Skip to content

Commit

Permalink
Test link command.
Browse files Browse the repository at this point in the history
  • Loading branch information
Neloreck committed Feb 13, 2024
1 parent 9ff51c3 commit de7e94f
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 0 deletions.
91 changes: 91 additions & 0 deletions cli/link/link.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import * as fsp from "fs/promises";

import { beforeAll, describe, expect, it, jest } from "@jest/globals";

import { ILinkCommandParameters, linkFolders } from "#/link/link";
import { getGamePaths } from "#/utils/fs/get_game_paths";

import { replaceFunctionMock } from "@/fixtures/jest";

jest.mock("fs/promises");
jest.mock("#/utils/fs/get_game_paths");

jest.mock("#/globals/paths", () => ({
TARGET_GAME_LINK_DIR: "game-path",
TARGET_LOGS_LINK_DIR: "logs-path",
TARGET_GAME_DATA_DIR: "target-gamedata-path",
}));

describe("unlinkFolders util", () => {
beforeAll(() => {
replaceFunctionMock(getGamePaths, async () => ({
gamedata: "gamedata-path",
root: "root-path",
logs: "logs-path",
}));
});

it("should correctly link folders with force flag", async () => {
jest.spyOn(fsp, "readlink").mockImplementation(async (target) => target as string);
jest.spyOn(fsp, "access").mockImplementation(async () => void 0);
jest.spyOn(fsp, "readlink").mockImplementation(async () => "test-link");

const parameters: ILinkCommandParameters = { force: true };

await linkFolders(parameters);

expect(fsp.rm).toHaveBeenCalledTimes(3);
expect(fsp.rm).toHaveBeenCalledWith("game-path", { recursive: true });
expect(fsp.rm).toHaveBeenCalledWith("gamedata-path", { recursive: true });
expect(fsp.rm).toHaveBeenCalledWith("logs-path", { recursive: true });

expect(fsp.symlink).toHaveBeenCalledTimes(3);
expect(fsp.symlink).toHaveBeenCalledWith("root-path", "game-path", "junction");
expect(fsp.symlink).toHaveBeenCalledWith("root-path", "game-path", "junction");
expect(fsp.symlink).toHaveBeenCalledWith("logs-path", "logs-path", "junction");
});

it("should correctly link folders without force flag", async () => {
jest.spyOn(fsp, "readlink").mockImplementation(async (target) => target as string);
jest.spyOn(fsp, "access").mockImplementation(() => Promise.reject());
jest.spyOn(fsp, "readlink").mockImplementation(async () => "test-link");

const parameters: ILinkCommandParameters = {};

await linkFolders(parameters);

expect(fsp.rm).toHaveBeenCalledTimes(0);

expect(fsp.symlink).toHaveBeenCalledTimes(3);
expect(fsp.symlink).toHaveBeenCalledWith("root-path", "game-path", "junction");
expect(fsp.symlink).toHaveBeenCalledWith("root-path", "game-path", "junction");
expect(fsp.symlink).toHaveBeenCalledWith("logs-path", "logs-path", "junction");
});

it("should skip link folders without force flag", async () => {
jest.spyOn(fsp, "readlink").mockImplementation(async (target) => target as string);
jest.spyOn(fsp, "access").mockImplementation(async () => void 0);
jest.spyOn(fsp, "readlink").mockImplementation(async () => "test-link");

const parameters: ILinkCommandParameters = {};

await linkFolders(parameters);

expect(fsp.rm).toHaveBeenCalledTimes(0);
expect(fsp.symlink).toHaveBeenCalledTimes(0);
});

it("should gracefully stop on error", async () => {
jest.spyOn(fsp, "readlink").mockImplementation(async (target) => target as string);
jest.spyOn(fsp, "access").mockImplementation(() => Promise.reject());
jest.spyOn(fsp, "readlink").mockImplementation(async () => "test-link");
jest.spyOn(fsp, "symlink").mockImplementationOnce(() => Promise.reject(new Error("Test.")));

const parameters: ILinkCommandParameters = {};

await expect(linkFolders(parameters)).resolves.not.toThrow();

expect(fsp.rm).toHaveBeenCalledTimes(0);
expect(fsp.symlink).toHaveBeenCalledTimes(1);
});
});
8 changes: 8 additions & 0 deletions cli/link/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export interface ILinkCommandParameters {

/**
* Link gamedata/engine/logs folders.
*
* @param parameters - command arguments
*/
export async function linkFolders(parameters: ILinkCommandParameters): Promise<void> {
log.info("Linking engine mod development folders");
Expand All @@ -39,6 +41,8 @@ export async function linkFolders(parameters: ILinkCommandParameters): Promise<v

/**
* Link target gamedata folder for faster / easier development
*
* @param parameters - command arguments
*/
async function linkGamedataFolders(parameters: ILinkCommandParameters): Promise<void> {
log.info("Linking gamedata folders");
Expand Down Expand Up @@ -77,6 +81,8 @@ async function linkGamedataFolders(parameters: ILinkCommandParameters): Promise<

/**
* Link game folder.
*
* @param parameters - command arguments
*/
async function linkGameFolder(parameters: ILinkCommandParameters): Promise<void> {
log.info("Linking game folders");
Expand All @@ -102,6 +108,8 @@ async function linkGameFolder(parameters: ILinkCommandParameters): Promise<void>

/**
* Link open-xray logs folder for easier check in project.
*
* @param parameters - command arguments
*/
async function linkLogsFolders(parameters: ILinkCommandParameters): Promise<void> {
log.info("Linking logs folders");
Expand Down
30 changes: 30 additions & 0 deletions cli/link/relink.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { describe, expect, it, jest } from "@jest/globals";

import { ILinkCommandParameters, linkFolders } from "#/link/link";
import { relinkFolders } from "#/link/relink";
import { unlinkFolders } from "#/link/unlink";

import { replaceFunctionMockOnce } from "@/fixtures/jest";

jest.mock("#/link/link");
jest.mock("#/link/unlink");

describe("relinkFolders util", () => {
it("should correctly relink existing files", async () => {
const parameters: ILinkCommandParameters = {};

await relinkFolders(parameters);

expect(unlinkFolders).toHaveBeenCalledTimes(1);
expect(linkFolders).toHaveBeenCalledTimes(1);
expect(linkFolders).toHaveBeenCalledWith(parameters);
});

it("should gracefully handle errors", async () => {
replaceFunctionMockOnce(unlinkFolders, async () => Promise.reject(new Error("Test.")));

const parameters: ILinkCommandParameters = {};

await expect(relinkFolders(parameters)).resolves.not.toThrow();
});
});
2 changes: 2 additions & 0 deletions cli/link/relink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export interface IRelinkCommandParameters {

/**
* Re-link gamedata/engine/logs folders.
*
* @param parameters - command arguments
*/
export async function relinkFolders(parameters: IRelinkCommandParameters): Promise<void> {
log.info("Performing relink");
Expand Down
49 changes: 49 additions & 0 deletions cli/link/unlink.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import * as fsp from "fs/promises";

import { beforeAll, describe, expect, it, jest } from "@jest/globals";

import { unlinkFolders } from "#/link/unlink";
import { getGamePaths } from "#/utils/fs/get_game_paths";

import { replaceFunctionMock } from "@/fixtures/jest";

jest.mock("fs/promises");
jest.mock("#/utils/fs/get_game_paths");

jest.mock("#/globals/paths", () => ({
TARGET_GAME_LINK_DIR: "game-path",
TARGET_LOGS_LINK_DIR: "logs-path",
}));

describe("unlinkFolders util", () => {
beforeAll(() => {
replaceFunctionMock(getGamePaths, async () => ({ gamedata: "gamedata-path" }));
});

it("should correctly unlink existing files", async () => {
jest.spyOn(fsp, "readlink").mockImplementation(async (target) => target as string);

await unlinkFolders();

expect(fsp.unlink).toHaveBeenCalledTimes(3);
expect(fsp.unlink).toHaveBeenCalledWith("gamedata-path");
expect(fsp.unlink).toHaveBeenCalledWith("logs-path");
expect(fsp.unlink).toHaveBeenCalledWith("game-path");
});

it("should correctly unlink existing files", async () => {
jest.spyOn(fsp, "readlink").mockImplementation(() => Promise.reject("Test."));

await unlinkFolders();

expect(fsp.unlink).toHaveBeenCalledTimes(0);
});

it("should gracefully handle unlink errors", async () => {
jest.spyOn(fsp, "readlink").mockImplementation(async (target) => target as string);
jest.spyOn(fsp, "unlink").mockImplementation(() => Promise.reject(new Error("Test.")));

await expect(unlinkFolders()).resolves.not.toThrow();
expect(fsp.unlink).toHaveBeenCalledTimes(1);
});
});

0 comments on commit de7e94f

Please sign in to comment.