mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 15:04:52 +09:00
Refactor the Config and ConfigGroup classes to match the JSON data class pattern with toJSON, toRemote and fromJSON methods replacing the load, init, and serialize methods. Since fromJSON requires extra information the messages structures passes around the plain JSON representation of the configs instead of serialising instances of the config classes automatically.
756 lines
23 KiB
JavaScript
756 lines
23 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);
|
|
});
|
|
it("should initialize all fields with defaults", function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
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", function() {
|
|
let testInstance = new TestGroup({ location: "remote" });
|
|
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", function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
assert.equal(testInstance.name, "test_group");
|
|
});
|
|
});
|
|
|
|
describe(".toJSON()", function() {
|
|
it("should serialize a basic group", function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
assert.deepEqual(testInstance.toJSON(), {
|
|
name: "test_group",
|
|
fields: {
|
|
enum: "b",
|
|
test: null,
|
|
func: 42,
|
|
bool: false,
|
|
json: {},
|
|
priv: null,
|
|
},
|
|
});
|
|
});
|
|
});
|
|
|
|
describe(".toRemote()", function() {
|
|
it("should leave out inaccessible fields", function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
assert.deepEqual(testInstance.toRemote("remote"), {
|
|
name: "test_group",
|
|
fields: {
|
|
enum: "b",
|
|
test: null,
|
|
func: 42,
|
|
bool: false,
|
|
json: {},
|
|
},
|
|
});
|
|
});
|
|
});
|
|
|
|
describe(".fromJSON()", function() {
|
|
it("should load a basic group", function() {
|
|
let testInstance = TestGroup.fromJSON({ name: "test_group", fields: {
|
|
enum: "c",
|
|
test: "blah",
|
|
func: 22,
|
|
bool: null,
|
|
json: { valid: true },
|
|
priv: "bar",
|
|
}}, mockConfig);
|
|
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", function() {
|
|
let testInstance = TestGroup.fromJSON({ name: "test_group", fields: { enum: "a" } }, mockConfig);
|
|
assert.equal(testInstance.get("enum"), "a");
|
|
assert.equal(testInstance.get("test"), null);
|
|
assert.equal(testInstance.get("func"), 42);
|
|
});
|
|
it("should ignore inaccessible fields", function() {
|
|
let remoteConfig = new events.EventEmitter();
|
|
remoteConfig.location = "remote";
|
|
let testInstance = TestGroup.fromJSON({ name: "test_group", fields: { priv: "bad" } }, remoteConfig);
|
|
assert.equal(testInstance._fields.get("priv"), undefined);
|
|
});
|
|
|
|
it("should preserve unknown fields when serialized back", function() {
|
|
let testFields = {
|
|
enum: "a",
|
|
test: "blah",
|
|
func: 50,
|
|
bool: false,
|
|
json: {},
|
|
priv: null,
|
|
alpha: null,
|
|
beta: "decay",
|
|
gamma: 99,
|
|
};
|
|
|
|
let testInstance = TestGroup.fromJSON({ name: "test_group", fields: testFields }, mockConfig);
|
|
assert.deepEqual(testInstance.toJSON().fields, testFields);
|
|
});
|
|
});
|
|
|
|
describe(".update()", function() {
|
|
it("should skip updating invalid values", function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
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", function() {
|
|
let testInstance = new TestGroup(mockConfig);
|
|
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(function() {
|
|
testInstance = new TestGroup(mockConfig, {
|
|
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(function() {
|
|
testInstance = new TestGroup(mockConfig, {
|
|
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(function() {
|
|
testInstance = TestGroup.fromJSON(
|
|
{ name: "test_group", fields: { enum: "a", test: "blah", func: 27 }},
|
|
mockConfig,
|
|
);
|
|
});
|
|
|
|
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(function() {
|
|
testInstance = TestGroup.fromJSON(
|
|
{ name: "test_group", fields: { enum: "a", test: "blah", func: 27 }},
|
|
mockConfig,
|
|
);
|
|
});
|
|
|
|
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")
|
|
);
|
|
});
|
|
it("should initialize all fields", function() {
|
|
let testInstance = new TestConfig("local");
|
|
assert.equal(testInstance.get("alpha.foo"), null);
|
|
assert.deepEqual(testInstance.get("beta.bar"), {});
|
|
});
|
|
});
|
|
|
|
describe(".toJSON()", function() {
|
|
it("should serialize a basic config", function() {
|
|
let testInstance = new TestConfig("local");
|
|
assert.deepEqual(testInstance.toJSON(), {
|
|
groups: [
|
|
{
|
|
name: "alpha",
|
|
fields: { foo: null },
|
|
},
|
|
{
|
|
name: "beta",
|
|
fields: { bar: {} },
|
|
},
|
|
],
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("static .fromJSON()", function() {
|
|
it("should throw on incorrect input passed", function() {
|
|
assert.throws(
|
|
() => TestConfig.fromJSON(null, "local"),
|
|
new Error("Invalid config")
|
|
);
|
|
assert.throws(
|
|
() => TestConfig.fromJSON(undefined, "local"),
|
|
new Error("Invalid config")
|
|
);
|
|
assert.throws(
|
|
() => TestConfig.fromJSON({ groups: null }, "local"),
|
|
new Error("Invalid config")
|
|
);
|
|
});
|
|
|
|
it("should load defaults for missing serialized groups", function() {
|
|
let testInstance = TestConfig.fromJSON({ groups: [{ name: "alpha", fields: { foo: "a" }}] }, "local");
|
|
assert.equal(testInstance.get("alpha.foo"), "a");
|
|
assert.deepEqual(testInstance.get("beta.bar"), {});
|
|
});
|
|
|
|
it("should preserve unknown groups when serialized back", function() {
|
|
let testGroups = [
|
|
{
|
|
name: "extra",
|
|
fields: { blah: true, spam: "foobar" },
|
|
},
|
|
{
|
|
name: "alpha",
|
|
fields: { foo: "true" },
|
|
},
|
|
{
|
|
name: "beta",
|
|
fields: { bar: { value: 20 }},
|
|
},
|
|
];
|
|
let testInstance = TestConfig.fromJSON({ groups: testGroups }, "local");
|
|
assert.deepEqual(testInstance.toJSON().groups, testGroups);
|
|
});
|
|
});
|
|
|
|
describe(".update()", function() {
|
|
it("should update a basic config", function() {
|
|
let testInstance = new TestConfig("local");
|
|
testInstance.update({ groups: [
|
|
{
|
|
name: "extra",
|
|
fields: { blah: true, spam: "baz" },
|
|
},
|
|
{
|
|
name: "beta",
|
|
fields: { bar: { value: 30 }},
|
|
},
|
|
]}, false);
|
|
|
|
assert.deepEqual(testInstance.toJSON(), {
|
|
groups: [
|
|
{
|
|
name: "extra",
|
|
fields: { blah: true, spam: "baz" },
|
|
},
|
|
{
|
|
name: "alpha",
|
|
fields: { foo: null },
|
|
},
|
|
{
|
|
name: "beta",
|
|
fields: { bar: { value: 30 }},
|
|
},
|
|
],
|
|
});
|
|
});
|
|
});
|
|
|
|
describe(".group()", function() {
|
|
it("should retrieve a given group", function() {
|
|
let testInstance = new TestConfig("local");
|
|
assert(testInstance.group("alpha") instanceof AlphaGroup);
|
|
});
|
|
});
|
|
|
|
describe(".canAccess()", function() {
|
|
it("should throw if group does not exist", function() {
|
|
let testInstance = new TestConfig("local");
|
|
assert.throws(() => testInstance.canAccess("invalid"), new Error("No config group named 'invalid'"));
|
|
});
|
|
|
|
it("should throw if no field is specified", function() {
|
|
let testInstance = new TestConfig("local");
|
|
assert.throws(() => testInstance.canAccess("alpha"), new Error("No field named ''"));
|
|
});
|
|
|
|
it("should return true for an accessible field", function() {
|
|
let testInstance = new TestConfig("local");
|
|
assert.equal(testInstance.canAccess("alpha.foo"), true);
|
|
});
|
|
});
|
|
|
|
describe(".get()", function() {
|
|
it("should throw if group does not exist", function() {
|
|
let testInstance = new TestConfig("local");
|
|
assert.throws(() => testInstance.get("invalid"), new Error("No config group named 'invalid'"));
|
|
});
|
|
|
|
it("should throw if no field is specified", function() {
|
|
let testInstance = new TestConfig("local");
|
|
assert.throws(() => testInstance.get("alpha"), new Error("No field named ''"));
|
|
});
|
|
});
|
|
|
|
describe(".set()", function() {
|
|
it("should set the value", function() {
|
|
let testInstance = new TestConfig("local");
|
|
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(function() {
|
|
testInstance = new TestConfig("local");
|
|
called = false;
|
|
testInstance.once("fieldChanged", (group, field, prev) => {
|
|
if (group.name === "beta" && field === "bar") {
|
|
called = true;
|
|
}
|
|
});
|
|
});
|
|
|
|
it("should be called when setting a field", function() {
|
|
testInstance.set("beta.bar", { value: 1 });
|
|
assert(called, "fieldChanged was not called");
|
|
});
|
|
|
|
it("should be called when updating a config", function() {
|
|
testInstance.update({
|
|
location: "local",
|
|
groups: [{ name: "beta", fields: { bar: { value: 1 }}}],
|
|
}, true);
|
|
assert(called, "fieldChanged was not called");
|
|
});
|
|
|
|
it("should be called when setting a prop", function() {
|
|
testInstance.setProp("beta.bar", "value", 2);
|
|
assert(called, "fieldChanged was not called");
|
|
});
|
|
});
|
|
});
|
|
});
|