mirror of
https://github.com/Kir-Antipov/mc-publish.git
synced 2024-11-22 00:11:02 -05:00
Deleted old test suites
This commit is contained in:
parent
fc1a2a044b
commit
9ad1412834
20 changed files with 0 additions and 1604 deletions
|
@ -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": "*"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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"
|
|
|
@ -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"
|
|
||||||
}
|
|
|
@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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; }, <Record<string, Dependency>>{});
|
|
||||||
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; }, <Record<string, Dependency>>{});
|
|
||||||
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; }, <Record<string, Dependency>>{});
|
|
||||||
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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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<number>(versions.gameVersions), ...Object.values(versions.loaders), ...Object.values(versions.java)]);
|
|
||||||
|
|
||||||
expect(curseForgeVersions).toHaveLength(expectedIds.size);
|
|
||||||
for (const expectedId of expectedIds) {
|
|
||||||
expect(curseForgeVersions).toContain(expectedId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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");
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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);
|
|
||||||
});
|
|
|
@ -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<true> {
|
|
||||||
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(<any>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(<any>SoftError);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("errorCallback is called whenever an error occurs", async () => {
|
|
||||||
await expect(retry({ func: createThrowingFunc(5), maxAttempts: 5, errorCallback: e => { throw e; } })).rejects.toThrow(<any>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(<any>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(<any>SoftError);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("errorCallback is called whenever an error occurs", async () => {
|
|
||||||
await expect(retry({ func: createAsyncThrowingFunc(5), maxAttempts: 5, errorCallback: e => { throw e; } })).rejects.toThrow(<any>SoftError);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
|
@ -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");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,15 +0,0 @@
|
||||||
import process from "process";
|
|
||||||
|
|
||||||
export function setupInput(input: Record<string, any>): 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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue