mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
The staging copy made by Config.set() went through the constructor, so plugin migrations ran a second time on the live fields. A version-gated migration was applied twice when setPluginVersions() changed the version. Staging now copies the fields with update() instead. A config saved without <plugin>.version got the running version as its default, so setPluginVersions() saw no change and nothing saved the stamp. The constructor now writes the registered plugin versions after the migrations run and marks the config dirty when that changes a loaded value. Controller.bootstrap() saves the instances that came out dirty, and setPluginVersions() is gone. Restructure the SyncHook and plugin config tests by method, and suggest the controller config version for role migrations in the docs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
66 lines
2.0 KiB
JavaScript
66 lines
2.0 KiB
JavaScript
import assert from "node:assert/strict";
|
|
|
|
import * as lib from "@clusterio/lib";
|
|
|
|
|
|
describe("lib/SyncHook", function() {
|
|
describe("class SyncHook", function() {
|
|
let hook;
|
|
beforeEach(function() {
|
|
hook = new lib.SyncHook();
|
|
});
|
|
|
|
describe(".attach()", function() {
|
|
it("should track attached handlers", function() {
|
|
assert.equal(hook.size, 0);
|
|
hook.attach("alpha", value => value);
|
|
hook.attach("beta", value => value);
|
|
assert.equal(hook.size, 2);
|
|
assert.deepEqual([...hook.attached], ["alpha", "beta"]);
|
|
});
|
|
it("should reject duplicate handler names", function() {
|
|
hook.attach("alpha", value => value);
|
|
assert.throws(
|
|
() => hook.attach("alpha", value => value),
|
|
new Error("Handler with name alpha is already attached")
|
|
);
|
|
});
|
|
});
|
|
describe(".detach()", function() {
|
|
it("should remove the named handler", function() {
|
|
hook.attach("alpha", value => value);
|
|
hook.attach("beta", value => value);
|
|
hook.detach("alpha");
|
|
assert.deepEqual([...hook.attached], ["beta"]);
|
|
});
|
|
});
|
|
describe(".clear()", function() {
|
|
it("should remove all handlers", function() {
|
|
hook.attach("alpha", value => value);
|
|
hook.attach("beta", value => value);
|
|
hook.clear();
|
|
assert.equal(hook.size, 0);
|
|
});
|
|
});
|
|
describe(".reduce()", function() {
|
|
it("should pass the value through handlers in attach order", function() {
|
|
hook.attach("alpha", value => [...value, "alpha"]);
|
|
hook.attach("beta", value => [...value, "beta"]);
|
|
assert.deepEqual(hook.reduce([]), ["alpha", "beta"]);
|
|
});
|
|
it("should return the value unchanged with no handlers", function() {
|
|
const value = {};
|
|
assert.equal(hook.reduce(value), value);
|
|
});
|
|
it("should rethrow errors as a PluginError named after the handler", function() {
|
|
hook.attach("alpha", () => { throw new Error("failed"); });
|
|
assert.throws(
|
|
() => hook.reduce(1),
|
|
err => err instanceof lib.PluginError && err.pluginName === "alpha"
|
|
&& err.original.message === "failed"
|
|
);
|
|
});
|
|
});
|
|
});
|
|
});
|