From 5e633ac2f1011198d1f3c3702d1e1b9fe3fbfcad Mon Sep 17 00:00:00 2001 From: bbassie <17990055+bbassie@users.noreply.github.com> Date: Tue, 18 Aug 2026 16:54:19 +0000 Subject: [PATCH] Move dependency resolver tests to test/messages/mod.test.js Also update the existing local mod fixtures to carry a factorio_version and drop enable-all-feature-flags from the live expectations: the 2.0 releases of pyalternativeenergy only list it as optional, it was only pulled in before because 2.1 releases were being selected. Co-Authored-By: Claude Fable 5 --- test/controller/ControlConnection.test.js | 73 ----------------------- test/messages/mod.test.js | 72 +++++++++++++++++++++- 2 files changed, 69 insertions(+), 76 deletions(-) diff --git a/test/controller/ControlConnection.test.js b/test/controller/ControlConnection.test.js index f0cbccb7..90483a08 100644 --- a/test/controller/ControlConnection.test.js +++ b/test/controller/ControlConnection.test.js @@ -1,6 +1,5 @@ "use strict"; const assert = require("assert").strict; -const lib = require("@clusterio/lib"); const { ControlConnection } = require("@clusterio/controller"); describe("controller/src/ControlConnection", function() { @@ -40,76 +39,4 @@ describe("controller/src/ControlConnection", function() { assert.equal(mockController.stopped, false); }); }); - - describe(".handleModDependencyResolveRequest()", function() { - const originalFetchModReleases = lib.ModStore.fetchModReleases; - const portal = new Map(); - let localMods; - - function release(version, factorioVersion, dependencies = []) { - return { - version, sha1: "0".repeat(40), - info_json: { factorio_version: factorioVersion, dependencies }, - }; - } - - before(function() { - lib.ModStore.fetchModReleases = async (name) => { - const releases = portal.get(name); - if (!releases) { - throw new Error("Fetch: returned 404 Not Found"); - } - return { name, owner: "owner", title: name, releases }; - }; - }); - after(function() { - lib.ModStore.fetchModReleases = originalFetchModReleases; - }); - beforeEach(function() { - portal.clear(); - localMods = []; - }); - - async function resolve(mods, factorioVersion, checkForUpdates = false) { - const response = await ControlConnection.prototype.handleModDependencyResolveRequest.call( - { _controller: { modStore: { mods: () => localMods } } }, - new lib.ModDependencyResolveRequest( - mods.map(mod => new lib.ModDependency(mod)), factorioVersion, checkForUpdates, - ), - ); - return new Map(response.dependencies.map(mod => [mod.name, mod])); - } - - it("only selects portal releases matching the mod pack's Factorio version", async function() { - portal.set("root", [release("1.0.0", "2.0", ["dep"]), release("1.1.0", "2.1", ["dep"])]); - portal.set("dep", [ - release("1.0.0", "1.1"), - release("2.0.0", "2.0"), - release("3.0.0", "2.1"), - ]); - assert.equal((await resolve(["root = 1.0.0"], "2.0")).get("dep").version, "2.0.0"); - assert.equal((await resolve(["root = 1.1.0"], "2.1")).get("dep").version, "3.0.0"); - }); - - it("only selects local mods matching the mod pack's Factorio version", async function() { - portal.set("root", [release("1.0.0", "2.0", ["dep"])]); - portal.set("dep", [release("2.0.0", "2.0")]); - localMods = [ - lib.ModInfo.fromJSON({ name: "dep", version: "3.0.0", factorio_version: "2.1" }), - lib.ModInfo.fromJSON({ name: "dep", version: "1.0.0", factorio_version: "2.0" }), - ]; - assert.equal((await resolve(["root = 1.0.0"], "2.0")).get("dep").version, "1.0.0"); - assert.equal((await resolve(["root = 1.0.0"], "2.0", true)).get("dep").version, "2.0.0"); - }); - - it("reports dependencies without a matching Factorio version as not found", async function() { - portal.set("root", [release("1.0.0", "2.0", ["dep"])]); - portal.set("dep", [release("3.0.0", "2.1")]); - const response = await ControlConnection.prototype.handleModDependencyResolveRequest.call( - { _controller: { modStore: { mods: () => localMods } } }, - new lib.ModDependencyResolveRequest([new lib.ModDependency("root = 1.0.0")], "2.0", false), - ); - assert.equal(response.errors.get("dep"), "notFound"); - }); - }); }); diff --git a/test/messages/mod.test.js b/test/messages/mod.test.js index f782d5fc..aee89b74 100644 --- a/test/messages/mod.test.js +++ b/test/messages/mod.test.js @@ -384,8 +384,10 @@ describe("messages/mod", function() { } }); it("prefers the locally installed version if matching", async function() { - controller.modStore.addMod(lib.ModInfo.fromJSON({ name: "foo", version: "1.0.0" })); for (const factorioVersion of factorioVersions) { + controller.modStore.addMod(lib.ModInfo.fromJSON({ + name: "foo", version: "1.0.0", factorio_version: factorioVersion, + })); setPortalModRelease("root", "1.0.0", factorioVersion, ["foo"]); setPortalModRelease("foo", "2.0.0", factorioVersion, []); @@ -402,8 +404,10 @@ describe("messages/mod", function() { } }); it("prefers the mod portal version when checking for updates", async function() { - controller.modStore.addMod(lib.ModInfo.fromJSON({ name: "foo", version: "1.0.0" })); for (const factorioVersion of factorioVersions) { + controller.modStore.addMod(lib.ModInfo.fromJSON({ + name: "foo", version: "1.0.0", factorio_version: factorioVersion, + })); setPortalModRelease("root", "1.0.0", factorioVersion, ["foo"]); setPortalModRelease("foo", "2.0.0", factorioVersion, []); @@ -455,6 +459,68 @@ describe("messages/mod", function() { assert.deepEqual(depIds, new Set(["root_1.0.0", "foo_2.0.0", "bar_1.5.0"])); } }); + it("only selects portal releases matching the factorio version", async function() { + setPortalModRelease("root", "1.0.0", "2.0", ["foo"]); + ModReleases.set("foo", { + name: "foo", + releases: [{ + version: "1.0.0", info_json: { factorio_version: "1.1", dependencies: [] }, + }, { + version: "2.0.0", info_json: { factorio_version: "2.0", dependencies: [] }, + }, { + version: "3.0.0", info_json: { factorio_version: "2.1", dependencies: [] }, + }], + }); + + const result = await controlConnection.handleModDependencyResolveRequest( + new lib.ModDependencyResolveRequest([new ModDependency("root")], "2.0") + ); + + assert.deepEqual(result.errors, new Map([ + ["base", "notFound"], + ])); + + const depIds = new Set(result.dependencies.map(mod => mod.id)); + assert.deepEqual(depIds, new Set(["root_1.0.0", "foo_2.0.0"])); + }); + it("only selects local mods matching the factorio version", async function() { + controller.modStore.addMod(lib.ModInfo.fromJSON({ + name: "foo", version: "1.0.0", factorio_version: "2.0", + })); + controller.modStore.addMod(lib.ModInfo.fromJSON({ + name: "foo", version: "3.0.0", factorio_version: "2.1", + })); + setPortalModRelease("root", "1.0.0", "2.0", ["foo"]); + setPortalModRelease("foo", "2.0.0", "2.0", []); + + let result = await controlConnection.handleModDependencyResolveRequest( + new lib.ModDependencyResolveRequest([new ModDependency("root")], "2.0") + ); + let depIds = new Set(result.dependencies.map(mod => mod.id)); + assert.deepEqual(depIds, new Set(["root_1.0.0", "foo_1.0.0"])); + + result = await controlConnection.handleModDependencyResolveRequest( + new lib.ModDependencyResolveRequest([new ModDependency("root")], "2.0", true) + ); + depIds = new Set(result.dependencies.map(mod => mod.id)); + assert.deepEqual(depIds, new Set(["root_1.0.0", "foo_2.0.0"])); + }); + it("highlights dependencies with no release for the factorio version", async function() { + setPortalModRelease("root", "1.0.0", "2.0", ["foo"]); + setPortalModRelease("foo", "1.0.0", "2.1", []); + + const result = await controlConnection.handleModDependencyResolveRequest( + new lib.ModDependencyResolveRequest([new ModDependency("root")], "2.0") + ); + + assert.deepEqual(result.errors, new Map([ + ["base", "notFound"], + ["foo", "notFound"], + ])); + + assert.equal(result.dependencies.length, 1); + assert.equal(result.dependencies[0].id, "root_1.0.0"); + }); it("rejects when a network error occurs", async function() { lib.ModStore.fetchModReleases = function() { throw new Error("Mock network error"); @@ -484,7 +550,7 @@ describe("messages/mod", function() { "pyalienlife", "pyalienlifegraphics", "pyalienlifegraphics2", "pyalienlifegraphics3", "pycoalprocessing", "pycoalprocessinggraphics", "pyfusionenergy", "pyfusionenergygraphics", "pypetroleumhandling", "pypetroleumhandlinggraphics", "pyrawores", "pyraworesgraphics", - "pyhightech", "pyhightechgraphics", "pyindustry", "pyindustrygraphics", "enable-all-feature-flags", + "pyhightech", "pyhightechgraphics", "pyindustry", "pyindustrygraphics", ])); }); });