diff --git a/packages/ctl/ctl.ts b/packages/ctl/ctl.ts index ddaf1933..349cc7ec 100755 --- a/packages/ctl/ctl.ts +++ b/packages/ctl/ctl.ts @@ -143,7 +143,19 @@ interface CtlArguments { pluginList: string, } -async function startControl() { +interface InitializeParameters { + args: CtlArguments; + shouldRun: boolean; + ctlPlugins?: Map; + rootCommands?: lib.CommandTree; + controlConfig?: lib.ControlConfig; +} + +export async function initialize( + argv: string | string[], + ctlPlugins?: Map, + noLoggerTransport?: boolean, +): Promise { yargs .scriptName("clusterioctl") .usage("$0 [options]") @@ -175,38 +187,41 @@ async function startControl() { // Parse the args first to get the configured plugin list. // eslint-disable-next-line node/no-sync - let args = yargs.parseSync() as CtlArguments; + let args = yargs.parseSync(argv) as CtlArguments; - // Log stream for the ctl session. - logger.add( - new ConsoleTransport({ - errorLevels: Object.keys(levels), - level: args.logLevel, - format: new lib.TerminalFormat(), - }) - ); - lib.handleUnhandledErrors(); - - logger.verbose(`Loading available plugins from ${args.pluginList}`); - let pluginList = await lib.loadPluginList(args.pluginList); - - // If the command is plugin management we don't try to load plugins - if (args._[0] === "plugin") { - await lib.handlePluginCommand(args, pluginList, args.pluginList); - return; + // Log stream for the ctl session. Skipped in testing. + if (!noLoggerTransport) { + logger.add( + new ConsoleTransport({ + errorLevels: Object.keys(levels), + level: args.logLevel, + format: new lib.TerminalFormat(), + }) + ); + lib.handleUnhandledErrors(); } - logger.verbose("Loading Plugins"); - let ctlPlugins = await loadPlugins(pluginList); + // Discover and load plugins. This check exists to allow tests to inject plugins. + if (!ctlPlugins || args._[0] === "plugin") { + logger.verbose(`Loading available plugins from ${args.pluginList}`); + const pluginList = await lib.loadPluginList(args.pluginList); - // Add all cluster management commands including ones from plugins - let rootCommands = await commands.registerCommands(ctlPlugins, yargs); + // If the command is plugin management we don't try to load plugins + if (args._[0] === "plugin") { + await lib.handlePluginCommand(args, pluginList, args.pluginList); + return { args, shouldRun: false }; + } - // Reparse after commands have been added with help and strict checking. + logger.verbose("Loading Plugins"); + ctlPlugins = await loadPlugins(pluginList); + } + + // Add all commands including from plugins and reparse with help and strict checking. + const rootCommands = await commands.registerCommands(ctlPlugins, yargs); args = yargs .help() .strict() - .parse() as CtlArguments + .parse(argv) as CtlArguments ; let controlConfig; @@ -233,18 +248,34 @@ async function startControl() { // Handle the control-config command before trying to connect. if (args._[0] === "control-config") { await lib.handleConfigCommand(args, controlConfig); - return; + return { args, controlConfig, ctlPlugins, rootCommands, shouldRun: false }; } - // Determine which command is being executed. + return { args, controlConfig, ctlPlugins, rootCommands, shouldRun: true }; +} + +export function selectTargetCommand(args: CtlArguments, rootCommands: lib.CommandTree): lib.Command { let commandPath = [...args._] as string[]; let targetCommand: lib.CommandTree | lib.Command = rootCommands; while (commandPath.length && targetCommand instanceof lib.CommandTree) { targetCommand = targetCommand.get(commandPath.shift()!)!; } assert(targetCommand instanceof lib.Command); + return targetCommand; +} + +async function startControl() { + const { + args, + shouldRun, + ctlPlugins, + rootCommands, + controlConfig, + } = await initialize(process.argv.slice(2)); + if (!shouldRun || !ctlPlugins || !rootCommands || !controlConfig) { + return; + } - // The remaining commands require connecting to the controller. if (!controlConfig.get("control.controller_url") || !controlConfig.get("control.controller_token")) { logger.error("Missing URL and/or token to connect with. See README.md for setting up access."); process.exitCode = 1; @@ -263,6 +294,7 @@ async function startControl() { tlsCa, controlConfig.get("control.controller_token")!, ); + let control = new Control(controlConnector, controlConfig, tlsCa, ctlPlugins); try { await controlConnector.connect(); @@ -284,6 +316,7 @@ async function startControl() { }); try { + const targetCommand = selectTargetCommand(args, rootCommands); await targetCommand.run(args, control); } catch (err) { diff --git a/plugins/global_chat/test/plugin.js b/plugins/global_chat/test/plugin.js index 315df7eb..0d22c5e8 100644 --- a/plugins/global_chat/test/plugin.js +++ b/plugins/global_chat/test/plugin.js @@ -26,7 +26,6 @@ describe("global_chat plugin", function() { let instancePlugin; before(async function() { - lib.Link.register(ChatEvent); instancePlugin = new instance.InstancePlugin(info, new mock.MockInstance(), new mock.MockHost()); await instancePlugin.init(); }); diff --git a/test/integration/clusterio.js b/test/integration/clusterio.js index f4763fb8..1b100bc7 100644 --- a/test/integration/clusterio.js +++ b/test/integration/clusterio.js @@ -13,7 +13,8 @@ const { wait } = lib; const testStrings = require("../lib/factorio/test_strings"); const { TestControl, TestControlConnector, url, controlToken, slowTest, - exec, execCtl, sendRcon, getControl, spawnNode, instancesDir, factorioDir, + exec, execCtl, execCtlProcess, execHost, sendRcon, getControl, + spawnNode, instancesDir, factorioDir, } = require("./index"); @@ -39,11 +40,11 @@ async function startAltHost() { await fs.remove(path.join("temp", "test", "alt-instances")); await fs.remove(path.join("temp", "test", "alt-mods")); await execCtl(`host create-config --id 5 --name alt-host --generate-token --output ${config}`); - await exec(`node ../../packages/host --config ${config} config set host.tls_ca ../../test/file/tls/cert.pem`); - await exec(`node ../../packages/host --config ${config} config set host.instances_directory alt-instances`); + await execHost(`--config ${config} config set host.tls_ca ../../test/file/tls/cert.pem`); + await execHost(`--config ${config} config set host.instances_directory alt-instances`); const dir = path.isAbsolute(factorioDir) ? factorioDir : path.join("..", "..", factorioDir); - await exec(`node ../../packages/host --config ${config} config set host.factorio_directory ${dir}`); - await exec(`node ../../packages/host --config ${config} config set host.mods_directory alt-mods`); + await execHost(`--config ${config} config set host.factorio_directory ${dir}`); + await execHost(`--config ${config} config set host.mods_directory alt-mods`); return await spawnAltHost(config); } @@ -259,9 +260,9 @@ describe("Integration of Clusterio", function() { describe("controller config set", function() { it("sets given config option", async function() { - await execCtl('controller config set controller.name "Test Cluster"'); + await execCtl("controller config set controller.name Test-Cluster"); let result = await getControl().send(new lib.ControllerConfigGetRequest()); - assert.equal(result["controller.name"], "Test Cluster"); + assert.equal(result["controller.name"], "Test-Cluster"); }); it("should not allow setting auth_secret", async function() { await assert.rejects(execCtl("controller config set controller.auth_secret root")); @@ -277,9 +278,9 @@ describe("Integration of Clusterio", function() { describe("controller plugin update", function() { it("runs", async function() { // In dev plugins have no npm package, so best we can do is get an error from the controller - assert.rejects( + await assert.rejects( execCtl("controller plugin update foo"), - "Plugin foo is not installed on this machine" + /Plugin foo is not installed on this machine/ ); }); // Update always fails, we can not test restart option @@ -289,9 +290,9 @@ describe("Integration of Clusterio", function() { it("runs", async function() { // Default is to disallow updates, changing this value would require a restart // Additionally, it can not be changed via ctl, so best we can do is get an error from the controller - assert.rejects( + await assert.rejects( execCtl("controller plugin install foo"), - "Plugin installs are disabled on this machine" + /Plugin installs are disabled on this machine/ ); }); // Install always fails, we can not test restart option @@ -303,9 +304,9 @@ describe("Integration of Clusterio", function() { }); it("accepts --restart", async function() { // We cannot restart the controller, so we check for controller error instead - assert.rejects( + await assert.rejects( execCtl("controller update --restart"), - "Cannot restart, controller does not have a process monitor to restart it." + /Cannot restart, controller does not have a process monitor to restart it./ ); }); }); @@ -313,9 +314,9 @@ describe("Integration of Clusterio", function() { describe("controller restart", function() { it("runs", async function() { // We cannot restart the controller, so we check for controller error instead - assert.rejects( + await assert.rejects( execCtl("controller restart"), - "Cannot restart, controller does not have a process monitor to restart it." + /Cannot restart, controller does not have a process monitor to restart it./ ); }); }); @@ -329,7 +330,7 @@ describe("Integration of Clusterio", function() { describe("host config", function() { it("changes host config", async function() { await execCtl("host config set 4 host.name My-Host"); - const result = await execCtl("host config list 4"); + const result = await execCtlProcess("host config list 4"); assert(/My-Host/.test(result.stdout), "New host name not in config output"); }); it("should not allow setting host.controller_token", async function() { @@ -359,9 +360,9 @@ describe("Integration of Clusterio", function() { describe("host plugin update", function() { it("runs", async function() { // In dev plugins have no npm package, so best we can do is get an error from the host - assert.rejects( + await assert.rejects( execCtl("host plugin update 4 foo"), - "Plugin foo is not installed on this machine" + /Plugin foo is not installed on this machine/ ); }); // Update always fails, we can not test restart option @@ -371,9 +372,9 @@ describe("Integration of Clusterio", function() { it("runs", async function() { // Default is to disallow updates, changing this value would require a restart // Additionally, it can not be changed via ctl, so best we can do is get an error from the host - assert.rejects( + await assert.rejects( execCtl("host plugin install 4 foo"), - "Plugin installs are disabled on this machine" + /Plugin installs are disabled on this machine/ ); }); // Install always fails, we can not test restart option @@ -385,9 +386,9 @@ describe("Integration of Clusterio", function() { }); it("accepts --restart", async function() { // We cannot restart the host, so we check for host error instead - assert.rejects( + await assert.rejects( execCtl("host update 4 --restart"), - "Cannot restart, host does not have a process monitor to restart it." + /Cannot restart, host does not have a process monitor to restart it./ ); }); }); @@ -395,9 +396,9 @@ describe("Integration of Clusterio", function() { describe("host restart", function() { it("runs", async function() { // We cannot restart the host, so we check for host error instead - assert.rejects( + await assert.rejects( execCtl("host restart 4"), - "Cannot restart, host does not have a process monitor to restart it." + /Cannot restart, host does not have a process monitor to restart it./ ); }); }); @@ -416,9 +417,12 @@ describe("Integration of Clusterio", function() { slowTest(this); let sawDisconnected; await runWithAltHost(async () => { - getControl().hostUpdates = []; + const control = getControl(); + control.hostUpdates = []; + await wait(50); // Allow for host to update instances await execCtl("host revoke-token 5"); - for (let update of getControl().hostUpdates) { + await wait(50); // Allow controller to notify control + for (let update of control.hostUpdates) { if (update.name !== "alt-host") { continue; } @@ -448,10 +452,8 @@ describe("Integration of Clusterio", function() { assert.equal(instances.get(44).status, "unassigned", "incorrect instance status"); // Make sure the following tests does not fail due to not having internet - let value = JSON.stringify({ lan: true, public: false }).replace( - /"/g, process.platform === "win32" ? '""' : '\\"' - ); - await execCtl(`instance config set-prop test factorio.settings visibility "${value}"`); + const value = jsonArg({ lan: true, public: false }); + await execCtlProcess(`instance config set-prop test factorio.settings visibility ${value}`); await execCtl("instance config set-prop test factorio.settings require_user_verification false"); }); it("can clone an instance", async function() { @@ -466,7 +468,7 @@ describe("Integration of Clusterio", function() { }); it("errors when cloning an invalid instance", async function() { slowTest(this); - assert.rejects( + await assert.rejects( execCtl("instance create testClone --id 440 --from 441"), new lib.RequestError("Instance with ID 441 does not exist") ); @@ -500,7 +502,7 @@ describe("Integration of Clusterio", function() { describe("instance save list", function() { it("lists the created save", async function() { slowTest(this); - let result = await execCtl("instance save list test"); + let result = await execCtlProcess("instance save list test"); assert(/world\.zip/.test(result.stdout), "world.zip not present in list save output"); }); }); @@ -615,7 +617,7 @@ describe("Integration of Clusterio", function() { assert(r1.log.some(info => /\[COMMAND\]/.test(info.message)), "Command was not sent"); await execCtl("instance config set test factorio.enable_script_commands false"); - assert.rejects( + await assert.rejects( execCtl("instance send-rcon test /c"), new Error( "Attempted to use script command while disabled. " + @@ -698,8 +700,8 @@ describe("Integration of Clusterio", function() { ]; for (let [prop, value] of testConfigs) { - let args = `test factorio.settings ${prop} ${jsonArg(value)}`; - await execCtl(`instance config set-prop ${args}`); + const args = `test factorio.settings ${prop} ${jsonArg(value)}`; + await execCtlProcess(`instance config set-prop ${args}`); } // Do this afterwards to leave enough to time for the @@ -909,6 +911,7 @@ describe("Integration of Clusterio", function() { await execCtl("instance config set 44 research_sync.load_plugin false"); await execCtl("instance config set 44 statistics_exporter.load_plugin false"); await execCtl("instance config set 44 subspace_storage.load_plugin false"); + await execCtl("instance config set 44 inventory_sync.load_plugin false"); await execCtl("instance start 44"); const instance = (await getInstances()).get(44); @@ -1188,7 +1191,7 @@ describe("Integration of Clusterio", function() { }); it("should allow setting all fields", async function() { const color = { r: 1, g: 0, b: 1, a: 0 }; - await execCtl( + await execCtlProcess( "mod-pack create full-pack 0.17.59 " + "--description Description " + "--mods empty_mod:1.0.0 " + @@ -1220,7 +1223,7 @@ describe("Integration of Clusterio", function() { describe("mod-pack list", function() { let result = null; it("runs", async function() { - result = await execCtl("mod-pack list"); + result = await execCtlProcess("mod-pack list"); }); it("contains defaults", function() { assert(result !== null, "Failed to return a value"); @@ -1249,7 +1252,7 @@ describe("Integration of Clusterio", function() { reference.settings["runtime-global"].set("MyDouble", { value: 12.25 }); reference.settings["runtime-per-user"].set("MyString", { value: "a-string" }); await execCtl(`mod-pack import ${reference.toModPackString()}`); - const result = await execCtl("mod-pack export imported-pack"); + const result = await execCtlProcess("mod-pack export imported-pack"); const roundtrip = lib.ModPack.fromModPackString(result.stdout.trim()); roundtrip.id = reference.id; assert.deepEqual(roundtrip, reference); @@ -1308,7 +1311,7 @@ describe("Integration of Clusterio", function() { describe("mod show", function() { it("gives details of a mod", async function() { - let result = await execCtl("mod show empty_mod 1.0.0"); + let result = await execCtlProcess("mod show empty_mod 1.0.0"); let hash = await lib.hashFile(path.join("temp", "test", "mods", "empty_mod_1.0.0.zip")); let stat = await fs.stat(path.join("temp", "test", "mods", "empty_mod_1.0.0.zip")); assert.equal( @@ -1333,14 +1336,14 @@ describe("Integration of Clusterio", function() { describe("mod list", function() { it("shows the list of mods", async function() { - let result = await execCtl("mod list"); + let result = await execCtlProcess("mod list"); assert(result.stdout.indexOf("empty_mod") !== -1, "empty_mod is not in the list"); }); }); describe("mod search", function() { it("searches the list of mods", async function() { - let result = await execCtl("mod search 1.1 name:empty_mod"); + let result = await execCtlProcess("mod search 1.1 name:empty_mod"); assert(result.stdout.indexOf("empty_mod") !== -1, "empty_mod is not in the result"); }); }); @@ -1415,7 +1418,7 @@ describe("Integration of Clusterio", function() { describe("role edit", function() { it("should modify the given role", async function() { let args = "--name new --description \"A new role\" --set-perms"; - await execCtl(`role edit temp ${args}`); + await execCtlProcess(`role edit temp ${args}`); let roles = await getControl().send(new lib.RoleListRequest()); let newRole = roles.find(role => role.name === "new"); if (newRole) { newRole.updatedAtMs = 0; } @@ -1497,7 +1500,7 @@ describe("Integration of Clusterio", function() { describe("user set-roles", function() { it("should set the roles on the user", async function() { getControl().userUpdates = []; - await execCtl('user set-roles temp "Cluster Admin"'); + await execCtlProcess('user set-roles temp "Cluster Admin"'); let users = await getControl().send(new lib.UserListRequest()); let tempUser = users.find(user => user.id === "temp"); assert.deepEqual(tempUser.roleIds, new Set([0])); @@ -1505,7 +1508,7 @@ describe("Integration of Clusterio", function() { }); it("should restrict actions based on roles", async function() { - await execCtl('user set-roles temp "Player"'); + await execCtl("user set-roles temp Player"); let tempControl; try { let tlsCa = await fs.readFile("test/file/tls/cert.pem"); @@ -1650,7 +1653,7 @@ describe("Integration of Clusterio", function() { ); }); it("should reject multiple provided options", async function() { - assert.rejects(execCtl("user import --bans --admins import-admins.json")); + await assert.rejects(execCtl("user import --bans --admins import-admins.json")); }); }); @@ -1659,7 +1662,6 @@ describe("Integration of Clusterio", function() { await execCtl("user create export_control"); }); it("should export users", async function() { - slowTest(this); await execCtl("user set-admin export_user --create"); await execCtl("user set-whitelisted export_user"); await execCtl("user export --users user-export.json"); @@ -1671,7 +1673,6 @@ describe("Integration of Clusterio", function() { }); }); it("should export bans", async function() { - slowTest(this); await execCtl("user set-banned export_ban --create"); await execCtl("user set-banned export_ban_reason --create --reason banned"); await execCtl("user export --bans ban-export.json"); @@ -1781,7 +1782,7 @@ describe("Integration of Clusterio", function() { assert(data.indexOf("restore_control") >= 0, "restore_control is missing"); }); it("should reject multiple provided options", async function() { - assert.rejects(execCtl("user restore --bans --admins restore-admins.json")); + await assert.rejects(execCtl("user restore --bans --admins restore-admins.json")); }); }); }); diff --git a/test/integration/index.js b/test/integration/index.js index baaaa7a0..7a31d23e 100644 --- a/test/integration/index.js +++ b/test/integration/index.js @@ -11,6 +11,8 @@ const events = require("events"); const lib = require("@clusterio/lib"); const { LineSplitter, ConsoleTransport, logger } = lib; +const { selectTargetCommand, initialize: initializeCtl } = require("@clusterio/ctl"); + // Make sure permissions from plugins are loaded require("../../plugins/global_chat/dist/node/index"); require("../../plugins/player_auth/dist/node/index"); @@ -84,6 +86,10 @@ class TestControl extends lib.Link { async handleUserUpdatesEvent(event) { this.userUpdates.push(...event.updates); } + + async setLogSubscriptions(args) { + // Do nothing + } } class TestControlConnector extends lib.WebSocketClientConnector { @@ -185,11 +191,27 @@ async function execHost(...args) { return await exec(...args); } -async function execCtl(...args) { +async function execCtlProcess(...args) { args[0] = `node --enable-source-maps ../../packages/ctl ${args[0]}`; return await exec(...args); } +async function execCtl(command) { + process.chdir("temp/test"); + try { + const initArgs = await initializeCtl(command, control.plugins, true); + if (!initArgs.shouldRun) { + return; + } + + control.config = initArgs.controlConfig; + const targetCommand = selectTargetCommand(initArgs.args, initArgs.rootCommands); + await targetCommand.run(initArgs.args, control); + } finally { + process.chdir("../.."); + } +} + async function sendRcon(instanceId, command) { return await control.sendTo({ instanceId }, new lib.InstanceSendRconRequest(command)); } @@ -291,33 +313,38 @@ before(async function() { await execController("config set controller.tls_private_key ../../test/file/tls/key.pem"); console.log("Setting Controller Plugins"); - await execCtl("plugin add ../../plugins/global_chat"); - await execCtl("plugin add ../../plugins/research_sync"); - await execCtl("plugin add ../../plugins/statistics_exporter"); - await execCtl("plugin add ../../plugins/subspace_storage"); - await execCtl("plugin add ../../plugins/player_auth"); + await execCtlProcess("plugin add ../../plugins/global_chat"); + await execCtlProcess("plugin add ../../plugins/research_sync"); + await execCtlProcess("plugin add ../../plugins/statistics_exporter"); + await execCtlProcess("plugin add ../../plugins/subspace_storage"); + await execCtlProcess("plugin add ../../plugins/inventory_sync"); + await execCtlProcess("plugin add ../../plugins/player_auth"); console.log("Bootstrapping"); await execController("bootstrap create-admin test"); await execController("bootstrap create-ctl-config test"); - await execCtl("control-config set control.tls_ca ../../test/file/tls/cert.pem"); + await execCtlProcess("control-config set control.tls_ca ../../test/file/tls/cert.pem"); controllerProcess = await spawnNode("controller:", "../../packages/controller run", /Started controller/); - await execCtl("host create-config --id 4 --name host --generate-token"); - const relativeFactorioDir = path.isAbsolute(factorioDir) ? factorioDir : path.join("..", "..", factorioDir); + await execCtlProcess("host create-config --id 4 --name host --generate-token"); await execHost(`config set host.factorio_directory ${relativeFactorioDir}`); await execHost("config set host.tls_ca ../../test/file/tls/cert.pem"); hostProcess = await spawnNode("host:", "../../packages/host run", /Started host/); - let tlsCa = await fs.readFile("test/file/tls/cert.pem"); - let controlConnector = new TestControlConnector(url, 2, tlsCa); + const tlsCa = await fs.readFile("test/file/tls/cert.pem"); + const controlConnector = new TestControlConnector(url, 2, tlsCa); controlConnector.token = controlToken; control = new TestControl(controlConnector); await controlConnector.connect(); + const initArgs = await initializeCtl(`--plugin-list ${pluginListPath} control-config list`, undefined, true); + control.config = initArgs.controlConfig; + control.plugins = initArgs.ctlPlugins; + control.tlsCa = tlsCa; + const testPack = lib.ModPack.fromJSON({}); testPack.id = 12; testPack.name = "subspace_storage-pack"; @@ -358,10 +385,12 @@ module.exports = { TestControl, TestControlConnector, TestHostConnector, + execCtlProcess, slowTest, get, exec, execCtl, + execHost, sendRcon, getControl, spawn, diff --git a/test/integration/instance.js b/test/integration/instance.js index ef94a935..77a654b8 100644 --- a/test/integration/instance.js +++ b/test/integration/instance.js @@ -3,7 +3,7 @@ const assert = require("assert").strict; const lib = require("@clusterio/lib"); const { - slowTest, exec, execCtl, sendRcon, getControl, + slowTest, exec, execCtl, execCtlProcess, sendRcon, getControl, } = require("./index"); const instId = 48; @@ -31,12 +31,12 @@ describe("Clusterio Instance", function() { // Create a new instance await execCtl(`instance create ${instName} --id ${instId}`); await execCtl(`instance config set ${instName} factorio.enable_whitelist true`); - await execCtl(`instance config set-prop ${instName} factorio.settings visibility "${visibility}"`); + await execCtlProcess(`instance config set-prop ${instName} factorio.settings visibility "${visibility}"`); await execCtl(`instance config set-prop ${instName} factorio.settings require_user_verification false`); await execCtl(`instance assign ${instName} 4`); for (const plugin of [ - "global_chat", "research_sync", "statistics_exporter", "subspace_storage", "player_auth", + "global_chat", "research_sync", "statistics_exporter", "subspace_storage", "player_auth", "inventory_sync", ]) { await execCtl(`instance config set ${instName} ${plugin}.load_plugin false`); } @@ -44,7 +44,7 @@ describe("Clusterio Instance", function() { // Create a new alt instance await execCtl(`instance create ${instAltName} --id ${instAltId}`); await execCtl(`instance config set ${instAltName} factorio.enable_whitelist true`); - await execCtl(`instance config set-prop ${instAltName} factorio.settings visibility "${visibility}"`); + await execCtlProcess(`instance config set-prop ${instAltName} factorio.settings visibility "${visibility}"`); await execCtl(`instance config set-prop ${instAltName} factorio.settings require_user_verification false`); await execCtl(`instance assign ${instAltName} 4`); await execCtl(`instance start ${instAltName}`); @@ -75,12 +75,12 @@ describe("Clusterio Instance", function() { if (savePatchingEnabled) { // IPC expects save patching to be enabled it("should do nothing for an unknown type", async function() { - assert.rejects(getUser("DoesNotExist"), "User should not exist"); + await assert.rejects(getUser("DoesNotExist"), "User should not exist"); await sendRcon(instId, `/sc ${requireApi} api.send_json("player_event",` + "{ type='invalid type', name='DoesNotExist' })" ); - assert.rejects(getUser("DoesNotExist"), "User was created"); + await assert.rejects(getUser("DoesNotExist"), "User was created"); }); it("should respond to a player join and leave event", async function() { await sendRcon(instId, diff --git a/test/lib/config/classes.js b/test/lib/config/classes.js index 94b47c69..4003d9b6 100644 --- a/test/lib/config/classes.js +++ b/test/lib/config/classes.js @@ -201,32 +201,16 @@ describe("lib/config/classes", function() { const filepath = path.join("temp", "test", "config_test.json"); it("should throw for file and json errors", async function() { await fs.writeFile(filepath, "abc"); - assert.rejects( - TestConfig.fromFile("local", filepath), - new Error( - `${filepath}: SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data` - ) - ); - assert.rejects( - TestConfig.fromFile("local", `${filepath}.notExist`), - ); + await assert.rejects(TestConfig.fromFile("local", filepath)); + await assert.rejects(TestConfig.fromFile("local", `${filepath}.notExist`)); }); it("should throw on incorrect input passed", async function() { await fs.writeFile(filepath, "null"); - await assert.rejects( - TestConfig.fromFile("local", filepath), - new Error("Invalid config") - ); + await assert.rejects(TestConfig.fromFile("local", filepath)); await fs.writeFile(filepath, "undefined"); - assert.rejects( - TestConfig.fromFile("local", filepath), - new Error("Invalid config") - ); + await assert.rejects(TestConfig.fromFile("local", filepath)); await fs.writeFile(filepath, "[]"); - assert.rejects( - TestConfig.fromFile("local", filepath), - new Error("Invalid config") - ); + await assert.rejects(TestConfig.fromFile("local", filepath)); }); it("should load defaults for missing fields", async function() { await fs.writeJSON(filepath, { diff --git a/test/lib/rce_ops.js b/test/lib/rce_ops.js index ec692462..c5b272b7 100644 --- a/test/lib/rce_ops.js +++ b/test/lib/rce_ops.js @@ -22,9 +22,9 @@ describe("rce_ops", function() { await lib.handlePluginUpdate("foo", [{ npmPackage: "foo" }]); }); it("rejects when plugin not installed", async function() { - assert.rejects( + await assert.rejects( lib.handlePluginUpdate("foo", []), - "Plugin foo is not installed on this machine" + /Plugin foo is not installed on this machine/ ); }); }); @@ -50,16 +50,16 @@ describe("rce_ops", function() { }); it("rejects when name too long", async function() { const pluginName = "a".repeat(215); - assert.rejects( + await assert.rejects( lib.handlePluginInstall(pluginName), - `Invalid plugin name: ${pluginName}` + { message: `Invalid plugin name: ${pluginName}` } ); }); it("rejects when invalid symbol present", async function() { const pluginName = "?"; - assert.rejects( + await assert.rejects( lib.handlePluginInstall(pluginName), - `Invalid plugin name: ${pluginName}` + { message: `Invalid plugin name: ${pluginName}` }, ); }); it("rejects unregistered packages", async function() { @@ -69,7 +69,7 @@ describe("rce_ops", function() { return { ok: false }; }; - assert.rejects(lib.handlePluginInstall("foo"), "Unknown plugin: foo"); + await assert.rejects(lib.handlePluginInstall("foo"), /Unknown plugin: foo/); assert.equal(calledWith, "https://registry.npmjs.com/foo"); }); }); diff --git a/test/lib/subscriptions.js b/test/lib/subscriptions.js index e8028fd5..48fd70c5 100644 --- a/test/lib/subscriptions.js +++ b/test/lib/subscriptions.js @@ -240,20 +240,20 @@ describe("lib/subscriptions", function() { subscriptions.handle(RegisteredEvent); }); - it("should not accept subscriptions to unregistered events", function() { + it("should not accept subscriptions to unregistered events", async function() { const request = new lib.SubscriptionRequest(RegisteredEvent.name, true); request.eventName = UnregisteredEvent.name; - assert.rejects( + await assert.rejects( subscriptions.handleRequest(getLink(0), request, addr({ controlId: 0 }), addr("controller")), - new Error(`Unregistered Event class ${UnregisteredEvent.name}`) + new Error(`Event ${UnregisteredEvent.name} is not a registered event`) ); }); - it("should not accept subscriptions to events not handled by the class", function() { + it("should not accept subscriptions to events not handled by the class", async function() { const request = new lib.SubscriptionRequest(RegisteredEvent.name, true); request.eventName = StringPermissionEvent.name; - assert.rejects( + await assert.rejects( subscriptions.handleRequest(getLink(0), request, addr({ controlId: 0 }), addr("controller")), - new Error(`Event ${StringPermissionEvent.eventName} is not a registered as subscribable`) + new Error(`Event ${StringPermissionEvent.name} is not a registered as subscribable`) ); }); it("should accept a subscription", async function() { diff --git a/test/messages/controller.test.js b/test/messages/controller.test.js index cb2c2efd..1e345475 100644 --- a/test/messages/controller.test.js +++ b/test/messages/controller.test.js @@ -28,9 +28,9 @@ describe("messages/controller", function() { }); it("rejects if updates are disabled", async function() { controller.config.set("controller.allow_remote_updates", false); - assert.rejects( + await assert.rejects( controlConnection.handleControllerUpdateRequest(new lib.ControllerUpdateRequest()), - "Remote updates are disabled on this machine" + /Remote updates are disabled on this machine/ ); }); }); diff --git a/test/messages/host.test.js b/test/messages/host.test.js index 83938147..2de73067 100644 --- a/test/messages/host.test.js +++ b/test/messages/host.test.js @@ -24,9 +24,9 @@ describe("messages/controller", function() { }); it("rejects if updates are disabled", async function() { host.config.set("host.allow_remote_updates", false); - assert.rejects( + await assert.rejects( host.handleHostUpdateRequest(new lib.HostUpdateRequest()), - "Remote updates are disabled on this machine" + /Remote updates are disabled on this machine/ ); }); }); diff --git a/test/messages/plugin.test.js b/test/messages/plugin.test.js index 63d3b5fb..ef76fbbc 100644 --- a/test/messages/plugin.test.js +++ b/test/messages/plugin.test.js @@ -115,9 +115,9 @@ describe("messages/plugin", function() { }); it("rejects if updates are disabled on the controller", async function() { controller.config.set("controller.allow_plugin_updates", false); - assert.rejects( + await assert.rejects( controlConnection.handlePluginUpdateRequest(new lib.PluginUpdateRequest("foo")), - "Plugin updates are disabled on this machine" + /Plugin updates are disabled on this machine/ ); }); it("runs on a host", async function() { @@ -127,9 +127,9 @@ describe("messages/plugin", function() { }); it("rejects if updates are disabled on the host", async function() { host.config.set("host.allow_plugin_updates", false); - assert.rejects( + await assert.rejects( host.handlePluginUpdateRequest(new lib.PluginUpdateRequest("foo")), - "Plugin updates are disabled on this machine" + /Plugin updates are disabled on this machine/ ); }); }); @@ -154,22 +154,22 @@ describe("messages/plugin", function() { controller.config.set("controller.allow_plugin_install", true); await controlConnection.handlePluginInstallRequest(new lib.PluginInstallRequest("foo")); }); - it("rejects if updates are disabled on the controller", async function() { + it("rejects if installs are disabled on the controller", async function() { controller.config.set("controller.allow_plugin_install", false); - assert.rejects( + await assert.rejects( controlConnection.handlePluginInstallRequest(new lib.PluginInstallRequest("foo")), - "Plugin updates are disabled on this machine" + /Plugin installs are disabled on this machine/ ); }); it("runs on a host", async function() { host.config.set("host.allow_plugin_install", true); await host.handlePluginInstallRequest(new lib.PluginInstallRequest("foo")); }); - it("rejects if updates are disabled on the host", async function() { + it("rejects if installs are disabled on the host", async function() { host.config.set("host.allow_plugin_install", false); - assert.rejects( + await assert.rejects( host.handlePluginInstallRequest(new lib.PluginInstallRequest("foo")), - "Plugin updates are disabled on this machine" + /Plugin installs are disabled on this machine/ ); }); }); diff --git a/test/mock.js b/test/mock.js index 14921adc..0afd1e77 100644 --- a/test/mock.js +++ b/test/mock.js @@ -218,7 +218,6 @@ class MockController { } async function createControllerPlugin(ControllerPluginClass, info) { - lib.registerPluginMessages([info]); let controller = new MockController(); let metrics = {}; let logger = new MockLogger();