diff --git a/test/content/fabric/fabric.mod.json b/test/content/fabric/fabric.mod.json deleted file mode 100644 index 197eef5..0000000 --- a/test/content/fabric/fabric.mod.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "schemaVersion": 1, - "id": "example-mod", - "version": "0.1.0", - "name": "Example Mod", - "description": "Description", - "authors": [ - "Author" - ], - "contact": { - "homepage": "https://github.com/", - "sources": "https://github.com/" - }, - "license": "MIT", - "icon": "assets/example-mod/icon.png", - "environment": "*", - "entrypoints": { - "main": [ - "example.ExampleMod" - ] - }, - "mixins": [ - "example-mod.mixins.json" - ], - - "custom": { - "modmanager": { - "modrinth": "AANobbMI" - }, - "projects": { - "curseforge": 394468 - }, - "mc-publish": { - "github": "mc1.18-0.4.0-alpha5" - } - }, - - "depends": { - "fabricloader": ">=0.11.3", - "fabric": ">=0.40.0", - "minecraft": [ - "1.17", - "1.17.1" - ], - "java": ">=16" - }, - "recommends": { - "recommended-mod": { - "version": "0.2.0", - "custom": { - "mc-publish": { - "modrinth": "AAAA", - "curseforge": 42, - "github": "v0.2.0", - "ignore": true - } - } - } - }, - "includes": { - "included-mod": "*" - }, - "suggests": { - "suggested-mod": "*" - }, - "conflicts": { - "conflicting-mod": "<0.40.0" - }, - "breaks": { - "breaking-mod": "*" - } - } \ No newline at end of file diff --git a/test/content/forge/mods.toml b/test/content/forge/mods.toml deleted file mode 100644 index 01c3140..0000000 --- a/test/content/forge/mods.toml +++ /dev/null @@ -1,71 +0,0 @@ -modLoader="javafml" -loaderVersion="[34,)" -issueTrackerURL="https://github.com/" -displayURL="https://github.com/" -authors="Author" -license="MIT" - -[[mods]] - modId="example-mod" - version="0.1.0" - displayName="Example Mod" - description=''' - Example mod - ''' - -[mc-publish] - modrinth="AANobbMI" -[custom.projects] - curseforge=394468 -[custom.mc-publish] - github="mc1.18-0.4.0-alpha5" - -[[dependencies.example-mod]] - modId="minecraft" - mandatory=true - versionRange="[1.17, 1.18)" - side="BOTH" - -[[dependencies.example-mod]] - modId="forge" - mandatory=true - versionRange="[34,)" - ordering="NONE" - side="BOTH" - -[[dependencies.example-mod]] - modId="java" - mandatory=true - versionRange="[16,)" - ordering="NONE" - side="BOTH" - -[[dependencies.example-mod]] - modId="recommended-mod" - mandatory=false - versionRange="0.2.0" - ordering="NONE" - side="BOTH" - [dependencies.example-mod.mc-publish] - modrinth="AAAA" - curseforge=42 - ignore=true - [dependencies.example-mod.custom.mc-publish] - github="v0.2.0" - - -[[dependencies.example-mod]] - modId="included-mod" - mandatory=false - embedded=true - versionRange="[0.40.0, )" - ordering="NONE" - side="BOTH" - -[[dependencies.example-mod]] - modId="breaking-mod" - mandatory=false - incompatible=true - versionRange="*" - ordering="NONE" - side="BOTH" diff --git a/test/content/quilt/quilt.mod.json b/test/content/quilt/quilt.mod.json deleted file mode 100644 index 0d930ff..0000000 --- a/test/content/quilt/quilt.mod.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "schema_version": 1, - "quilt_loader": { - "group": "com.example", - "id": "example-mod", - "version": "0.1.0", - "name": "Example Mod", - "description": "Description", - "authors": [ - "Author" - ], - "contact": { - "homepage": "https://github.com/", - "sources": "https://github.com/", - "issues": "https://github.com/", - "wiki": "https://github.com/" - }, - "license": "MIT", - "icon": "icon.jpg", - "intermediate_mappings": "net.fabricmc:intermediary", - "environment": "*", - "entrypoints": { - "main": [ - "example.ExampleMod" - ] - }, - "depends": [ - { - "id": "quilt_loader", - "versions": ">=0.11.3" - }, - { - "id": "quilt_base", - "versions": ">=0.40.0" - }, - { - "id": "minecraft", - "versions": [ - "1.17", - "1.17.1" - ] - }, - { - "id": "java", - "versions": ">=16" - }, - { - "id": "recommended-mod", - "versions": "0.2.0", - "optional": true, - "mc-publish": { - "curseforge": 42, - "github": "v0.2.0", - "modrinth": "AAAA", - "ignore": true - } - } - ], - "provides": [ - "included:included-mod" - ], - "breaks": [ - "breaking-mod", - { - "id": "conflicting:conflicting-mod", - "versions": "<0.40.0", - "unless": "fix-conflicting-mod" - } - ] - }, - "mc-publish": { - "github": "mc1.18-0.4.0-alpha5", - "modrinth": "AANobbMI" - }, - "projects": { - "curseforge": 394468 - }, - "mixins": [ - "example-mod.mixins.json" - ], - "access_widener": "example.accesswidener" -} diff --git a/test/unit-tests/metadata/dependency-kind.test.ts b/test/unit-tests/metadata/dependency-kind.test.ts deleted file mode 100644 index b1d1ad6..0000000 --- a/test/unit-tests/metadata/dependency-kind.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { describe, test, expect } from "@jest/globals"; -import DependencyKind from "../../../src/metadata/dependency-kind"; - -describe("DependencyKind.getValues", () => { - test("all DependencyKind values are returned", () => { - const kinds = DependencyKind.getValues(); - expect(kinds).toHaveLength(6); - expect(kinds).toContain(DependencyKind.Depends); - expect(kinds).toContain(DependencyKind.Recommends); - expect(kinds).toContain(DependencyKind.Includes); - expect(kinds).toContain(DependencyKind.Suggests); - expect(kinds).toContain(DependencyKind.Conflicts); - expect(kinds).toContain(DependencyKind.Breaks); - }); -}); - -describe("DependencyKind.parse", () => { - test("every DependencyKind can be parsed", () => { - for (const kind of DependencyKind.getValues()) { - expect(DependencyKind.parse(DependencyKind.toString(kind))).toStrictEqual(kind); - } - }); - - test("DependencyKind's name is case-insensitive", () => { - for (const kind of DependencyKind.getValues()) { - expect(DependencyKind.parse(DependencyKind.toString(kind).toLowerCase())).toStrictEqual(kind); - expect(DependencyKind.parse(DependencyKind.toString(kind).toUpperCase())).toStrictEqual(kind); - } - }); - - test("undefined is returned when the value cannot be parsed", () => { - expect(DependencyKind.parse("There's no such dependency kind")).toBeUndefined(); - }); -}); \ No newline at end of file diff --git a/test/unit-tests/metadata/mod-metadata-reader-factory.test.ts b/test/unit-tests/metadata/mod-metadata-reader-factory.test.ts deleted file mode 100644 index a13e457..0000000 --- a/test/unit-tests/metadata/mod-metadata-reader-factory.test.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { describe, test, expect } from "@jest/globals"; -import ModLoaderType from "../../../src/metadata/mod-loader-type"; -import ModMetadataReaderFactory from "../../../src/metadata/mod-metadata-reader-factory"; - -describe("ModMetadataReaderFactory.create", () => { - test("factory can create metadata reader for every ModLoaderType value", () => { - const factory = new ModMetadataReaderFactory(); - for (const target of ModLoaderType.getValues()) { - const reader = factory.create(target); - expect(reader).toHaveProperty("readMetadata"); - } - }); - - test("the method throws on invalid ModLoaderType value", () => { - const factory = new ModMetadataReaderFactory(); - expect(() => factory.create(-1)).toThrow(); - }); -}); diff --git a/test/unit-tests/metadata/mod-metadata-reader.test.ts b/test/unit-tests/metadata/mod-metadata-reader.test.ts deleted file mode 100644 index 060baac..0000000 --- a/test/unit-tests/metadata/mod-metadata-reader.test.ts +++ /dev/null @@ -1,277 +0,0 @@ -import { describe, test, expect, beforeAll, afterAll } from "@jest/globals"; -import Dependency from "../../../src/metadata/dependency"; -import DependencyKind from "../../../src/metadata/dependency-kind"; -import ModMetadataReader from "../../../src/metadata/mod-metadata-reader"; -import PublisherTarget from "../../../src/publishing/publisher-target"; -import { ZipFile } from "yazl"; -import fs from "fs"; - -describe("ModMetadataReader.readMetadata", () => { - describe("Fabric", () => { - beforeAll(() => new Promise(resolve => { - const zip = new ZipFile(); - zip.addFile("./test/content/fabric/fabric.mod.json", "fabric.mod.json"); - zip.end(); - zip.outputStream.pipe(fs.createWriteStream("example-mod.fabric.jar")).on("close", resolve); - })); - - afterAll(() => new Promise(resolve => fs.unlink("example-mod.fabric.jar", resolve))); - - test("the format can be read", async () => { - const metadata = await ModMetadataReader.readMetadata("example-mod.fabric.jar"); - expect(metadata).toBeTruthy(); - }); - - test("mod info can be read", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!; - expect(metadata.id).toBe("example-mod"); - expect(metadata.name).toBe("Example Mod"); - expect(metadata.version).toBe("0.1.0"); - expect(metadata.loaders).toMatchObject(["fabric"] as any); - }); - - test("project ids can be specified in the config file", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!; - expect(metadata.getProjectId(PublisherTarget.Modrinth)).toBe("AANobbMI"); - expect(metadata.getProjectId(PublisherTarget.CurseForge)).toBe("394468"); - expect(metadata.getProjectId(PublisherTarget.GitHub)).toBe("mc1.18-0.4.0-alpha5"); - }); - - test("all dependencies are read", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!; - expect(metadata.dependencies).toHaveLength(9); - const dependencies = metadata.dependencies.reduce((agg, x) => { agg[x.id] = x; return agg; }, >{}); - expect(dependencies["fabricloader"]?.kind).toBe(DependencyKind.Depends); - expect(dependencies["fabric"]?.kind).toBe(DependencyKind.Depends); - expect(dependencies["minecraft"]?.kind).toBe(DependencyKind.Depends); - expect(dependencies["java"]?.kind).toBe(DependencyKind.Depends); - expect(dependencies["recommended-mod"]?.kind).toBe(DependencyKind.Recommends); - expect(dependencies["included-mod"]?.kind).toBe(DependencyKind.Includes); - expect(dependencies["suggested-mod"]?.kind).toBe(DependencyKind.Suggests); - expect(dependencies["conflicting-mod"]?.kind).toBe(DependencyKind.Conflicts); - expect(dependencies["breaking-mod"]?.kind).toBe(DependencyKind.Breaks); - }); - - test("dependency info can be read", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!; - const conflicting = metadata.dependencies.find(x => x.id === "conflicting-mod")!; - expect(conflicting).toBeTruthy(); - expect(conflicting.id).toBe("conflicting-mod"); - expect(conflicting.kind).toBe(DependencyKind.Conflicts); - expect(conflicting.version).toBe("<0.40.0"); - expect(conflicting.ignore).toBe(false); - for (const project of PublisherTarget.getValues()) { - expect(conflicting.getProjectSlug(project)).toBe(conflicting.id); - } - }); - - test("version array is supported", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!; - const minecraft = metadata.dependencies.find(x => x.id === "minecraft"); - expect(minecraft.version).toStrictEqual("1.17 || 1.17.1"); - }); - - test("custom metadata can be attached to dependency entry", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!; - const recommended = metadata.dependencies.find(x => x.id === "recommended-mod")!; - expect(recommended).toBeTruthy(); - expect(recommended.id).toBe("recommended-mod"); - expect(recommended.kind).toBe(DependencyKind.Recommends); - expect(recommended.version).toBe("0.2.0"); - expect(recommended.ignore).toBe(true); - expect(recommended.getProjectSlug(PublisherTarget.Modrinth)).toBe("AAAA"); - expect(recommended.getProjectSlug(PublisherTarget.CurseForge)).toBe("42"); - expect(recommended.getProjectSlug(PublisherTarget.GitHub)).toBe("v0.2.0"); - }); - - test("special case dependencies (minecraft, java and fabricloader) are ignored by default", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!; - expect(metadata.dependencies.find(x => x.id === "minecraft")!.ignore).toBe(true); - expect(metadata.dependencies.find(x => x.id === "java")!.ignore).toBe(true); - expect(metadata.dependencies.find(x => x.id === "fabricloader")!.ignore).toBe(true); - }); - - test("special case dependencies (fabric) are replaced with their aliases", async() => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.fabric.jar"))!; - const fabric = metadata.dependencies.find(x => x.id === "fabric")!; - for (const target of PublisherTarget.getValues()) { - expect(fabric.getProjectSlug(target) === "fabric-api"); - } - }); - }); - - describe("Forge", () => { - beforeAll(() => new Promise(resolve => { - const zip = new ZipFile(); - zip.addFile("./test/content/forge/mods.toml", "META-INF/mods.toml"); - zip.end(); - zip.outputStream.pipe(fs.createWriteStream("example-mod.forge.jar")).on("close", resolve); - })); - - afterAll(() => new Promise(resolve => fs.unlink("example-mod.forge.jar", resolve))); - - test("the format can be read", async () => { - const metadata = await ModMetadataReader.readMetadata("example-mod.forge.jar"); - expect(metadata).toBeTruthy(); - }); - - test("mod info can be read", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.forge.jar"))!; - expect(metadata.id).toBe("example-mod"); - expect(metadata.name).toBe("Example Mod"); - expect(metadata.version).toBe("0.1.0"); - expect(metadata.loaders).toMatchObject(["forge"] as any); - }); - - test("project ids can be specified in the config file", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.forge.jar"))!; - expect(metadata.getProjectId(PublisherTarget.Modrinth)).toBe("AANobbMI"); - expect(metadata.getProjectId(PublisherTarget.CurseForge)).toBe("394468"); - expect(metadata.getProjectId(PublisherTarget.GitHub)).toBe("mc1.18-0.4.0-alpha5"); - }); - - test("all dependencies are read", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.forge.jar"))!; - expect(metadata.dependencies).toHaveLength(6); - const dependencies = metadata.dependencies.reduce((agg, x) => { agg[x.id] = x; return agg; }, >{}); - expect(dependencies["forge"]?.kind).toBe(DependencyKind.Depends); - expect(dependencies["minecraft"]?.kind).toBe(DependencyKind.Depends); - expect(dependencies["java"]?.kind).toBe(DependencyKind.Depends); - expect(dependencies["recommended-mod"]?.kind).toBe(DependencyKind.Recommends); - expect(dependencies["included-mod"]?.kind).toBe(DependencyKind.Includes); - expect(dependencies["breaking-mod"]?.kind).toBe(DependencyKind.Breaks); - }); - - test("dependency info can be read", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.forge.jar"))!; - const included = metadata.dependencies.find(x => x.id === "included-mod")!; - expect(included).toBeTruthy(); - expect(included.id).toBe("included-mod"); - expect(included.kind).toBe(DependencyKind.Includes); - expect(included.version).toBe("[0.40.0, )"); - expect(included.ignore).toBe(false); - for (const project of PublisherTarget.getValues()) { - expect(included.getProjectSlug(project)).toBe(included.id); - } - }); - - test("custom metadata can be attached to dependency entry", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.forge.jar"))!; - const recommended = metadata.dependencies.find(x => x.id === "recommended-mod")!; - expect(recommended).toBeTruthy(); - expect(recommended.id).toBe("recommended-mod"); - expect(recommended.kind).toBe(DependencyKind.Recommends); - expect(recommended.version).toBe("0.2.0"); - expect(recommended.ignore).toBe(true); - expect(recommended.getProjectSlug(PublisherTarget.Modrinth)).toBe("AAAA"); - expect(recommended.getProjectSlug(PublisherTarget.CurseForge)).toBe("42"); - expect(recommended.getProjectSlug(PublisherTarget.GitHub)).toBe("v0.2.0"); - }); - - test("special case dependencies (minecraft, java and forge) are ignored by default", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.forge.jar"))!; - expect(metadata.dependencies.find(x => x.id === "minecraft")!.ignore).toBe(true); - expect(metadata.dependencies.find(x => x.id === "java")!.ignore).toBe(true); - expect(metadata.dependencies.find(x => x.id === "forge")!.ignore).toBe(true); - }); - }); - - describe("Quilt", () => { - beforeAll(() => new Promise(resolve => { - const zip = new ZipFile(); - zip.addFile("./test/content/quilt/quilt.mod.json", "quilt.mod.json"); - zip.end(); - zip.outputStream.pipe(fs.createWriteStream("example-mod.quilt.jar")).on("close", resolve); - })); - - afterAll(() => new Promise(resolve => fs.unlink("example-mod.quilt.jar", resolve))); - - test("the format can be read", async () => { - const metadata = await ModMetadataReader.readMetadata("example-mod.quilt.jar"); - expect(metadata).toBeTruthy(); - }); - - test("mod info can be read", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!; - expect(metadata.id).toBe("example-mod"); - expect(metadata.name).toBe("Example Mod"); - expect(metadata.version).toBe("0.1.0"); - expect(metadata.loaders).toMatchObject(["quilt"] as any); - }); - - test("project ids can be specified in the config file", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!; - expect(metadata.getProjectId(PublisherTarget.Modrinth)).toBe("AANobbMI"); - expect(metadata.getProjectId(PublisherTarget.CurseForge)).toBe("394468"); - expect(metadata.getProjectId(PublisherTarget.GitHub)).toBe("mc1.18-0.4.0-alpha5"); - }); - - test("all dependencies are read", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!; - expect(metadata.dependencies).toHaveLength(8); - const dependencies = metadata.dependencies.reduce((agg, x) => { agg[x.id] = x; return agg; }, >{}); - expect(dependencies["quilt_loader"]?.kind).toBe(DependencyKind.Depends); - expect(dependencies["quilt_base"]?.kind).toBe(DependencyKind.Depends); - expect(dependencies["minecraft"]?.kind).toBe(DependencyKind.Depends); - expect(dependencies["java"]?.kind).toBe(DependencyKind.Depends); - expect(dependencies["recommended-mod"]?.kind).toBe(DependencyKind.Recommends); - expect(dependencies["included-mod"]?.kind).toBe(DependencyKind.Includes); - expect(dependencies["conflicting-mod"]?.kind).toBe(DependencyKind.Conflicts); - expect(dependencies["breaking-mod"]?.kind).toBe(DependencyKind.Breaks); - }); - - test("dependency info can be read", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!; - const conflicting = metadata.dependencies.find(x => x.id === "conflicting-mod")!; - expect(conflicting).toBeTruthy(); - expect(conflicting.id).toBe("conflicting-mod"); - expect(conflicting.kind).toBe(DependencyKind.Conflicts); - expect(conflicting.version).toBe("<0.40.0"); - expect(conflicting.ignore).toBe(false); - for (const project of PublisherTarget.getValues()) { - expect(conflicting.getProjectSlug(project)).toBe(conflicting.id); - } - }); - - test("version array is supported", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!; - const minecraft = metadata.dependencies.find(x => x.id === "minecraft"); - expect(minecraft.version).toStrictEqual("1.17 || 1.17.1"); - }); - - test("custom metadata can be attached to dependency entry", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!; - const recommended = metadata.dependencies.find(x => x.id === "recommended-mod")!; - expect(recommended).toBeTruthy(); - expect(recommended.id).toBe("recommended-mod"); - expect(recommended.kind).toBe(DependencyKind.Recommends); - expect(recommended.version).toBe("0.2.0"); - expect(recommended.ignore).toBe(true); - expect(recommended.getProjectSlug(PublisherTarget.Modrinth)).toBe("AAAA"); - expect(recommended.getProjectSlug(PublisherTarget.CurseForge)).toBe("42"); - expect(recommended.getProjectSlug(PublisherTarget.GitHub)).toBe("v0.2.0"); - }); - - test("special case dependencies (minecraft, java and quilt_loader) are ignored by default", async () => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!; - expect(metadata.dependencies.find(x => x.id === "minecraft")!.ignore).toBe(true); - expect(metadata.dependencies.find(x => x.id === "java")!.ignore).toBe(true); - expect(metadata.dependencies.find(x => x.id === "quilt_loader")!.ignore).toBe(true); - }); - - test("special case dependencies (quilted_quilt_api) are replaced with their aliases", async() => { - const metadata = (await ModMetadataReader.readMetadata("example-mod.quilt.jar"))!; - const quilt = metadata.dependencies.find(x => x.id === "quilt_base")!; - for (const target of PublisherTarget.getValues()) { - expect(quilt.getProjectSlug(target) === "qsl"); - } - }); - }); - - describe("unsupported mod formats", () => { - test("null is returned when the format is not supported or specified file does not exist", async () => { - const metadata = await ModMetadataReader.readMetadata("example-mod.unknown.jar"); - expect(metadata).toBeNull(); - }); - }); -}); diff --git a/test/unit-tests/publishing/publisher-factory.test.ts b/test/unit-tests/publishing/publisher-factory.test.ts deleted file mode 100644 index b56c964..0000000 --- a/test/unit-tests/publishing/publisher-factory.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { describe, test, expect } from "@jest/globals"; -import PublisherFactory from "../../../src/publishing/publisher-factory"; -import PublisherTarget from "../../../src/publishing/publisher-target"; -import { getConsoleLogger } from "../../../src/utils/logging/logger"; - -describe("PublisherFactory.create", () => { - test("factory can create publisher for every PublisherTarget value", () => { - const factory = new PublisherFactory(); - for (const target of PublisherTarget.getValues()) { - const logger = getConsoleLogger(); - const publisher = factory.create(target, logger); - expect(publisher.target).toStrictEqual(target); - expect((publisher as any).logger).toStrictEqual(logger); - } - }); - - test("every publisher has logger object", () => { - const factory = new PublisherFactory(); - for (const target of PublisherTarget.getValues()) { - const publisher = factory.create(target); - expect(publisher.target).toStrictEqual(target); - expect((publisher as any).logger).toBeTruthy(); - } - }); - - test("the method throws on invalid PublisherTarget value", () => { - const factory = new PublisherFactory(); - expect(() => factory.create(-1)).toThrow(); - }); -}); diff --git a/test/unit-tests/utils/actions/input.test.ts b/test/unit-tests/utils/actions/input.test.ts deleted file mode 100644 index 9aacb6a..0000000 --- a/test/unit-tests/utils/actions/input.test.ts +++ /dev/null @@ -1,253 +0,0 @@ -import { describe, test, expect, beforeAll, afterAll } from "@jest/globals"; -import { setupInput, unsetInput } from "../../../utils/input-utils"; -import { getInputAsObject, mapStringInput, mapObjectInput, mapNumberInput, mapBooleanInput, mapEnumInput } from "../../../../src/utils/actions/input"; - -const defaultInput = { - "boolean": true, - "object": { foo: "bar" }, - "number": 1, - "array": ["foo", "bar"], - "undefined": "${undefined}", - - "files-primary": "primaryPath", - "files-secondary": "secondaryPath", - "files-secondary-inner": "innerSecondaryPath", - "files": "path", - - "modrinth-id": 42, - "modrinth-token": "1234", - "modrinth-files-primary": "primaryPath", - "modrinth-files-secondary": "secondaryPath", - - "This is a Very--Long_Name!": "foo" -}; - -describe("getInputAsObject", () => { - beforeAll(() => setupInput(defaultInput)); - afterAll(() => unsetInput()); - - test("input object contains only strings", () => { - const input = getInputAsObject(); - expect(input).toHaveProperty("boolean", "true"); - expect(input).toHaveProperty("object", {}.toString()); - expect(input).not.toHaveProperty("object.foo"); - expect(input).toHaveProperty("number", "1"); - expect(input).toHaveProperty("array", ["foo", "bar"].toString()); - }); - - test("property names are converted to paths inside of the input object (a-b -> a.b and aB)", () => { - const input = getInputAsObject(); - expect(input).toHaveProperty("modrinth.id", "42"); - expect(input).toHaveProperty("modrinthId", "42"); - - expect(input).toHaveProperty("modrinth.token", "1234"); - expect(input).toHaveProperty("modrinthToken", "1234"); - - expect(input).toHaveProperty("modrinth.files.primary", "primaryPath"); - expect(input).toHaveProperty("modrinth.filesPrimary", "primaryPath"); - expect(input).toHaveProperty("modrinthFilesPrimary", "primaryPath"); - - expect(input).toHaveProperty("modrinth.files.secondary", "secondaryPath"); - expect(input).toHaveProperty("modrinth.filesSecondary", "secondaryPath"); - expect(input).toHaveProperty("modrinthFilesSecondary", "secondaryPath"); - }); - - test("string values do not have additional properties", () => { - const input = getInputAsObject(); - expect(input).toHaveProperty("files", "path"); - expect(input).toHaveProperty("filesPrimary", "primaryPath"); - expect(input).toHaveProperty("filesSecondary", "secondaryPath"); - expect(input).toHaveProperty("filesSecondaryInner", "innerSecondaryPath"); - expect(input).not.toHaveProperty("files.primary"); - expect(input).not.toHaveProperty("files.secondary"); - }); - - test("input object does not have empty property names", () => { - const input = getInputAsObject(); - expect(input).toHaveProperty("this.is.a.very.long.name", "foo"); - expect(input).toHaveProperty("thisIsAVeryLongName", "foo"); - }); - - test("special case for GitHub Actions: ${undefined} transforms into undefined", () => { - const input = getInputAsObject(); - expect(input.undefined).toBeUndefined(); - }); -}); - -describe("mapStringInput", () => { - beforeAll(() => setupInput(defaultInput)); - afterAll(() => unsetInput()); - - test("returns default value if input is not a string", () => { - const input = getInputAsObject(); - - expect(input["undefined"]).toBeUndefined(); - expect(mapStringInput(input["undefined"], "42")).toBe("42"); - }); - - test("maps strings to string", () => { - const input = getInputAsObject(); - expect(mapStringInput(input["boolean"], "")).toBe("true"); - expect(mapStringInput(input["number"], "")).toBe("1"); - expect(mapStringInput(input["object"])).toBe({}.toString()); - }); -}); - -describe("mapObjectInput", () => { - beforeAll(() => setupInput(defaultInput)); - afterAll(() => unsetInput()); - - test("returns default value if input is not an object", () => { - const input = getInputAsObject(); - - expect(input["boolean"]).not.toBeUndefined(); - expect(mapObjectInput(input["boolean"], null!)).toBeNull(); - - expect(input["number"]).not.toBeUndefined(); - expect(mapObjectInput(input["number"], null!)).toBeNull() - - expect(input["array"]).not.toBeUndefined(); - expect(mapObjectInput(input["array"])).toBeNull() - - expect(input["undefined"]).toBeUndefined(); - expect(mapObjectInput(input["undefined"], { answer: 42 })).toStrictEqual({ answer: 42 }); - }); - - test("maps object values to object", () => { - const input = getInputAsObject(); - expect(mapObjectInput(input["modrinth"], null!)).toStrictEqual({ id: "42", token: "1234", filesPrimary: "primaryPath", filesSecondary: "secondaryPath", files: { primary: "primaryPath", secondary: "secondaryPath" } }); - }); -}); - -describe("mapNumberInput", () => { - beforeAll(() => setupInput({ - ...defaultInput, - numberOne: 1, - numberOneString: "1", - numberOneStringWithWhitespace: " 1 ", - })); - afterAll(() => unsetInput()); - - test("returns default value if input is not number or number-like", () => { - const input = getInputAsObject(); - - expect(input["boolean"]).not.toBeUndefined(); - expect(mapNumberInput(input["boolean"], 0)).toBe(0); - - expect(input["object"]).not.toBeUndefined(); - expect(mapNumberInput(input["object"], 0)).toBe(0); - - expect(input["array"]).not.toBeUndefined(); - expect(mapNumberInput(input["array"], 0)).toBe(0); - - expect(input["undefined"]).toBeUndefined(); - expect(mapNumberInput(input["undefined"], 1)).toBe(1); - }); - - test("maps number and number-like values to number", () => { - const input = getInputAsObject(); - - expect(mapNumberInput(input["numberone"], 0)).toBe(1); - expect(mapNumberInput(input["numberonestring"], 0)).toBe(1); - expect(mapNumberInput(input["numberonestringwithwhitespace"])).toBe(1); - }); -}); - -describe("mapBooleanInput", () => { - beforeAll(() => setupInput({ - ...defaultInput, - booleanTrue: true, - booleanTrueStringLowerCase: "true", - booleanTrueStringUpperCase: "TRUE", - booleanTrueStringUpperCaseWithWhitespace: " TRUE ", - booleanFalse: false, - booleanFalseStringLowerCase: "false", - booleanFalseStringUpperCase: "FALSE", - booleanFalseStringUpperCaseWithWhitespace: " FALSE ", - })); - afterAll(() => unsetInput()); - - test("returns default value if input is not boolean or boolean-like", () => { - const input = getInputAsObject(); - - expect(input["object"]).not.toBeUndefined(); - expect(mapBooleanInput(input["object"], false)).toBe(false); - - expect(input["number"]).not.toBeUndefined(); - expect(mapBooleanInput(input["number"], false)).toBe(false); - - expect(input["array"]).not.toBeUndefined(); - expect(mapBooleanInput(input["array"], false)).toBe(false); - - expect(input["undefined"]).toBeUndefined(); - expect(mapBooleanInput(input["undefined"], true)).toBe(true); - }); - - test("maps boolean and boolean-like values to boolean", () => { - const input = getInputAsObject(); - expect(mapBooleanInput(input["booleantrue"], false)).toBe(true); - expect(mapBooleanInput(input["booleantruestringlowercase"], false)).toBe(true); - expect(mapBooleanInput(input["booleantruestringuppercase"], false)).toBe(true); - expect(mapBooleanInput(input["booleantruestringuppercasewithwhitespace"])).toBe(true); - expect(mapBooleanInput(input["booleanfalse"], true)).toBe(false); - expect(mapBooleanInput(input["booleanfalsestringlowercase"], true)).toBe(false); - expect(mapBooleanInput(input["booleanfalsestringuppercase"], true)).toBe(false); - expect(mapBooleanInput(input["booleanfalsestringuppercasewithwhitespace"], true)).toBe(false); - }); -}); - -describe("mapEnumInput", () => { - enum TestEnum { - None = 0, - - A = 1, - B = 2, - C = 4, - - A_B = 1 | 2, - A_C = 1 | 4, - B_C = 2 | 4, - - A_B_C = 1 | 2 | 4, - } - - beforeAll(() => setupInput({ - ...defaultInput, - enumAB: TestEnum.A_B, - enumABStringUpperCase: "A_B", - enumABStringLowerCase: "a_b", - enumABStringLowerCaseWithWhitespace: " a_b ", - enumABStringLowerCaseWithWhitespaceAndDifferentSeparator: " a-b ", - - enumABStringLowerCaseWithWhitespaceBitwise: " a | b ", - enumABCStringLowerCaseWithWhitespaceBitwise: " c | b | b | a ", - })); - afterAll(() => unsetInput()); - - test("returns default value if input cannot be casted to the given enum", () => { - const input = getInputAsObject(); - - expect(input["object"]).not.toBeUndefined(); - expect(mapEnumInput(input["object"], TestEnum)).toBeNull(); - - expect(input["boolean"]).not.toBeUndefined(); - expect(mapEnumInput(input["boolean"], TestEnum)).toBeNull(); - - expect(input["array"]).not.toBeUndefined(); - expect(mapEnumInput(input["array"], TestEnum)).toBeNull(); - - expect(input["undefined"]).toBeUndefined(); - expect(mapEnumInput(input["undefined"], TestEnum, TestEnum.A_B_C)).toBe(TestEnum.A_B_C); - }); - - test("maps values to the given enum", () => { - const input = getInputAsObject(); - expect(mapEnumInput(input["enumab"], TestEnum)).toBe(TestEnum.A_B); - expect(mapEnumInput(input["enumabstringuppercase"], TestEnum)).toBe(TestEnum.A_B); - expect(mapEnumInput(input["enumabstringlowercase"], TestEnum)).toBe(TestEnum.A_B); - expect(mapEnumInput(input["enumabstringlowercasewithwhitespace"], TestEnum)).toBe(TestEnum.A_B); - expect(mapEnumInput(input["enumabstringlowercasewithwhitespaceanddifferentseparator"], TestEnum)).toBe(TestEnum.A_B); - expect(mapEnumInput(input["enumabstringlowercasewithwhitespacebitwise"], TestEnum)).toBe(TestEnum.A_B); - expect(mapEnumInput(input["enumabcstringlowercasewithwhitespacebitwise"], TestEnum, TestEnum.A_B)).toBe(TestEnum.A_B_C); - }); -}); diff --git a/test/unit-tests/utils/curseforge/index.test.ts b/test/unit-tests/utils/curseforge/index.test.ts deleted file mode 100644 index 00a6968..0000000 --- a/test/unit-tests/utils/curseforge/index.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -import process from "process"; -import { describe, test, expect } from "@jest/globals"; -import { unifyGameVersion, unifyJava, convertToCurseForgeVersions } from "../../../../src/utils/curseforge"; - -describe("unifyGameVersion", () => { - test("versions in the unified format are not changed", async () => { - const validVersions = ["1.7.10", "1.12", "1.17-Snapshot", "1.17"]; - for (const version of validVersions) { - expect(await unifyGameVersion(version)).toStrictEqual(version); - } - }); - - test("snapshot versions are converted to the unified format (\\d+\\.\\d+(\\.\\d+)?-Snapshot)", async () => { - expect(await unifyGameVersion("21w37a")).toStrictEqual("1.18-Snapshot"); - expect(await unifyGameVersion("1.17.1-pre1")).toStrictEqual("1.17.1-Snapshot"); - expect(await unifyGameVersion("1.17.1-pre2")).toStrictEqual("1.17.1-Snapshot"); - expect(await unifyGameVersion("1.17.1-pre3")).toStrictEqual("1.17.1-Snapshot"); - expect(await unifyGameVersion("1.17.1-rc1")).toStrictEqual("1.17.1-Snapshot"); - expect(await unifyGameVersion("1.17.1-rc2")).toStrictEqual("1.17.1-Snapshot"); - expect(await unifyGameVersion("1.17-rc2")).toStrictEqual("1.17-Snapshot"); - expect(await unifyGameVersion("1.16-snapshot")).toStrictEqual("1.16-Snapshot"); - }); - - test("unnecessary punctuation marks and whitespace symbols do not break the function", async () => { - expect(await unifyGameVersion(" 21w37a ")).toStrictEqual("1.18-Snapshot"); - expect(await unifyGameVersion("1.17.1 pre1")).toStrictEqual("1.17.1-Snapshot"); - expect(await unifyGameVersion(" 1.17.1-pre2 ")).toStrictEqual("1.17.1-Snapshot"); - expect(await unifyGameVersion(" 1.17.1_pre2 ")).toStrictEqual("1.17.1-Snapshot"); - expect(await unifyGameVersion(" 1 17 1 pre3 ")).toStrictEqual("1.17.1-Snapshot"); - expect(await unifyGameVersion("1-17-1-rc1")).toStrictEqual("1.17.1-Snapshot"); - expect(await unifyGameVersion("1.17.1.rc2")).toStrictEqual("1.17.1-Snapshot"); - expect(await unifyGameVersion("1..17--rc2")).toStrictEqual("1.17-Snapshot"); - expect(await unifyGameVersion("\t1-16.snapshot\t")).toStrictEqual("1.16-Snapshot"); - }); -}); - -describe("unifyJava", () => { - test("versions in the unified format are not changed", () => { - const validVersions = ["Java 8", "Java 9", "Java 10", "Java 11", "Java 1234"]; - for (const version of validVersions) { - expect(unifyJava(version)).toStrictEqual(version); - } - }); - - test("java versions are converted to the unified format (Java \\d+)", () => { - expect(unifyJava("Java 1.8")).toStrictEqual("Java 8"); - expect(unifyJava("Java 1.9")).toStrictEqual("Java 9"); - expect(unifyJava("Java 1.10")).toStrictEqual("Java 10"); - expect(unifyJava("Java 1.11")).toStrictEqual("Java 11"); - expect(unifyJava("1.1234")).toStrictEqual("Java 1234"); - }); - - test("unnecessary punctuation marks and whitespace symbols do not break the function", () => { - expect(unifyJava("1.8")).toStrictEqual("Java 8"); - expect(unifyJava("9")).toStrictEqual("Java 9"); - expect(unifyJava(" Java 10 ")).toStrictEqual("Java 10"); - expect(unifyJava(" Java 1.11 ")).toStrictEqual("Java 11"); - expect(unifyJava("\t\t\tjava 1 12\n")).toStrictEqual("Java 12"); - expect(unifyJava(" 1.1234 ")).toStrictEqual("Java 1234"); - }); -}); - -describe("convertToCurseForgeVersions", () => { - // This test can only be executed in the GitHub Actions' environment, - // because CurseForge is a little bitch. - if (!process.env.CI) { - return; - } - - test("versions are converted to CurseForge ids", async () => { - const versions = { - gameVersions: { - "1.18-Snapshot": 8633, - "21w37a": 8633, - "1.18 (snapshot)": 8633, - "1.18-rc1": 8633, - "1.17-pre3": 8282, - "1.17.1": 8516, - }, - loaders: { - fabric: 7499, - forge: 7498, - quilt: 9153, - rift: 7500 - }, - java: { - "Java 8": 4458, - "Java 1.8": 4458, - "1.8": 4458, - "8": 4458, - "Java 1.7": 4457, - "java 1.16": 8325, - "17": 8326, - } - }; - - const curseForgeVersions = await convertToCurseForgeVersions(Object.keys(versions.gameVersions), Object.keys(versions.loaders), Object.keys(versions.java), process.env.CURSEFORGE_TOKEN as string); - const expectedIds = new Set([...Object.values(versions.gameVersions), ...Object.values(versions.loaders), ...Object.values(versions.java)]); - - expect(curseForgeVersions).toHaveLength(expectedIds.size); - for (const expectedId of expectedIds) { - expect(curseForgeVersions).toContain(expectedId); - } - }); -}); diff --git a/test/unit-tests/utils/diagnostics/stopwatch.test.ts b/test/unit-tests/utils/diagnostics/stopwatch.test.ts deleted file mode 100644 index 53c042e..0000000 --- a/test/unit-tests/utils/diagnostics/stopwatch.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { describe, test, expect } from "@jest/globals"; -import sleep from "../../../../src/utils/sleep"; -import Stopwatch from "../../../../src/utils/diagnostics/stopwatch"; - -describe("Stopwatch", () => { - test("base functionality of Stopwatch works", async () => { - const stopwatch = new Stopwatch(); - expect(stopwatch.isRunning).toBe(false); - expect(stopwatch.elapsedMilliseconds).toBe(0); - expect(stopwatch.start()).toBe(true); - await sleep(100); - expect(stopwatch.start()).toBe(false); - expect(stopwatch.stop()).toBe(true); - expect(stopwatch.stop()).toBe(false); - expect(stopwatch.elapsedMilliseconds).toBeGreaterThan(50); - expect(stopwatch.elapsedMilliseconds).toBeLessThan(200); - stopwatch.reset(); - expect(stopwatch.elapsedMilliseconds).toBe(0); - }); - - test("Stopwatch executes callbacks on start and end", async () => { - let started = 0; - let stopped = 0; - let ms = 0; - - const stopwatch = new Stopwatch(() => ++started, elapsedMilliseconds => { - ++stopped; - ms = elapsedMilliseconds; - }); - - expect(stopwatch.isRunning).toBe(false); - expect(stopwatch.elapsedMilliseconds).toBe(0); - - expect(stopwatch.start()).toBe(true); - expect(started).toBe(1); - expect(stopped).toBe(0); - - await sleep(100); - - expect(stopwatch.start()).toBe(false); - expect(started).toBe(1); - expect(stopped).toBe(0); - - expect(stopwatch.stop()).toBe(true); - expect(started).toBe(1); - expect(stopped).toBe(1); - - expect(stopwatch.stop()).toBe(false); - expect(started).toBe(1); - expect(stopped).toBe(1); - - expect(stopwatch.elapsedMilliseconds).toBeGreaterThan(50); - expect(stopwatch.elapsedMilliseconds).toBeLessThan(200); - expect(stopwatch.elapsedMilliseconds).toBe(ms); - - stopwatch.reset(); - expect(stopwatch.elapsedMilliseconds).toBe(0); - }); -}); diff --git a/test/unit-tests/utils/io/file.test.ts b/test/unit-tests/utils/io/file.test.ts deleted file mode 100644 index 8385fde..0000000 --- a/test/unit-tests/utils/io/file.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { describe, test, expect } from "@jest/globals"; -import File from "../../../../src/utils/io/file"; - -describe("File", () => { - describe("getFiles", () => { - test("all files matching the given pattern are returned", async () => { - expect(await File.getFiles("(README|LICENSE|FOO).md")).toHaveLength(2); - }); - - test("files matching the primary pattern are returned first", async () => { - const files = await File.getFiles({ primary: "README.md", secondary: "(README|LICENSE|FOO).md" }); - expect(files).toHaveLength(2); - expect(files[0]).toHaveProperty("name", "README.md"); - - const inversedFiles = await File.getFiles({ primary: "LICENSE.md", secondary: "(README|LICENSE|FOO).md" }); - expect(inversedFiles).toHaveLength(2); - expect(inversedFiles[0]).toHaveProperty("name", "LICENSE.md"); - }); - }); - - describe("getRequiredFiles", () => { - test("all files matching the given pattern are returned", async () => { - expect(await File.getRequiredFiles("(README|LICENSE|FOO).md")).toHaveLength(2); - }); - - test("an error is thrown if no files are found", async () => { - await expect(File.getRequiredFiles("FOO.md")).rejects.toBeInstanceOf(Error); - }); - }); -}); diff --git a/test/unit-tests/utils/logging/logging-stopwatch.test.ts b/test/unit-tests/utils/logging/logging-stopwatch.test.ts deleted file mode 100644 index 489d468..0000000 --- a/test/unit-tests/utils/logging/logging-stopwatch.test.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { describe, test, expect } from "@jest/globals"; -import sleep from "../../../../src/utils/sleep"; -import Logger from "../../../../src/utils/logging/logger"; -import LogginStopwatch from "../../../../src/utils/logging/logging-stopwatch"; - -function createLogger(info?: (msg: string) => void): Logger { - const notImplementedLogger = () => { - throw new Error("Not implemented and should never be called"); - }; - - return { - fatal: notImplementedLogger, - error: notImplementedLogger, - warn: notImplementedLogger, - debug: notImplementedLogger, - info: info ?? notImplementedLogger - }; -} - -describe("LogginStopwatch", () => { - test("base functionality of LogginStopwatch works", async () => { - const stopwatch = new LogginStopwatch(createLogger()); - expect(stopwatch.isRunning).toBe(false); - expect(stopwatch.elapsedMilliseconds).toBe(0); - expect(stopwatch.start()).toBe(true); - await sleep(100); - expect(stopwatch.start()).toBe(false); - expect(stopwatch.stop()).toBe(true); - expect(stopwatch.stop()).toBe(false); - expect(stopwatch.elapsedMilliseconds).toBeGreaterThan(50); - expect(stopwatch.elapsedMilliseconds).toBeLessThan(200); - stopwatch.reset(); - expect(stopwatch.elapsedMilliseconds).toBe(0); - }); - - test("LogginStopwatch executes callbacks on start and end", async () => { - let started = 0; - let stopped = 0; - let ms = 0; - const logger = createLogger(msg => { - if (msg.startsWith("start")) { - ++started; - } else if (msg.startsWith("stop")) { - ++stopped; - ms = +msg.split(" ")[1]; - } else { - throw new Error("Unrecognized message"); - } - }); - - const stopwatch = new LogginStopwatch(logger, "start", ms => `stop ${ms}`); - - expect(stopwatch.isRunning).toBe(false); - expect(stopwatch.elapsedMilliseconds).toBe(0); - - expect(stopwatch.start()).toBe(true); - expect(started).toBe(1); - expect(stopped).toBe(0); - - await sleep(100); - - expect(stopwatch.start()).toBe(false); - expect(started).toBe(1); - expect(stopped).toBe(0); - - expect(stopwatch.stop()).toBe(true); - expect(started).toBe(1); - expect(stopped).toBe(1); - - expect(stopwatch.stop()).toBe(false); - expect(started).toBe(1); - expect(stopped).toBe(1); - - expect(stopwatch.elapsedMilliseconds).toBeGreaterThan(50); - expect(stopwatch.elapsedMilliseconds).toBeLessThan(200); - expect(stopwatch.elapsedMilliseconds).toBe(ms); - - stopwatch.reset(); - expect(stopwatch.elapsedMilliseconds).toBe(0); - }); -}); diff --git a/test/unit-tests/utils/minecraft/index.test.ts b/test/unit-tests/utils/minecraft/index.test.ts deleted file mode 100644 index 66f833b..0000000 --- a/test/unit-tests/utils/minecraft/index.test.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { describe, test, expect } from "@jest/globals"; -import { getVersionById, findVersionByName, isSnapshot, parseVersionName, parseVersionNameFromFileVersion, getVersions, getLatestRelease, getCompatibleBuilds } from "../../../../src/utils/minecraft"; -import Version from "../../../../src/utils/versioning/version"; - -describe("getVersionById", () => { - test("returned versions have the same id as the given one", async () => { - const existingVersionIds = ["20w45a", "1.14.4-pre4", "3D Shareware v1.34", "20w14infinite", "1.14.2 Pre-Release 4", "1.7.10", "1.12.2"]; - for (const versionId of existingVersionIds) { - expect(await getVersionById(versionId)).toHaveProperty("id", versionId); - } - }); - - test("the method returns null if version with the given id does not exist", async () => { - const nonExistingVersionIds = ["", "0.0.0", "1.16.6", "18w100c", "1.7.10-rc1"]; - for (const versionId of nonExistingVersionIds) { - expect(await getVersionById(versionId)).toBeNull(); - } - }); - - test("returned versions have expected names", async () => { - const versions = { - "21w37a": "1.18", - "1.17.1": "1.17.1", - "1.17.1-pre3": "1.17.1", - "1.14.2 Pre-Release 4": "1.14.2", - "1.7.10": "1.7.10", - }; - - for (const [id, name] of Object.entries(versions)) { - expect (await getVersionById(id)).toHaveProperty("name", name); - } - }); -}); - -describe("findVersionByName", () => { - test("if the given name is an identifier, id of the found version should match it", async () => { - const ids = ["21w37a", "1.17.1-pre3", "1.16.5", "3D Shareware v1.34", "20w14infinite", "1.14.2 Pre-Release 4"]; - for (const id of ids) { - expect(await findVersionByName(id)).toHaveProperty("id", id); - } - }); - - test("if version with the given name does not exist, the most similar is returned", async () => { - const versions = { - "1.17.1-Snapshot": "1.17.1-rc2", - "1.17.1-rc3": "1.17.1-rc2", - "1.17.1 (snapshot)": "1.17.1-rc2", - "1.15.2 Pre-Release": "1.15.2-pre2", - }; - - for (const [name, id] of Object.entries(versions)) { - expect(await findVersionByName(name)).toHaveProperty("id", id); - } - }); -}); - -describe("isSnapshot", () => { - test("the method returns true if provided version is a snapshot; otherwise, false", () => { - const versions = { - "1.7.10": false, - "1.7.10-pre4": true, - "1.6.3-rc1": true, - "21w37a": true, - "1.14.2 Pre-Release 3": true, - "1.6.1": false, - "1.6": true, - "1.5": true, - "14w34c": true, - "1.RV-Pre1": true, - "20w14infinite": true, - "1.12.2": false, - "1.17-Snapshot": true, - }; - - for (const [name, snapshot] of Object.entries(versions)) { - expect(isSnapshot(name)).toStrictEqual(snapshot); - } - }); -}); - -describe("parseVersionName", () => { - test("Minecraft versions are parsed correctly", () => { - expect(parseVersionName("1.17.1")).toStrictEqual("1.17.1"); - expect(parseVersionName("1.16.3")).toStrictEqual("1.16.3"); - expect(parseVersionName("1.17")).toStrictEqual("1.17"); - expect(parseVersionName("1.16")).toStrictEqual("1.16"); - }); - - test("weird formats that contain Minecraft version are parsed correctly", () => { - expect(parseVersionName("1.17-5.0.1-beta+build.29")).toStrictEqual("1.17"); - expect(parseVersionName("[1.16.5, 1.17)")).toStrictEqual("1.16.5"); - expect(parseVersionName(">=1.17")).toStrictEqual("1.17"); - }); - - test("null is returned if version string does not contain Minecraft version", () => { - expect(parseVersionName("5.0.8-beta+build.111")).toBeNull(); - expect(parseVersionName("5.3.3-BETA+ec3b0e5d")).toBeNull(); - expect(parseVersionName("2.0.12")).toBeNull(); - }); -}); - -describe("parseVersionNameFromFileVersion", () => { - test("Sodium-like versions are parsed correctly", () => { - expect(parseVersionNameFromFileVersion("mc1.17.1-0.3.2+build.7")).toStrictEqual("1.17.1"); - expect(parseVersionNameFromFileVersion("mc1.16.3-0.1.0")).toStrictEqual("1.16.3"); - expect(parseVersionNameFromFileVersion("mc1.17.x-1.2")).toStrictEqual("1.17"); - expect(parseVersionNameFromFileVersion("mc1.16.*-1.2")).toStrictEqual("1.16"); - }); - - test("Fabric-like versions are parsed correctly", () => { - expect(parseVersionNameFromFileVersion("0.40.1+1.18_experimental")).toStrictEqual("1.18"); - expect(parseVersionNameFromFileVersion("0.5+1.17")).toStrictEqual("1.17"); - expect(parseVersionNameFromFileVersion("1.17.1+1.19")).toStrictEqual("1.19"); - expect(parseVersionNameFromFileVersion("1.19+1.17.1")).toStrictEqual("1.17.1"); - }); - - test("weird formats that contain obvious Minecraft version are parsed correctly", () => { - expect(parseVersionNameFromFileVersion("1.17-5.0.1-beta+build.29")).toStrictEqual("1.17"); - }); - - test("null is returned if version string does not contain obvious Minecraft version", () => { - expect(parseVersionNameFromFileVersion("5.0.8-beta+build.111")).toBeNull(); - expect(parseVersionNameFromFileVersion("5.3.3-BETA+ec3b0e5d")).toBeNull(); - expect(parseVersionNameFromFileVersion("2.0.12")).toBeNull(); - expect(parseVersionNameFromFileVersion("1.17")).toBeNull(); - }); -}); - -describe("getLatestRelease", () => { - test("the latest release is returned", async () => { - const latestRelease = (await getVersions()).filter(x => x.isRelease).sort((a, b) => b.releaseTime.getTime() - a.releaseTime.getTime())[0]; - expect(await getLatestRelease()).toHaveProperty("id", latestRelease.id); - }); -}); - -describe("getCompatibleBuilds", () => { - test("empty array is returned if no versions were found", async () => { - expect(await getCompatibleBuilds("42.0.0")).toHaveLength(0); - }); - - test("all versions of the given minor are returned", async () => { - const builds = (await getCompatibleBuilds("1.16")).map(x => x.id); - expect(builds).toHaveLength(54); - expect(builds).toContain("1.16"); - expect(builds).toContain("1.16.1"); - expect(builds).toContain("1.16.2"); - expect(builds).toContain("1.16.3"); - expect(builds).toContain("1.16.4"); - expect(builds).toContain("1.16.5"); - expect(builds).toContain("20w06a"); - expect(builds).toContain("20w14infinite"); - expect(builds).not.toContain("1.17"); - expect(builds).not.toContain("1.15"); - }); - - test("all versions of the given minor starting with the given build are returned", async () => { - const builds = (await getCompatibleBuilds(new Version(1, 17, 1))).map(x => x.id); - expect(builds).toHaveLength(6); - expect(builds).toContain("1.17.1"); - expect(builds).toContain("1.17.1-pre1"); - expect(builds).toContain("1.17.1-pre2"); - expect(builds).toContain("1.17.1-pre3"); - expect(builds).toContain("1.17.1-rc1"); - expect(builds).toContain("1.17.1-rc2"); - expect(builds).not.toContain("1.18"); - expect(builds).not.toContain("1.17"); - }); -}); diff --git a/test/unit-tests/utils/minecraft/minecraft-version-resolver.test.ts b/test/unit-tests/utils/minecraft/minecraft-version-resolver.test.ts deleted file mode 100644 index cf59c3f..0000000 --- a/test/unit-tests/utils/minecraft/minecraft-version-resolver.test.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { describe, test, expect } from "@jest/globals"; -import MinecraftVersionResolver from "../../../../src/utils/minecraft/minecraft-version-resolver"; - -describe("MinecraftVersionResolver.byName", () => { - test("every predefined MinecraftVersionResolver can be resolved", () => { - for (const [key, value] of Object.entries(MinecraftVersionResolver).filter(([_, x]) => x instanceof MinecraftVersionResolver)) { - expect(MinecraftVersionResolver.byName(key)).toStrictEqual(value); - } - }); - - test("null is returned if MinecraftVersionResolver with the given name doesn't exist", () => { - expect(MinecraftVersionResolver.byName("non-existing-resolver")).toBeNull(); - }); - - test("name of MinecraftVersionResolver is case insensitive", () => { - expect(MinecraftVersionResolver.byName("latest")).toStrictEqual(MinecraftVersionResolver.latest); - expect(MinecraftVersionResolver.byName("Latest")).toStrictEqual(MinecraftVersionResolver.latest); - expect(MinecraftVersionResolver.byName("LATEST")).toStrictEqual(MinecraftVersionResolver.latest); - expect(MinecraftVersionResolver.byName("LatesT")).toStrictEqual(MinecraftVersionResolver.latest); - }); -}); - -describe("MinecraftVersionResolver.exact", () => { - test("the exact version is returned", async () => { - const _1_17 = (await MinecraftVersionResolver.exact.resolve("1.17")).map(x => x.id); - expect(_1_17).toHaveLength(1); - expect(_1_17).toContain("1.17"); - - const _1_17_1 = (await MinecraftVersionResolver.exact.resolve("1.17.1")).map(x => x.id); - expect(_1_17_1).toHaveLength(1); - expect(_1_17_1).toContain("1.17.1"); - }); - - test("empty array is returned if no versions were found", async () => { - expect(await MinecraftVersionResolver.exact.resolve("42.0")).toHaveLength(0); - }); -}); - -describe("MinecraftVersionResolver.latest", () => { - test("the latest version of the given minor is returned", async () => { - const versions = (await MinecraftVersionResolver.latest.resolve("1.17")).map(x => x.id); - expect(versions).toHaveLength(1); - expect(versions).toContain("1.17.1"); - }); - - test("empty array is returned if no versions were found", async () => { - expect(await MinecraftVersionResolver.latest.resolve("42.0")).toHaveLength(0); - }); -}); - -describe("MinecraftVersionResolver.all", () => { - test("all versions of the given minor are returned", async () => { - const versions = (await MinecraftVersionResolver.all.resolve("1.17")).map(x => x.id); - expect(versions).toHaveLength(31); - expect(versions).toContain("1.17"); - expect(versions).toContain("1.17.1"); - expect(versions).toContain("1.17.1-rc2"); - expect(versions).toContain("1.17.1-rc1"); - expect(versions).toContain("1.17.1-pre3"); - expect(versions).toContain("1.17.1-pre2"); - expect(versions).toContain("1.17.1-pre1"); - expect(versions).toContain("21w03a"); - }); - - test("all versions of the given minor starting with the given build are returned", async () => { - const versions = (await MinecraftVersionResolver.all.resolve("1.17.1")).map(x => x.id); - expect(versions).toHaveLength(6); - expect(versions).toContain("1.17.1"); - expect(versions).toContain("1.17.1-rc2"); - expect(versions).toContain("1.17.1-rc1"); - expect(versions).toContain("1.17.1-pre3"); - expect(versions).toContain("1.17.1-pre2"); - expect(versions).toContain("1.17.1-pre1"); - }); - - test("empty array is returned if no versions were found", async () => { - expect(await MinecraftVersionResolver.all.resolve("42.0")).toHaveLength(0); - }); -}); - -describe("MinecraftVersionResolver.releases", () => { - test("all releases of the given minor are returned", async () => { - const versions = (await MinecraftVersionResolver.releases.resolve("1.17")).map(x => x.id); - expect(versions).toHaveLength(2); - expect(versions).toContain("1.17"); - expect(versions).toContain("1.17.1"); - }); - - test("all releases of the given minor starting with the given build are returned", async () => { - const versions = (await MinecraftVersionResolver.releases.resolve("1.16.1")).map(x => x.id); - expect(versions).toHaveLength(5); - expect(versions).toContain("1.16.1"); - expect(versions).toContain("1.16.2"); - expect(versions).toContain("1.16.3"); - expect(versions).toContain("1.16.4"); - expect(versions).toContain("1.16.5"); - }); - - test("an empty array is returned if no versions were found", async () => { - expect(await MinecraftVersionResolver.releases.resolve("42.0")).toHaveLength(0); - }); -}); - -describe("MinecraftVersionResolver.releasesIfAny", () => { - test("all releases of the given minor are returned", async () => { - const versions = (await MinecraftVersionResolver.releasesIfAny.resolve("1.17")).map(x => x.id); - expect(versions).toHaveLength(2); - expect(versions).toContain("1.17"); - expect(versions).toContain("1.17.1"); - }); - - test("empty array is returned if no versions were found", async () => { - expect(await MinecraftVersionResolver.releasesIfAny.resolve("42.0")).toHaveLength(0); - }); -}); diff --git a/test/unit-tests/utils/modrinth/index.test.ts b/test/unit-tests/utils/modrinth/index.test.ts deleted file mode 100644 index b7d0440..0000000 --- a/test/unit-tests/utils/modrinth/index.test.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { describe, test, expect } from "@jest/globals"; -import { getProject, getVersions } from "../../../../src/utils/modrinth"; - -const timeout = 15000; - -describe("getProject", () => { - test("returned versions have expected ids", async () => { - const projects = { - "sodium": "AANobbMI", - "fabric-api": "P7dR8mSH", - "sync-fabric": "OrJTMhHF", - "nether-chest": "okOUGirG", - "ebe": "OVuFYfre", - }; - - for (const [slug, id] of Object.entries(projects)) { - const project = await getProject(slug); - expect(project).toHaveProperty("id", id); - } - }, timeout); - - test("the method returns null if project with the given slug does not exist", async () => { - const nonExistentProjects = [ - "Na-11", - "api-fabric", - "sync-forge", - "ever-chest", - "beb", - "i-swear-to-god-if-someone-registers-these-mods" - ]; - - for (const slug of nonExistentProjects) { - const project = await getProject(slug); - expect(project).toBeNull(); - } - }, timeout); -}); - -describe("getVersions", () => { - test("returns unfiltered versions if no parameters were passed", async () => { - const versions = await getVersions("terra"); - expect(versions.find(x => x.featured)).toBeTruthy(); - expect(versions.find(x => !x.featured)).toBeTruthy(); - expect(versions.find(x => x.loaders.includes("fabric"))).toBeTruthy(); - expect(versions.find(x => x.loaders.includes("forge"))).toBeTruthy(); - expect(versions.find(x => x.game_versions.includes("1.18.2"))).toBeTruthy(); - expect(versions.find(x => x.game_versions.includes("1.16.5"))).toBeTruthy(); - }, timeout); - - test("returns only featured versions with featured === true", async () => { - const versions = await getVersions("terra", null!, null!, true); - expect(versions.every(x => x.featured)).toBe(true); - }, timeout); - - test("returns only unfeatured versions with featured === false", async () => { - const versions = await getVersions("terra", null!, null!, false); - expect(versions.every(x => !x.featured)).toBe(true); - }, timeout); - - test("returns only versions that support given modloaders", async () => { - const fabricVersions = await getVersions("terra", ["fabric"]); - expect(fabricVersions.every(x => x.loaders.includes("fabric"))).toBe(true); - - const forgeVersions = await getVersions("terra", ["forge"]); - expect(forgeVersions.every(x => x.loaders.includes("forge"))).toBe(true); - }, timeout); - - test("returns only versions that support given mc versions", async () => { - const versions_1_18_2 = await getVersions("terra", null!, ["1.18.2"]); - expect(versions_1_18_2.every(x => x.game_versions.includes("1.18.2"))).toBe(true); - - const versions_1_16_5 = await getVersions("terra", null!, ["1.16.5"]); - expect(versions_1_16_5.every(x => x.game_versions.includes("1.16.5"))).toBe(true); - }, timeout); -}); diff --git a/test/unit-tests/utils/retry.test.ts b/test/unit-tests/utils/retry.test.ts deleted file mode 100644 index 5eef984..0000000 --- a/test/unit-tests/utils/retry.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { describe, test, expect } from "@jest/globals"; -import retry from "../../../src/utils/retry"; -import SoftError from "../../../src/utils/soft-error"; - -function createThrowingFunc(attempts: number): () => true { - let counter = 0; - return () => { - if (++counter !== attempts) { - throw new SoftError(true); - } - return true; - }; -} - -function createAsyncThrowingFunc(attempts: number): () => Promise { - const func = createThrowingFunc(attempts); - return async () => func(); -} - -describe("retry", () => { - test("function resolves after several attempts", async () => { - expect(await retry({ func: createThrowingFunc(5), maxAttempts: 5 })).toBe(true); - }); - - test("delay is applied between the attempts", async () => { - const start = new Date(); - expect(await retry({ func: createThrowingFunc(2), maxAttempts: 2, delay: 100 })).toBe(true); - const end = new Date(); - const duration = end.getTime() - start.getTime(); - expect(duration > 50 && duration < 200).toBe(true); - }); - - test("the original error is thrown if retry function didn't succeed", async () => { - await expect(retry({ func: createThrowingFunc(5), maxAttempts: 1 })).rejects.toThrow(SoftError); - }); - - test("softErrorPredicate is used to determine whether the error is soft or not", async () => { - await expect(retry({ func: createThrowingFunc(5), maxAttempts: 5, softErrorPredicate: _ => false })).rejects.toThrow(SoftError); - }); - - test("errorCallback is called whenever an error occurs", async () => { - await expect(retry({ func: createThrowingFunc(5), maxAttempts: 5, errorCallback: e => { throw e; } })).rejects.toThrow(SoftError); - }); -}); - -describe("retry (async)", () => { - test("function resolves after several attempts", async () => { - expect(await retry({ func: createAsyncThrowingFunc(5), maxAttempts: 5 })).toBe(true); - }); - - test("delay is applied between the attempts", async () => { - const start = new Date(); - expect(await retry({ func: createAsyncThrowingFunc(2), maxAttempts: 2, delay: 100 })).toBe(true); - const end = new Date(); - const duration = end.getTime() - start.getTime(); - expect(duration > 50 && duration < 200).toBe(true); - }); - - test("the original error is thrown if retry function didn't succeed", async () => { - await expect(retry({ func: createAsyncThrowingFunc(5), maxAttempts: 1 })).rejects.toThrow(SoftError); - }); - - test("softErrorPredicate is used to determine whether the error is soft or not", async () => { - await expect(retry({ func: createAsyncThrowingFunc(5), maxAttempts: 5, softErrorPredicate: _ => false })).rejects.toThrow(SoftError); - }); - - test("errorCallback is called whenever an error occurs", async () => { - await expect(retry({ func: createAsyncThrowingFunc(5), maxAttempts: 5, errorCallback: e => { throw e; } })).rejects.toThrow(SoftError); - }); -}); diff --git a/test/unit-tests/utils/sleep.test.ts b/test/unit-tests/utils/sleep.test.ts deleted file mode 100644 index c425c38..0000000 --- a/test/unit-tests/utils/sleep.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { describe, test, expect } from "@jest/globals"; -import sleep from "../../../src/utils/sleep"; - -describe("sleep", () => { - test("execution continues after the specified delay", async () => { - const start = new Date(); - await sleep(100); - const end = new Date(); - const duration = end.getTime() - start.getTime(); - expect(duration).toBeGreaterThan(50); - expect(duration).toBeLessThan(200); - }); -}); - diff --git a/test/unit-tests/utils/versioning/version-type.test.ts b/test/unit-tests/utils/versioning/version-type.test.ts deleted file mode 100644 index 554df1f..0000000 --- a/test/unit-tests/utils/versioning/version-type.test.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { describe, test, expect } from "@jest/globals"; -import VersionType from "../../../../src/utils/versioning/version-type"; - -describe("VersionType", () => { - describe("fromName", () => { - test("version type is correctly extracted from the filename", () => { - expect(VersionType.fromName("sodium-fabric-mc1.17.1-0.3.2+build.7")).toStrictEqual("release"); - expect(VersionType.fromName("fabric-api-0.40.1+1.18_experimental")).toStrictEqual("release"); - expect(VersionType.fromName("TechReborn-5.0.8-beta+build.111")).toStrictEqual("beta"); - expect(VersionType.fromName("TechReborn-1.17-5.0.1-beta+build.29")).toStrictEqual("beta"); - expect(VersionType.fromName("Terra-forge-5.3.3-BETA+ec3b0e5d")).toStrictEqual("beta"); - expect(VersionType.fromName("Terra-forge-5.3.3-alpha+ec3b0e5d")).toStrictEqual("alpha"); - expect(VersionType.fromName("modmenu-2.0.12")).toStrictEqual("release"); - expect(VersionType.fromName("enhancedblockentities-0.5+1.17")).toStrictEqual("release"); - expect(VersionType.fromName("sync-mc1.17.x-1.2")).toStrictEqual("release"); - }); - }); -}); diff --git a/test/unit-tests/utils/versioning/version.test.ts b/test/unit-tests/utils/versioning/version.test.ts deleted file mode 100644 index e847d2c..0000000 --- a/test/unit-tests/utils/versioning/version.test.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { describe, test, expect } from "@jest/globals"; -import Version from "../../../../src/utils/versioning/version"; - -describe("Version", () => { - describe("fromName", () => { - test("file version is correctly extracted from the filename", () => { - expect(Version.fromName("sodium-fabric-mc1.17.1-0.3.2+build.7")).toStrictEqual("mc1.17.1-0.3.2+build.7"); - expect(Version.fromName("fabric-api-0.40.1+1.18_experimental")).toStrictEqual("0.40.1+1.18_experimental"); - expect(Version.fromName("TechReborn-5.0.8-beta+build.111")).toStrictEqual("5.0.8-beta+build.111"); - expect(Version.fromName("TechReborn-1.17-5.0.1-beta+build.29")).toStrictEqual("1.17-5.0.1-beta+build.29"); - expect(Version.fromName("Terra-forge-5.3.3-BETA+ec3b0e5d")).toStrictEqual("5.3.3-BETA+ec3b0e5d"); - expect(Version.fromName("modmenu-2.0.12")).toStrictEqual("2.0.12"); - expect(Version.fromName("enhancedblockentities-0.5+1.17")).toStrictEqual("0.5+1.17"); - expect(Version.fromName("sync-mc1.17.x-1.2")).toStrictEqual("mc1.17.x-1.2"); - }); - }); -}); diff --git a/test/utils/input-utils.ts b/test/utils/input-utils.ts deleted file mode 100644 index 3ca4dc2..0000000 --- a/test/utils/input-utils.ts +++ /dev/null @@ -1,15 +0,0 @@ -import process from "process"; - -export function setupInput(input: Record): void { - for (const [key, value] of Object.entries(input)) { - process.env[`INPUT_${key.replace(/ /g, "_").toUpperCase()}`] = value.toString(); - } -} - -export function unsetInput(): void { - for (const key of Object.keys(process.env)) { - if (key.startsWith("INPUT_")) { - delete process.env[key]; - } - } -}