mirror of
https://github.com/Kir-Antipov/mc-publish.git
synced 2024-11-25 01:41:05 -05:00
Added tests for curseforge-upload-api-client
This commit is contained in:
parent
2c6ab90c5f
commit
f61c637942
1 changed files with 414 additions and 0 deletions
|
@ -0,0 +1,414 @@
|
|||
import { readFileSync } from "node:fs";
|
||||
import { resolve } from "node:path";
|
||||
import mockFs from "mock-fs";
|
||||
import { createFakeFetch } from "../../../utils/fetch-utils";
|
||||
import { FormData } from "@/utils/net/form-data";
|
||||
import { HttpResponse } from "@/utils/net/http-response";
|
||||
import { CurseForgeDependencyType } from "@/platforms/curseforge/curseforge-dependency-type";
|
||||
import { CurseForgeVersionInitMetadata } from "@/platforms/curseforge/curseforge-version";
|
||||
import { CURSEFORGE_UPLOAD_API_URL, CurseForgeUploadApiClient } from "@/platforms/curseforge/curseforge-upload-api-client";
|
||||
|
||||
const FILES = Object.freeze([
|
||||
"fabric.mod.json",
|
||||
"mods.toml",
|
||||
"quilt.mod.json",
|
||||
]) as string[];
|
||||
|
||||
const DB = Object.freeze({
|
||||
versionTypes: Object.freeze(JSON.parse(
|
||||
readFileSync(resolve(__dirname, "../../../content/curseforge/version-types.json"), "utf8")
|
||||
)),
|
||||
|
||||
versions: Object.freeze(JSON.parse(
|
||||
readFileSync(resolve(__dirname, "../../../content/curseforge/versions.json"), "utf8")
|
||||
)),
|
||||
|
||||
projects: Object.freeze([
|
||||
{
|
||||
id: 1,
|
||||
slug: "mod",
|
||||
|
||||
// 1.19, Fabric, Java 17
|
||||
game_versions: [9186, 7499, 8326],
|
||||
},
|
||||
|
||||
{
|
||||
id: 2,
|
||||
slug: "plugin",
|
||||
|
||||
// 1.19+Bukkit
|
||||
game_versions: [9190],
|
||||
},
|
||||
|
||||
{
|
||||
id: 4,
|
||||
slug: "resource-pack",
|
||||
|
||||
// 1.19
|
||||
game_versions: [9186],
|
||||
},
|
||||
|
||||
{
|
||||
id: 5,
|
||||
slug: "addon",
|
||||
|
||||
// 1.19+Addon
|
||||
game_versions: [9189],
|
||||
},
|
||||
]),
|
||||
|
||||
files: Object.freeze([
|
||||
{
|
||||
id: 1,
|
||||
name: "Mod v1.0.0",
|
||||
project_id: 1,
|
||||
url: "https://www.curseforge.com/api/v1/mods/1/files/1/download",
|
||||
version_id: 1,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "mods.toml",
|
||||
project_id: 1,
|
||||
url: "https://www.curseforge.com/api/v1/mods/1/files/2/download",
|
||||
version_id: 1,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "quilt.mod.json",
|
||||
project_id: 1,
|
||||
url: "https://www.curseforge.com/api/v1/mods/1/files/3/download",
|
||||
version_id: 1,
|
||||
},
|
||||
|
||||
{
|
||||
id: 4,
|
||||
name: "Plugin v1.0.0",
|
||||
project_id: 2,
|
||||
url: "https://www.curseforge.com/api/v1/mods/2/files/4/download",
|
||||
version_id: 4,
|
||||
},
|
||||
|
||||
{
|
||||
id: 5,
|
||||
name: "Resource Pack v1.0.0",
|
||||
project_id: 4,
|
||||
url: "https://www.curseforge.com/api/v1/mods/4/files/5/download",
|
||||
version_id: 5,
|
||||
},
|
||||
|
||||
{
|
||||
id: 6,
|
||||
name: "Addon v1.0.0",
|
||||
project_id: 5,
|
||||
url: "https://www.curseforge.com/api/v1/mods/5/files/6/download",
|
||||
version_id: 6,
|
||||
},
|
||||
]),
|
||||
});
|
||||
|
||||
const CURSEFORGE_FETCH = createFakeFetch({
|
||||
baseUrl: CURSEFORGE_UPLOAD_API_URL,
|
||||
requiredHeaders: ["X-Api-Token"],
|
||||
|
||||
GET: {
|
||||
"^\\/game\\/version-types": () => DB.versionTypes,
|
||||
|
||||
"^\\/game\\/versions": () => DB.versions,
|
||||
},
|
||||
|
||||
POST: {
|
||||
"^\\/projects\\/(\\d+)\\/upload-file": ([id], { body }) => {
|
||||
const project = DB.projects.find(x => x.id === +id);
|
||||
if (!project) {
|
||||
return HttpResponse.json({ errorCode: 404, errorMessage: `Project not found: '${id}'` }, { status: 404 });
|
||||
}
|
||||
|
||||
const formData = body as FormData;
|
||||
const fileName = formData.get("file")?.["name"] as string;
|
||||
const metadata = JSON.parse(formData.get("metadata") as string) as CurseForgeVersionInitMetadata;
|
||||
const dependencies = metadata.relations?.projects?.map(x => x.slug) || [];
|
||||
const unknownDependency = dependencies.find(x => !DB.projects.find(y => x === y.slug));
|
||||
const unknownGameVersion = metadata.gameVersions?.find(x => !project.game_versions.includes(x));
|
||||
|
||||
if (metadata.relations && !dependencies.length || metadata.parentFileID && dependencies.length) {
|
||||
return HttpResponse.json({ errorCode: 400, errorMessage: "We don't know how to parse an empty array, so just like fuck you, lmao" }, { status: 400 });
|
||||
}
|
||||
|
||||
if (!!metadata.gameVersions?.length === !!metadata.parentFileID) {
|
||||
return HttpResponse.json({ errorCode: 400, errorMessage: "At least one game version is required" }, { status: 400 });
|
||||
}
|
||||
|
||||
if (unknownGameVersion) {
|
||||
return HttpResponse.json({ errorCode: 1009, errorMessage: `Invalid game version: '${unknownGameVersion}'` }, { status: 400 });
|
||||
}
|
||||
|
||||
if (unknownDependency) {
|
||||
return HttpResponse.json({ errorCode: 1018, errorMessage: `Invalid slug in project relations: '${unknownDependency}'` }, { status: 400 });
|
||||
}
|
||||
|
||||
const uploadedFile = DB.files.find(x => x.project_id === project.id && [fileName, metadata.displayName].includes(x.name));
|
||||
expect(uploadedFile).toBeDefined();
|
||||
|
||||
return HttpResponse.json(uploadedFile, { status: 200 });
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
const fakeFiles = FILES.reduce((a, b) => ({ ...a, [b]: "" }), {});
|
||||
|
||||
mockFs(fakeFiles);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockFs.restore();
|
||||
});
|
||||
|
||||
describe("CurseForgeUploadApiClient", () => {
|
||||
describe("getGameVersionTypes", () => {
|
||||
test("returns game version types", async () => {
|
||||
const api = new CurseForgeUploadApiClient({ fetch: CURSEFORGE_FETCH, token: "token" });
|
||||
|
||||
const versionTypes = await api.getGameVersionTypes();
|
||||
|
||||
expect(versionTypes?.length).toBeGreaterThan(0);
|
||||
for (const versionType of versionTypes) {
|
||||
expect(versionType).toHaveProperty("id");
|
||||
expect(versionType).toHaveProperty("name");
|
||||
expect(versionType).toHaveProperty("slug");
|
||||
}
|
||||
});
|
||||
|
||||
test("returned game version types contain one representing Bukkit plugins", async () => {
|
||||
const api = new CurseForgeUploadApiClient({ fetch: CURSEFORGE_FETCH, token: "token" });
|
||||
|
||||
const versionTypes = await api.getGameVersionTypes();
|
||||
|
||||
expect(versionTypes).toContainEqual({
|
||||
id: 1,
|
||||
slug: "bukkit",
|
||||
name: "Bukkit",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("getGameVersions", () => {
|
||||
test("returns game versions", async () => {
|
||||
const api = new CurseForgeUploadApiClient({ fetch: CURSEFORGE_FETCH, token: "token" });
|
||||
|
||||
const versions = await api.getGameVersions();
|
||||
|
||||
expect(versions?.length).toBeGreaterThan(0);
|
||||
for (const version of versions) {
|
||||
expect(version).toHaveProperty("id");
|
||||
expect(version).toHaveProperty("gameVersionTypeID");
|
||||
expect(version).toHaveProperty("name");
|
||||
expect(version).toHaveProperty("slug");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("getGameVersionMap", () => {
|
||||
test("returns game version map", async () => {
|
||||
const api = new CurseForgeUploadApiClient({ fetch: CURSEFORGE_FETCH, token: "token" });
|
||||
|
||||
const map = await api.getGameVersionMap();
|
||||
|
||||
expect(map.environments?.length).toBeGreaterThan(0);
|
||||
expect(map.game_versions?.length).toBeGreaterThan(0);
|
||||
expect(map.game_versions_for_addons?.length).toBeGreaterThan(0);
|
||||
expect(map.game_versions_for_plugins?.length).toBeGreaterThan(0);
|
||||
expect(map.java_versions?.length).toBeGreaterThan(0);
|
||||
expect(map.loaders?.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("createVersion", () => {
|
||||
test("creates a new mod version", async () => {
|
||||
const api = new CurseForgeUploadApiClient({ fetch: CURSEFORGE_FETCH, token: "token" });
|
||||
|
||||
const expectedVersionId = 1;
|
||||
const projectId = 1;
|
||||
const name = "Mod v1.0.0";
|
||||
const fileCount = 1;
|
||||
|
||||
const version = await api.createVersion({
|
||||
project_id: projectId,
|
||||
files: FILES.slice(0, fileCount),
|
||||
name,
|
||||
game_versions: ["1.19"],
|
||||
loaders: ["fabric"],
|
||||
java_versions: ["Java 17"],
|
||||
});
|
||||
|
||||
expect(version).toEqual({
|
||||
id: expectedVersionId,
|
||||
project_id: projectId,
|
||||
name,
|
||||
files: DB.files.filter(x => x.project_id === projectId).slice(0, fileCount),
|
||||
});
|
||||
});
|
||||
|
||||
test("creates a new plugin version", async () => {
|
||||
const api = new CurseForgeUploadApiClient({ fetch: CURSEFORGE_FETCH, token: "token" });
|
||||
|
||||
const expectedVersionId = 4;
|
||||
const projectId = 2;
|
||||
const name = "Plugin v1.0.0";
|
||||
const fileCount = 1;
|
||||
|
||||
const version = await api.createVersion({
|
||||
project_id: projectId,
|
||||
files: FILES.slice(0, fileCount),
|
||||
name,
|
||||
game_versions: ["1.19"],
|
||||
loaders: ["fabric"],
|
||||
java_versions: ["Java 17"],
|
||||
});
|
||||
|
||||
expect(version).toEqual({
|
||||
id: expectedVersionId,
|
||||
project_id: projectId,
|
||||
name,
|
||||
files: DB.files.filter(x => x.project_id === projectId).slice(0, fileCount),
|
||||
});
|
||||
});
|
||||
|
||||
test("creates a new resource pack version", async () => {
|
||||
const api = new CurseForgeUploadApiClient({ fetch: CURSEFORGE_FETCH, token: "token" });
|
||||
|
||||
const expectedVersionId = 5;
|
||||
const projectId = 4;
|
||||
const name = "Resource Pack v1.0.0";
|
||||
const fileCount = 1;
|
||||
|
||||
const version = await api.createVersion({
|
||||
project_id: projectId,
|
||||
files: FILES.slice(0, fileCount),
|
||||
name,
|
||||
game_versions: ["1.19"],
|
||||
loaders: ["fabric"],
|
||||
java_versions: ["Java 17"],
|
||||
});
|
||||
|
||||
expect(version).toEqual({
|
||||
id: expectedVersionId,
|
||||
project_id: projectId,
|
||||
name,
|
||||
files: DB.files.filter(x => x.project_id === projectId).slice(0, fileCount),
|
||||
});
|
||||
});
|
||||
|
||||
test("creates a new addon version", async () => {
|
||||
const api = new CurseForgeUploadApiClient({ fetch: CURSEFORGE_FETCH, token: "token" });
|
||||
|
||||
const expectedVersionId = 6;
|
||||
const projectId = 5;
|
||||
const name = "Addon v1.0.0";
|
||||
const fileCount = 1;
|
||||
|
||||
const version = await api.createVersion({
|
||||
project_id: projectId,
|
||||
files: FILES.slice(0, fileCount),
|
||||
name,
|
||||
game_versions: ["1.19"],
|
||||
loaders: ["fabric"],
|
||||
java_versions: ["Java 17"],
|
||||
});
|
||||
|
||||
expect(version).toEqual({
|
||||
id: expectedVersionId,
|
||||
project_id: projectId,
|
||||
name,
|
||||
files: DB.files.filter(x => x.project_id === projectId).slice(0, fileCount),
|
||||
});
|
||||
});
|
||||
|
||||
test("creates a new version with multiple files", async () => {
|
||||
const api = new CurseForgeUploadApiClient({ fetch: CURSEFORGE_FETCH, token: "token" });
|
||||
|
||||
const expectedVersionId = 1;
|
||||
const projectId = 1;
|
||||
const name = "Mod v1.0.0";
|
||||
const fileCount = 3;
|
||||
|
||||
const version = await api.createVersion({
|
||||
project_id: projectId,
|
||||
files: FILES.slice(0, fileCount),
|
||||
name,
|
||||
game_versions: ["1.19"],
|
||||
loaders: ["fabric"],
|
||||
java_versions: ["Java 17"],
|
||||
});
|
||||
|
||||
expect(version).toEqual({
|
||||
id: expectedVersionId,
|
||||
project_id: projectId,
|
||||
name,
|
||||
files: DB.files.filter(x => x.project_id === projectId).slice(0, fileCount),
|
||||
});
|
||||
});
|
||||
|
||||
test("creates a new version with dependencies", async () => {
|
||||
const api = new CurseForgeUploadApiClient({ fetch: CURSEFORGE_FETCH, token: "token" });
|
||||
|
||||
const expectedVersionId = 1;
|
||||
const projectId = 1;
|
||||
const name = "Mod v1.0.0";
|
||||
const fileCount = 3;
|
||||
|
||||
const version = await api.createVersion({
|
||||
project_id: projectId,
|
||||
files: FILES.slice(0, fileCount),
|
||||
name,
|
||||
game_versions: ["1.19"],
|
||||
loaders: ["fabric"],
|
||||
java_versions: ["Java 17"],
|
||||
dependencies: [
|
||||
{ slug: "addon", type: CurseForgeDependencyType.OPTIONAL_DEPENDENCY },
|
||||
{ slug: "resource-pack", type: CurseForgeDependencyType.REQUIRED_DEPENDENCY },
|
||||
{ slug: "plugin", type: CurseForgeDependencyType.EMBEDDED_LIBRARY },
|
||||
],
|
||||
});
|
||||
|
||||
expect(version).toEqual({
|
||||
id: expectedVersionId,
|
||||
project_id: projectId,
|
||||
name,
|
||||
files: DB.files.filter(x => x.project_id === projectId).slice(0, fileCount),
|
||||
});
|
||||
});
|
||||
|
||||
test("creates a new version while filtering out invalid dependencies", async () => {
|
||||
const api = new CurseForgeUploadApiClient({ fetch: CURSEFORGE_FETCH, token: "token" });
|
||||
|
||||
const expectedVersionId = 1;
|
||||
const projectId = 1;
|
||||
const name = "Mod v1.0.0";
|
||||
const fileCount = 3;
|
||||
|
||||
const version = await api.createVersion({
|
||||
project_id: projectId,
|
||||
files: FILES.slice(0, fileCount),
|
||||
name,
|
||||
game_versions: ["1.19"],
|
||||
loaders: ["fabric"],
|
||||
java_versions: ["Java 17"],
|
||||
dependencies: [
|
||||
{ slug: "addon", type: CurseForgeDependencyType.OPTIONAL_DEPENDENCY },
|
||||
{ slug: "addon-1", type: CurseForgeDependencyType.OPTIONAL_DEPENDENCY },
|
||||
{ slug: "resource-pack", type: CurseForgeDependencyType.REQUIRED_DEPENDENCY },
|
||||
{ slug: "plugin", type: CurseForgeDependencyType.EMBEDDED_LIBRARY },
|
||||
{ slug: "plugin-1", type: CurseForgeDependencyType.EMBEDDED_LIBRARY },
|
||||
],
|
||||
});
|
||||
|
||||
expect(version).toEqual({
|
||||
id: expectedVersionId,
|
||||
project_id: projectId,
|
||||
name,
|
||||
files: DB.files.filter(x => x.project_id === projectId).slice(0, fileCount),
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue