mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 07:04:52 +09:00
Move all functions and classes currently available through lib/name and libName to be under a single flat namespace in lib. This make reorganising the lib namespace much simpler as the location of symbols can move without breaking the consumers of lib. The multi-entrypoint design was already problematic for the web plugin system which couldn't effectively use it due to how webpack's shared module system is awkward to set up with multiple entrypoints per package.
797 lines
24 KiB
JavaScript
797 lines
24 KiB
JavaScript
"use strict";
|
|
const lib = require("@clusterio/lib");
|
|
const assert = require("assert").strict;
|
|
const events = require("events");
|
|
|
|
|
|
describe("lib/config/classes", function() {
|
|
describe("ConfigGroup", function() {
|
|
let mockConfig = new events.EventEmitter();
|
|
mockConfig.location = "local";
|
|
class TestGroup extends lib.ConfigGroup { }
|
|
TestGroup.defaultAccess = ["local", "remote"];
|
|
TestGroup.groupName = "test_group";
|
|
describe(".define()", function() {
|
|
it("should throw if groupName is not set", function() {
|
|
class NoGroupName extends lib.ConfigGroup { }
|
|
assert.throws(
|
|
() => NoGroupName.define({ name: "a", type: "string", optional: true }),
|
|
new Error("Expected ConfigGroup class NoGroupName to have the groupName property set to a string")
|
|
);
|
|
});
|
|
it("should throw on unknown properties", function() {
|
|
assert.throws(
|
|
() => TestGroup.define({ name: "a", type: "string", optional: true, invalid: true }),
|
|
new Error("Unknown property invalid")
|
|
);
|
|
});
|
|
it("should throw on invalid properties", function() {
|
|
for (let [def, error] of [
|
|
[
|
|
{ access: "local", name: "a", type: "string", optional: true },
|
|
"access must be an array",
|
|
],
|
|
[
|
|
{ name: "a", type: "invalid", optional: true },
|
|
"invalid is not a valid type",
|
|
],
|
|
[
|
|
{ name: [], type: "string", optional: true },
|
|
"name must be a string",
|
|
],
|
|
[
|
|
{ name: "a", type: "string", enum: true, optional: true },
|
|
"enum must be an array",
|
|
],
|
|
[
|
|
{ name: "a", title: 2, type: "string", optional: true },
|
|
"title must be a string",
|
|
],
|
|
[
|
|
{ name: "a", description: 2, type: "string", optional: true },
|
|
"description must be a string",
|
|
],
|
|
[
|
|
{ name: "a", type: "string", optional: "yes" },
|
|
"optional must be a boolean",
|
|
],
|
|
[
|
|
{ name: "a", type: "string", initial_value: 1 },
|
|
"initial_value must match the type or be a function",
|
|
],
|
|
[
|
|
{ name: "a", type: "string" },
|
|
"Non-optional field a needs an initial_value",
|
|
],
|
|
]) {
|
|
assert.throws(() => TestGroup.define(def), new Error(error));
|
|
}
|
|
});
|
|
it("should throw on defaultAccess not set", function() {
|
|
class NoAccessGroup extends lib.ConfigGroup { }
|
|
NoAccessGroup.groupName = "no_access";
|
|
assert.throws(
|
|
() => NoAccessGroup.define({ name: "a", type: "string", optional: true }),
|
|
new Error("access not set and no defaultAccess defined for NoAccessGroup")
|
|
);
|
|
});
|
|
it("should throw on missing properties", function() {
|
|
assert.throws(
|
|
() => TestGroup.define({ type: "string", optional: true }),
|
|
new Error("name is required when defining an field")
|
|
);
|
|
assert.throws(
|
|
() => TestGroup.define({ name: "a", optional: true }),
|
|
new Error("type is required when defining an field")
|
|
);
|
|
});
|
|
it("should allow defining entries", function() {
|
|
TestGroup.define({ name: "test", type: "string", optional: true });
|
|
TestGroup.define({ name: "func", type: "number", initial_value: () => 42 });
|
|
TestGroup.define({ name: "bool", type: "boolean", initial_value: false, optional: true });
|
|
TestGroup.define({ name: "json", type: "object", initial_value: {}, optional: true });
|
|
TestGroup.define({ name: "priv", access: ["local"], type: "string", optional: true });
|
|
|
|
assert(TestGroup._definitions.has("test"), "field test was not defined");
|
|
assert(TestGroup._definitions.has("func"), "field func was not defined");
|
|
assert(TestGroup._definitions.has("bool"), "field bool was not defined");
|
|
assert(TestGroup._definitions.has("json"), "field json was not defined");
|
|
assert(TestGroup._definitions.has("priv"), "field priv was not defined");
|
|
});
|
|
|
|
it("should throw on already defined entries", function() {
|
|
assert.throws(
|
|
() => TestGroup.define({ name: "test", type: "string", optional: true }),
|
|
new Error("Config field test has already been defined")
|
|
);
|
|
});
|
|
|
|
it("should set the entries on the class", function() {
|
|
let field = {
|
|
access: ["local", "remote"],
|
|
type: "string",
|
|
name: "enum",
|
|
title: "Enum",
|
|
description: "Enum thingy",
|
|
restartRequired: true,
|
|
enum: ["a", "b", "c"],
|
|
optional: true,
|
|
initial_value: "b",
|
|
};
|
|
TestGroup.define(field);
|
|
// Generated properties
|
|
field.fullName = "test_group.enum";
|
|
|
|
assert.deepEqual(TestGroup._definitions.get("enum"), field);
|
|
});
|
|
});
|
|
|
|
describe("get definitions", function() {
|
|
it("should give the field definitions", function() {
|
|
assert.equal(TestGroup.definitions, TestGroup._definitions);
|
|
});
|
|
});
|
|
|
|
describe(".finalize()", function() {
|
|
it("should throw if groupName is not set", function() {
|
|
class NoGroupName extends lib.ConfigGroup { }
|
|
assert.throws(
|
|
() => NoGroupName.finalize(),
|
|
new Error("Expected ConfigGroup class NoGroupName to have the groupName property set to a string")
|
|
);
|
|
});
|
|
it("should throw when creating an instance before finalize", function() {
|
|
assert.throws(
|
|
() => new TestGroup(mockConfig),
|
|
new Error("Cannot instantiate incomplete ConfigGroup class TestGroup")
|
|
);
|
|
});
|
|
|
|
it("should not throw", function() {
|
|
TestGroup.finalize();
|
|
});
|
|
|
|
it("should throw when calling define after finalize", function() {
|
|
assert.throws(
|
|
() => TestGroup.define({}),
|
|
new Error("Cannot define field for ConfigGroup class TestGroup after it has been finalized")
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("constructor", function() {
|
|
it("should create an instance", function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
});
|
|
});
|
|
|
|
describe(".init()", function() {
|
|
it("should initialize all fields with defaults", async function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
await testInstance.init();
|
|
|
|
assert.equal(testInstance.get("enum"), "b");
|
|
assert.equal(testInstance.get("test"), null);
|
|
assert.equal(testInstance.get("func"), 42);
|
|
assert.equal(testInstance.get("priv"), null);
|
|
});
|
|
it("should not initalize inaccessible fields", async function() {
|
|
let testInstance = new TestGroup({ location: "remote" });
|
|
await testInstance.init();
|
|
assert.equal(testInstance._fields.get("enum"), "b");
|
|
assert.equal(testInstance._fields.get("priv"), undefined);
|
|
});
|
|
});
|
|
|
|
describe("get name", function() {
|
|
it("should give the name of the group", async function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
await testInstance.init();
|
|
assert.equal(testInstance.name, "test_group");
|
|
});
|
|
});
|
|
|
|
describe(".serialize()", function() {
|
|
it("should serialize a basic group", async function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
await testInstance.init();
|
|
|
|
assert.deepEqual(testInstance.serialize(), {
|
|
name: "test_group",
|
|
fields: {
|
|
enum: "b",
|
|
test: null,
|
|
func: 42,
|
|
bool: false,
|
|
json: {},
|
|
priv: null,
|
|
},
|
|
});
|
|
});
|
|
it("should leave out inaccessible fields", async function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
await testInstance.init();
|
|
|
|
assert.deepEqual(testInstance.serialize("remote"), {
|
|
name: "test_group",
|
|
fields: {
|
|
enum: "b",
|
|
test: null,
|
|
func: 42,
|
|
bool: false,
|
|
json: {},
|
|
},
|
|
});
|
|
});
|
|
});
|
|
|
|
describe(".load()", function() {
|
|
it("should load a basic group", async function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
await testInstance.load({ name: "test_group", fields: {
|
|
enum: "c",
|
|
test: "blah",
|
|
func: 22,
|
|
bool: null,
|
|
json: { valid: true },
|
|
priv: "bar",
|
|
}});
|
|
|
|
assert.equal(testInstance.get("enum"), "c");
|
|
assert.equal(testInstance.get("test"), "blah");
|
|
assert.equal(testInstance.get("func"), 22);
|
|
assert.equal(testInstance.get("bool"), null);
|
|
assert.equal(testInstance.get("priv"), "bar");
|
|
assert.deepEqual(testInstance.get("json"), { valid: true });
|
|
});
|
|
it("should load defaults for missing serialized fields", async function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
await testInstance.load({ name: "test_group", fields: { enum: "a" } });
|
|
|
|
assert.equal(testInstance.get("enum"), "a");
|
|
assert.equal(testInstance.get("test"), null);
|
|
assert.equal(testInstance.get("func"), 42);
|
|
});
|
|
it("should ignore inaccessible fields", async function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
await testInstance.load({ name: "test_group", fields: { priv: "bad" } }, "remote");
|
|
assert.equal(testInstance.get("priv"), null);
|
|
});
|
|
|
|
it("should preserve unknown fields when serialized back", async function() {
|
|
let testFields = {
|
|
enum: "a",
|
|
test: "blah",
|
|
func: 50,
|
|
bool: false,
|
|
json: {},
|
|
priv: null,
|
|
alpha: null,
|
|
beta: "decay",
|
|
gamma: 99,
|
|
};
|
|
|
|
let testInstance = new TestGroup(mockConfig);
|
|
await testInstance.load({ name: "test_group", fields: testFields });
|
|
|
|
assert.deepEqual(testInstance.serialize().fields, testFields);
|
|
});
|
|
});
|
|
|
|
describe(".update()", function() {
|
|
it("should skip updating invalid values", async function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
await testInstance.init();
|
|
testInstance.update({ name: "test_group", fields: { enum: "wrong", test: 3, func: null }}, false);
|
|
|
|
assert.equal(testInstance.get("enum"), "b");
|
|
assert.equal(testInstance.get("test"), null);
|
|
assert.equal(testInstance.get("func"), 42);
|
|
});
|
|
it("should skip updating inaccessible fields", async function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
await testInstance.init();
|
|
testInstance.update(
|
|
{ name: "test_group", fields: { test: "a", priv: "bad" }}, false, "remote"
|
|
);
|
|
|
|
assert.equal(testInstance.get("test"), "a");
|
|
assert.equal(testInstance.get("priv"), null);
|
|
});
|
|
|
|
it("should throw on invalid input", function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
assert.throws(
|
|
() => testInstance.update(),
|
|
new Error("Expected object, not undefined for ConfigGroup")
|
|
);
|
|
assert.throws(
|
|
() => testInstance.update({}, false),
|
|
new Error("Expected group name test_group, not undefined")
|
|
);
|
|
assert.throws(
|
|
() => testInstance.update({ name: "test_group" }, false),
|
|
new Error("Expected fields to be an object, not undefined")
|
|
);
|
|
assert.throws(
|
|
() => testInstance.update({ name: "test_group", fields: [] }, false),
|
|
new Error("Expected fields to be an object, not array")
|
|
);
|
|
assert.throws(
|
|
() => testInstance.update({ name: "test_group", fields: null }, false),
|
|
new Error("Expected fields to be an object, not null")
|
|
);
|
|
});
|
|
});
|
|
|
|
describe(".canAccess()", function() {
|
|
let testInstance;
|
|
before(async function() {
|
|
testInstance = new TestGroup(mockConfig);
|
|
await testInstance.load({ name: "test_group", fields: {
|
|
enum: "a", priv: "blah", func: 27,
|
|
}});
|
|
});
|
|
it("should return true for fields that are accessible", function() {
|
|
for (let field of ["enum", "test", "func", "bool", "json"]) {
|
|
assert.equal(testInstance.canAccess(field), true);
|
|
assert.equal(testInstance.canAccess(field, "local"), true);
|
|
assert.equal(testInstance.canAccess(field, "remote"), true);
|
|
}
|
|
assert.equal(testInstance.canAccess("priv"), true);
|
|
assert.equal(testInstance.canAccess("priv", "local"), true);
|
|
assert.equal(testInstance.canAccess("priv", "remote"), false);
|
|
});
|
|
});
|
|
|
|
describe(".get()", function() {
|
|
let testInstance;
|
|
before(async function() {
|
|
testInstance = new TestGroup(mockConfig);
|
|
await testInstance.load({ name: "test_group", fields: {
|
|
enum: "a", priv: "blah", func: 27,
|
|
}});
|
|
});
|
|
it("should retreive value of field", function() {
|
|
assert.equal(testInstance.get("enum"), "a");
|
|
assert.equal(testInstance.get("priv"), "blah");
|
|
assert.equal(testInstance.get("func"), 27);
|
|
});
|
|
it("should throw if field is inaccessible", function() {
|
|
assert.throws(
|
|
() => testInstance.get("priv", "remote"),
|
|
new lib.InvalidAccess("Field 'priv' is not accessible from remote")
|
|
);
|
|
});
|
|
});
|
|
|
|
describe(".set()", function() {
|
|
let testInstance;
|
|
before(async function() {
|
|
testInstance = new TestGroup(mockConfig);
|
|
await testInstance.load({ name: "test_group", fields: { enum: "a", test: "blah", func: 27 }});
|
|
});
|
|
|
|
it("should throw if field does not exist", function() {
|
|
assert.throws(
|
|
() => testInstance.set("bar", 1),
|
|
new lib.InvalidField("No field named 'bar'")
|
|
);
|
|
});
|
|
|
|
it("should throw if field is inaccesible", function() {
|
|
assert.throws(
|
|
() => testInstance.set("priv", "bad", "remote"),
|
|
new lib.InvalidAccess("Field 'priv' is not accessible from remote")
|
|
);
|
|
});
|
|
|
|
it("should throw if field is not in enum", function() {
|
|
assert.throws(
|
|
() => testInstance.set("enum", "bar"),
|
|
new Error("Expected one of [a, b, c], not bar")
|
|
);
|
|
});
|
|
|
|
it("should work if field is in enum", function() {
|
|
testInstance.set("enum", "c");
|
|
assert.equal(testInstance.get("enum"), "c");
|
|
});
|
|
|
|
it("should throw if field is not optional", function() {
|
|
assert.throws(
|
|
() => testInstance.set("func", null),
|
|
new Error("Field func cannot be null")
|
|
);
|
|
});
|
|
|
|
it("should work if field is optional", function() {
|
|
testInstance.set("test", "spam");
|
|
assert.equal(testInstance.get("test"), "spam");
|
|
});
|
|
|
|
it("should throw if field is of wrong type", function() {
|
|
assert.throws(
|
|
() => testInstance.set("test", 1),
|
|
new Error("Expected type of test to be string, not number")
|
|
);
|
|
});
|
|
|
|
it("should treat empty string as null", function() {
|
|
testInstance.set("test", "");
|
|
assert.equal(testInstance.get("test"), null);
|
|
});
|
|
|
|
it("should auto convert string to boolean if possible", function() {
|
|
testInstance.set("bool", "true");
|
|
assert.equal(testInstance.get("bool"), true);
|
|
testInstance.set("bool", "false");
|
|
assert.equal(testInstance.get("bool"), false);
|
|
|
|
assert.throws(
|
|
() => testInstance.set("bool", "blah"),
|
|
new lib.InvalidValue("Expected type of bool to be boolean, not string")
|
|
);
|
|
});
|
|
|
|
it("should auto convert string to number if possible", function() {
|
|
for (let s of [
|
|
"1",
|
|
"+23",
|
|
".23e5",
|
|
"-.1e-2",
|
|
"100.0001",
|
|
"Infinity",
|
|
]) {
|
|
testInstance.set("func", s);
|
|
assert.equal(testInstance.get("func"), Number.parseFloat(s));
|
|
}
|
|
|
|
assert.throws(
|
|
() => testInstance.set("func", "blah"),
|
|
new lib.InvalidValue("Expected type of func to be number, not string")
|
|
);
|
|
});
|
|
|
|
it("should auto convert string to object", function() {
|
|
testInstance.set("json", '{"json": true}');
|
|
assert.deepEqual(testInstance.get("json"), { json: true });
|
|
|
|
let errMsg;
|
|
try {
|
|
JSON.parse("blah");
|
|
} catch (err) {
|
|
errMsg = err.message;
|
|
}
|
|
assert.throws(
|
|
() => testInstance.set("json", "blah"),
|
|
new lib.InvalidValue(`Error parsing value for json: ${errMsg}`)
|
|
);
|
|
});
|
|
});
|
|
|
|
describe(".setProp()", function() {
|
|
let testInstance;
|
|
before(async function() {
|
|
testInstance = new TestGroup(mockConfig);
|
|
await testInstance.load({ name: "test_group", fields: {
|
|
enum: "a", test: "blah", func: 27,
|
|
}});
|
|
});
|
|
|
|
it("should throw if field does not exist", function() {
|
|
assert.throws(
|
|
() => testInstance.setProp("bar", 1),
|
|
new lib.InvalidField("No field named 'bar'")
|
|
);
|
|
});
|
|
|
|
it("should throw if field is inaccesible", function() {
|
|
assert.throws(
|
|
() => testInstance.setProp("priv", "prop", "bad", "remote"),
|
|
new lib.InvalidAccess("Field 'priv' is not accessible from remote")
|
|
);
|
|
});
|
|
|
|
it("should throw if field is not an object", function() {
|
|
assert.throws(
|
|
() => testInstance.setProp("enum", "prop", "a"),
|
|
new lib.InvalidField("Cannot set property on non-object field 'enum'")
|
|
);
|
|
});
|
|
|
|
it("should work if field is an object", function() {
|
|
testInstance.set("json", { prev: 32, test: false });
|
|
testInstance.setProp("json", "test", true);
|
|
assert.deepEqual(testInstance.get("json"), { prev: 32, test: true });
|
|
});
|
|
|
|
it("should handle field being null", function() {
|
|
testInstance.set("json", null);
|
|
testInstance.setProp("json", "test", true);
|
|
assert.deepEqual(testInstance.get("json"), { test: true });
|
|
});
|
|
|
|
it("should unset field if passed undefined", function() {
|
|
testInstance.set("json", { test: true, extra: "yes" });
|
|
testInstance.setProp("json", "extra", undefined);
|
|
assert.deepEqual(testInstance.get("json"), { test: true });
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Config", function() {
|
|
class AlphaGroup extends lib.ConfigGroup { }
|
|
AlphaGroup.defaultAccess = ["local", "remote"];
|
|
AlphaGroup.groupName = "alpha";
|
|
class BetaGroup extends lib.ConfigGroup { }
|
|
BetaGroup.defaultAccess = ["local", "remote"];
|
|
BetaGroup.groupName = "beta";
|
|
class TestConfig extends lib.Config { }
|
|
|
|
before(function() {
|
|
AlphaGroup.define({ name: "foo", type: "string", optional: true });
|
|
AlphaGroup.finalize();
|
|
TestConfig.registerGroup(AlphaGroup);
|
|
BetaGroup.define({ name: "bar", type: "object", initial_value: {} });
|
|
BetaGroup.finalize();
|
|
TestConfig.registerGroup(BetaGroup);
|
|
});
|
|
|
|
describe(".registerGroup()", function() {
|
|
it("should throw if the class is finalized", function() {
|
|
class FinalizedConfig extends lib.Config { }
|
|
FinalizedConfig.finalize();
|
|
class TestGroup extends lib.ConfigGroup { }
|
|
TestGroup.groupName = "test";
|
|
TestGroup.finalize();
|
|
|
|
assert.throws(
|
|
() => FinalizedConfig.registerGroup(TestGroup),
|
|
new Error("Cannot register group on finalized config")
|
|
);
|
|
});
|
|
it("should throw if the group is not finalized", function() {
|
|
class UnfinishedGroup extends lib.ConfigGroup { }
|
|
|
|
assert.throws(
|
|
() => TestConfig.registerGroup(UnfinishedGroup),
|
|
new Error("Group must be finalized before it can be registered")
|
|
);
|
|
});
|
|
it("should throw if the group is already registered", function() {
|
|
assert.throws(
|
|
() => TestConfig.registerGroup(AlphaGroup),
|
|
new Error("alpha has already been registered")
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("constructor", function() {
|
|
it("should throw if config is not finalized", function() {
|
|
assert.throws(
|
|
() => new TestConfig("local"),
|
|
new Error("Cannot instantiate incomplete Config class TestConfig")
|
|
);
|
|
});
|
|
it("should construct a finalized class", function() {
|
|
TestConfig.finalize();
|
|
let config = new TestConfig("local");
|
|
assert(config);
|
|
});
|
|
it("should throw if location is not passed", function() {
|
|
assert.throws(
|
|
() => new TestConfig(),
|
|
new Error("location must be a string")
|
|
);
|
|
});
|
|
});
|
|
|
|
describe(".init()", function() {
|
|
it("should initialize all fields", async function() {
|
|
let testInstance = new TestConfig("local");
|
|
await testInstance.init();
|
|
assert.equal(testInstance.get("alpha.foo"), null);
|
|
assert.deepEqual(testInstance.get("beta.bar"), {});
|
|
});
|
|
});
|
|
|
|
describe(".serialize()", function() {
|
|
it("should serialize a basic config", async function() {
|
|
let testInstance = new TestConfig("local");
|
|
await testInstance.init();
|
|
assert.deepEqual(testInstance.serialize(), {
|
|
groups: [
|
|
{
|
|
name: "alpha",
|
|
fields: { foo: null },
|
|
},
|
|
{
|
|
name: "beta",
|
|
fields: { bar: {} },
|
|
},
|
|
],
|
|
});
|
|
});
|
|
});
|
|
|
|
describe(".load()", function() {
|
|
it("should reject on incorrect input passed", async function() {
|
|
let testInstance = new TestConfig("local");
|
|
await assert.rejects(
|
|
testInstance.load(null),
|
|
new Error("Expected object, not null for config")
|
|
);
|
|
await assert.rejects(
|
|
testInstance.load(undefined),
|
|
new Error("Expected object, not undefined for config")
|
|
);
|
|
await assert.rejects(
|
|
testInstance.load({ groups: null }),
|
|
new Error("Expected groups to be an array, not null")
|
|
);
|
|
});
|
|
|
|
it("should load defaults for missing serialized groups", async function() {
|
|
let testInstance = new TestConfig("local");
|
|
await testInstance.load({ groups: [{ name: "alpha", fields: { foo: "a" }}] });
|
|
|
|
assert.equal(testInstance.get("alpha.foo"), "a");
|
|
assert.deepEqual(testInstance.get("beta.bar"), {});
|
|
});
|
|
|
|
it("should preserve unknown groups when serialized back", async function() {
|
|
let testGroups = [
|
|
{
|
|
name: "extra",
|
|
fields: { blah: true, spam: "foobar" },
|
|
},
|
|
{
|
|
name: "alpha",
|
|
fields: { foo: "true" },
|
|
},
|
|
{
|
|
name: "beta",
|
|
fields: { bar: { value: 20 }},
|
|
},
|
|
];
|
|
|
|
let testInstance = new TestConfig("local");
|
|
await testInstance.load({ groups: testGroups });
|
|
|
|
assert.deepEqual(testInstance.serialize().groups, testGroups);
|
|
});
|
|
});
|
|
|
|
describe(".update()", function() {
|
|
it("should update a basic config", async function() {
|
|
let testInstance = new TestConfig("local");
|
|
await testInstance.init();
|
|
testInstance.update({ groups: [
|
|
{
|
|
name: "extra",
|
|
fields: { blah: true, spam: "baz" },
|
|
},
|
|
{
|
|
name: "beta",
|
|
fields: { bar: { value: 30 }},
|
|
},
|
|
]}, false);
|
|
|
|
assert.deepEqual(testInstance.serialize(), {
|
|
groups: [
|
|
{
|
|
name: "extra",
|
|
fields: { blah: true, spam: "baz" },
|
|
},
|
|
{
|
|
name: "alpha",
|
|
fields: { foo: null },
|
|
},
|
|
{
|
|
name: "beta",
|
|
fields: { bar: { value: 30 }},
|
|
},
|
|
],
|
|
});
|
|
});
|
|
});
|
|
|
|
describe(".group()", function() {
|
|
it("should throw if instance is not initialized", function() {
|
|
let testInstance = new TestConfig("local");
|
|
assert.throws(
|
|
() => testInstance.group("test"),
|
|
new Error("TestConfig instance is uninitialized")
|
|
);
|
|
});
|
|
});
|
|
|
|
describe(".canAccess()", function() {
|
|
it("should throw if group does not exist", async function() {
|
|
let testInstance = new TestConfig("local");
|
|
await testInstance.init();
|
|
|
|
assert.throws(() => testInstance.canAccess("invalid"), new Error("No config group named 'invalid'"));
|
|
});
|
|
|
|
it("should throw if no field is specified", async function() {
|
|
let testInstance = new TestConfig("local");
|
|
await testInstance.init();
|
|
|
|
assert.throws(() => testInstance.canAccess("alpha"), new Error("No field named ''"));
|
|
});
|
|
|
|
it("should return true for an accessible field", async function() {
|
|
let testInstance = new TestConfig("local");
|
|
await testInstance.init();
|
|
|
|
assert.equal(testInstance.canAccess("alpha.foo"), true);
|
|
});
|
|
});
|
|
|
|
describe(".get()", function() {
|
|
it("should throw if group does not exist", async function() {
|
|
let testInstance = new TestConfig("local");
|
|
await testInstance.init();
|
|
|
|
assert.throws(() => testInstance.get("invalid"), new Error("No config group named 'invalid'"));
|
|
});
|
|
|
|
it("should throw if no field is specified", async function() {
|
|
let testInstance = new TestConfig("local");
|
|
await testInstance.init();
|
|
|
|
assert.throws(() => testInstance.get("alpha"), new Error("No field named ''"));
|
|
});
|
|
});
|
|
|
|
describe(".set()", function() {
|
|
it("should set the value", async function() {
|
|
let testInstance = new TestConfig("local");
|
|
await testInstance.init();
|
|
|
|
testInstance.set("alpha.foo", "new value");
|
|
assert.equal(testInstance.get("alpha.foo"), "new value");
|
|
});
|
|
});
|
|
|
|
describe("get groups", function() {
|
|
it("should give the registered group classes", function() {
|
|
assert.equal(TestConfig.groups, TestConfig._groups);
|
|
});
|
|
});
|
|
|
|
describe("fieldChanged event", function() {
|
|
let testInstance;
|
|
let called;
|
|
beforeEach(async function() {
|
|
testInstance = new TestConfig("local");
|
|
await testInstance.init();
|
|
|
|
called = false;
|
|
testInstance.once("fieldChanged", (group, field, prev) => {
|
|
if (group.name === "beta" && field === "bar") {
|
|
called = true;
|
|
}
|
|
});
|
|
});
|
|
|
|
it("should be called when setting a field", async function() {
|
|
testInstance.set("beta.bar", { value: 1 });
|
|
assert(called, "fieldChanged was not called");
|
|
});
|
|
|
|
it("should be called when updating a config", async function() {
|
|
testInstance.update({ groups: [{ name: "beta", fields: { bar: { value: 1 }}}]}, true);
|
|
assert(called, "fieldChanged was not called");
|
|
});
|
|
|
|
it("should be called when setting a prop", async function() {
|
|
testInstance.setProp("beta.bar", "value", 2);
|
|
assert(called, "fieldChanged was not called");
|
|
});
|
|
});
|
|
});
|
|
});
|