Skip to content

Commit

Permalink
test: add tests for thrown errors
Browse files Browse the repository at this point in the history
  • Loading branch information
ComradeVanti committed Jul 5, 2024
1 parent 57de6f9 commit 680ba54
Show file tree
Hide file tree
Showing 12 changed files with 149 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const debugLog: DebugLog = (message, context) =>
const regClient = new RegClient({ log });
const getCwd = makeGetCwd();
const runChildProcess = makeRunChildProcess(debugLog);
const getHomePath = makeGetHomePath(debugLog);
const getHomePath = makeGetHomePath();
const readFile = makeReadText();
const writeFile = makeWriteText();
const loadProjectManifest = makeLoadProjectManifest(readFile, debugLog);
Expand Down
17 changes: 9 additions & 8 deletions src/io/builtin-packages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,20 @@ export function makeFindBuiltInPackages(
);

return (
resultifyAsyncOp<readonly string[], NodeJS.ErrnoException>(
tryGetDirectoriesIn(packagesDir)
)
resultifyAsyncOp(tryGetDirectoriesIn(packagesDir))
// We can assume correct format
.map((names) => names as DomainName[])
.mapErr((error) => {
assertIsNodeError(error);
debugLog(
"Failed to get directories in built-in package directory",
error
);
if (error.code === "ENOENT")

if (error.code === "ENOENT") {
debugLog(
"Failed to get directories in built-in package directory",
error
);
return new EditorNotInstalledError(editorVersion);
}

throw error;
})
);
Expand Down
3 changes: 1 addition & 2 deletions src/io/special-paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
} from "../domain/editor-version";
import { EditorVersionNotSupportedError } from "../common-errors";
import { tryGetEnv } from "../utils/env-util";
import { DebugLog } from "../logging";

/**
* Error for when a specific OS does not support a specific editor-version.
Expand Down Expand Up @@ -55,7 +54,7 @@ export class NoHomePathError extends CustomError {}
/**
* Makes a {@link GetHomePath} function.
*/
export function makeGetHomePath(debugLog: DebugLog): GetHomePath {
export function makeGetHomePath(): GetHomePath {
return () => {
const homePath = tryGetEnv("USERPROFILE") ?? tryGetEnv("HOME");
if (homePath === null) throw new NoHomePathError();
Expand Down
5 changes: 4 additions & 1 deletion src/services/remove-packages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ export function makeRemovePackages(

return (projectPath, packageNames) => {
// load manifest
const initialManifest = resultifyAsyncOp(loadProjectManifest(projectPath));
const initialManifest = resultifyAsyncOp<
UnityProjectManifest,
RemovePackagesError
>(loadProjectManifest(projectPath));

// remove
const removeResult = initialManifest.andThen((it) =>
Expand Down
12 changes: 7 additions & 5 deletions src/services/resolve-remote-packument-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import {
ResolvePackumentVersionError,
} from "../packument-version-resolving";
import { PackumentNotFoundError } from "../common-errors";
import { tryResolvePackumentVersion } from "../domain/packument";
import {
tryResolvePackumentVersion,
UnityPackument,
} from "../domain/packument";
import { FetchPackument } from "../io/packument-io";
import { resultifyAsyncOp } from "../utils/result-utils";

Expand All @@ -30,10 +33,9 @@ export function makeResolveRemotePackumentVersion(
fetchPackument: FetchPackument
): ResolveRemotePackumentVersion {
return (packageName, requestedVersion, source) =>
resultifyAsyncOp(fetchPackument(source, packageName)).andThen<
ResolvedPackumentVersion,
ResolvePackumentVersionError
>((packument) => {
resultifyAsyncOp<UnityPackument | null, ResolvePackumentVersionError>(
fetchPackument(source, packageName)
).andThen((packument) => {
if (packument === null)
return Err(new PackumentNotFoundError(packageName));
return tryResolvePackumentVersion(packument, requestedVersion).map(
Expand Down
2 changes: 1 addition & 1 deletion src/utils/result-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function AsyncErr<T>(error: T): AsyncResult<never, T> {
* Wraps a promise or operation returning a promise into an {@link AsyncResult}.
* @param op The operation to wrap.
*/
export function resultifyAsyncOp<T, TError = never>(
export function resultifyAsyncOp<T, TError>(
op: (() => Promise<T>) | Promise<T>
): AsyncResult<T, TError> {
return new AsyncResult(
Expand Down
61 changes: 59 additions & 2 deletions test/cli/cmd-add.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { makeAddCmd, UnresolvedDependenciesError } from "../../src/cli/cmd-add";
import {
CompatibilityCheckFailedError,
makeAddCmd,
PackageIncompatibleError,
UnresolvedDependenciesError,
} from "../../src/cli/cmd-add";
import { makeDomainName } from "../../src/domain/domain-name";
import { Env, ParseEnv } from "../../src/services/parse-env";
import { exampleRegistryUrl } from "../domain/data-registry";
Expand All @@ -17,10 +22,16 @@ import {
LoadProjectManifest,
WriteProjectManifest,
} from "../../src/io/project-manifest-io";
import { VersionNotFoundError } from "../../src/domain/packument";
import {
UnityPackumentVersion,
VersionNotFoundError,
} from "../../src/domain/packument";
import { noopLogger } from "../../src/logging";
import { DetermineEditorVersion } from "../../src/services/determine-editor-version";
import { ResultCodes } from "../../src/cli/result-codes";
import { AsyncErr, AsyncOk } from "../../src/utils/result-utils";
import { PackumentNotFoundError } from "../../src/common-errors";
import { ResolvedPackumentVersion } from "../../src/packument-version-resolving";

const somePackage = makeDomainName("com.some.package");
const otherPackage = makeDomainName("com.other.package");
Expand Down Expand Up @@ -161,6 +172,20 @@ describe("cmd-add", () => {
expect(resultCode).toEqual(ResultCodes.Ok);
});

it("should fail when adding package with incompatible with editor and not running with force", async () => {
const { addCmd, resolveRemovePackumentVersion } = makeDependencies();
mockResolvedPackuments(resolveRemovePackumentVersion, [
exampleRegistryUrl,
incompatiblePackument,
]);

await expect(
addCmd(somePackage, {
_global: {},
})
).rejects.toBeInstanceOf(PackageIncompatibleError);
});

it("should not fetch dependencies for upstream packages", async () => {
const { addCmd, resolveRemovePackumentVersion, resolveDependencies } =
makeDependencies();
Expand All @@ -176,6 +201,38 @@ describe("cmd-add", () => {
expect(resolveDependencies).not.toHaveBeenCalled();
});

it("should fail if package could not be resolved", async () => {
const { addCmd, resolveRemovePackumentVersion } = makeDependencies();
resolveRemovePackumentVersion.mockReturnValue(
AsyncErr(new PackumentNotFoundError(somePackage))
);

await expect(() =>
addCmd(somePackage, {
_global: {},
})
).rejects.toBeInstanceOf(PackumentNotFoundError);
});

it("should fail if packument had malformed target editor and not running with force", async () => {
const { addCmd, resolveRemovePackumentVersion } = makeDependencies();
resolveRemovePackumentVersion.mockReturnValue(
AsyncOk({
packumentVersion: {
name: somePackage,
version: makeSemanticVersion("1.0.0"),
unity: "bad vesion",
} as unknown as UnityPackumentVersion,
} as unknown as ResolvedPackumentVersion)
);

await expect(() =>
addCmd(somePackage, {
_global: {},
})
).rejects.toBeInstanceOf(CompatibilityCheckFailedError);
});

it("should fail if dependency could not be resolved and not running with force", async () => {
const { addCmd, resolveDependencies } = makeDependencies();
resolveDependencies.mockResolvedValue([
Expand Down
10 changes: 10 additions & 0 deletions test/cli/cmd-view.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { buildPackument } from "../domain/data-packument";
import { mockService } from "../services/service.mock";
import { ResultCodes } from "../../src/cli/result-codes";
import { FetchPackument } from "../../src/io/packument-io";
import { PackumentNotFoundError } from "../../src/common-errors";

const somePackage = makeDomainName("com.some.package");
const somePackument = buildPackument(somePackage, (packument) =>
Expand Down Expand Up @@ -78,6 +79,15 @@ describe("cmd-view", () => {
expect(resultCode).toEqual(ResultCodes.Error);
});

it("should fail if package is not found", async () => {
const { viewCmd, fetchPackument } = makeDependencies();
fetchPackument.mockResolvedValue(null);

await expect(viewCmd(somePackage, { _global: {} })).rejects.toBeInstanceOf(
PackumentNotFoundError
);
});

it("should notify if package version was specified", async () => {
const { viewCmd, log } = makeDependencies();

Expand Down
14 changes: 13 additions & 1 deletion test/io/builtin-packages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from "../../src/io/builtin-packages";
import { makeEditorVersion } from "../../src/domain/editor-version";
import { noopLogger } from "../../src/logging";
import { enoentError } from "./node-error.mock";
import { eaccesError, enoentError } from "./node-error.mock";

function makeDependencies() {
const getBuiltInPackages = makeFindBuiltInPackages(noopLogger);
Expand Down Expand Up @@ -42,6 +42,18 @@ describe("builtin-packages", () => {
expect(result).toBeError((actual) => expect(actual).toEqual(expected));
});

it("should fail if directory could not be read", async () => {
const version = makeEditorVersion(2022, 1, 2, "f", 1);
const { getBuiltInPackages } = makeDependencies();
const expected = eaccesError;
jest
.spyOn(specialPaths, "tryGetEditorInstallPath")
.mockReturnValue(Ok("/some/path"));
jest.spyOn(directoryIO, "tryGetDirectoriesIn").mockRejectedValue(expected);

await expect(getBuiltInPackages(version).promise).rejects.toEqual(expected);
});

it("should find package names", async () => {
const version = makeEditorVersion(2022, 1, 2, "f", 1);
const expected = ["com.unity.ugui", "com.unity.modules.uielements"];
Expand Down
22 changes: 21 additions & 1 deletion test/io/project-manifest-io.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {
makeLoadProjectManifest,
makeWriteProjectManifest,
ManifestMalformedError,
ManifestMissingError,
manifestPathFor,
} from "../../src/io/project-manifest-io";
import { mapScopedRegistry } from "../../src/domain/project-manifest";
Expand Down Expand Up @@ -41,7 +43,25 @@ describe("project-manifest io", () => {

await expect(
loadProjectManifest(exampleProjectPath)
).rejects.toBeDefined();
).rejects.toBeInstanceOf(ManifestMissingError);
});

it("should fail if manifest contains invalid json", async () => {
const { loadProjectManifest, readFile } = makeDependencies();
readFile.mockResolvedValue("not {} valid : json");

await expect(
loadProjectManifest(exampleProjectPath)
).rejects.toBeInstanceOf(ManifestMalformedError);
});

it("should fail if manifest contains invalid content", async () => {
const { loadProjectManifest, readFile } = makeDependencies();
readFile.mockResolvedValue(`123`);

await expect(
loadProjectManifest(exampleProjectPath)
).rejects.toBeInstanceOf(ManifestMalformedError);
});

it("should load valid manifest", async () => {
Expand Down
23 changes: 20 additions & 3 deletions test/io/project-version-io.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { ReadTextFile } from "../../src/io/text-file-io";
import { mockService } from "../services/service.mock";
import { makeLoadProjectVersion } from "../../src/io/project-version-io";
import {
makeLoadProjectVersion,
ProjectVersionMalformedError,
ProjectVersionMissingError,
} from "../../src/io/project-version-io";
import { noopLogger } from "../../src/logging";

describe("project-version-io", () => {
Expand All @@ -17,14 +21,27 @@ describe("project-version-io", () => {
const { loadProjectVersion, readFile } = makeDependencies();
readFile.mockResolvedValue(null);

await expect(loadProjectVersion("/some/bad/path")).rejects.toBeDefined();
await expect(loadProjectVersion("/some/bad/path")).rejects.toBeInstanceOf(
ProjectVersionMissingError
);
});

it("should fail if file does not contain valid yaml", async () => {
const { loadProjectVersion, readFile } = makeDependencies();
readFile.mockResolvedValue("this\\ is { not } : yaml");

await expect(loadProjectVersion("/some/path")).rejects.toBeInstanceOf(
ProjectVersionMalformedError
);
});

it("should fail if yaml does not contain editor-version", async () => {
const { loadProjectVersion, readFile } = makeDependencies();
readFile.mockResolvedValue("thisIsYaml: but not what we want");

await expect(loadProjectVersion("/some/path")).rejects.toBeDefined();
await expect(loadProjectVersion("/some/path")).rejects.toBeInstanceOf(
ProjectVersionMalformedError
);
});

it("should load valid version strings", async () => {
Expand Down
6 changes: 3 additions & 3 deletions test/io/special-paths.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ import path from "path";
import { tryGetEnv } from "../../src/utils/env-util";
import {
makeGetHomePath,
NoHomePathError,
OSNotSupportedError,
tryGetEditorInstallPath,
VersionNotSupportedOnOsError,
} from "../../src/io/special-paths";
import os from "os";
import { makeEditorVersion } from "../../src/domain/editor-version";
import { EditorVersionNotSupportedError } from "../../src/common-errors";
import { noopLogger } from "../../src/logging";

jest.mock("../../src/utils/env-util");

describe("special-paths", () => {
describe("home", () => {
function makeDependencies() {
const getHomePath = makeGetHomePath(noopLogger);
const getHomePath = makeGetHomePath();

return { getHomePath } as const;
}
Expand Down Expand Up @@ -49,7 +49,7 @@ describe("special-paths", () => {
const { getHomePath } = makeDependencies();
jest.mocked(tryGetEnv).mockReturnValue(null);

expect(() => getHomePath()).toThrow();
expect(() => getHomePath()).toThrow(NoHomePathError);
});
});

Expand Down

0 comments on commit 680ba54

Please sign in to comment.