mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
fix: Fix issue when there are multiple values for the same CLI parameter
* fix: added check for multiple values for the same option * Update test/unit/init/CliRunner.test.ts Co-authored-by: Ruben Verborgh <ruben@verborgh.org> * fix: made CliRunner.run sync Co-authored-by: Ruben Verborgh <ruben@verborgh.org>
This commit is contained in:
parent
12ace1b556
commit
dd5b496f1d
@ -13,10 +13,11 @@ export class CliRunner {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic run function for starting the server from a given config
|
* Generic run function for starting the server from a given config
|
||||||
|
* Made run to be non-async to lower the chance of unhandled promise rejection errors in the future.
|
||||||
* @param args - Command line arguments.
|
* @param args - Command line arguments.
|
||||||
* @param stderr - Standard error stream.
|
* @param stderr - Standard error stream.
|
||||||
*/
|
*/
|
||||||
public async run({
|
public run({
|
||||||
argv = process.argv,
|
argv = process.argv,
|
||||||
stderr = process.stderr,
|
stderr = process.stderr,
|
||||||
}: {
|
}: {
|
||||||
@ -24,7 +25,7 @@ export class CliRunner {
|
|||||||
stdin?: ReadStream;
|
stdin?: ReadStream;
|
||||||
stdout?: WriteStream;
|
stdout?: WriteStream;
|
||||||
stderr?: WriteStream;
|
stderr?: WriteStream;
|
||||||
} = {}): Promise<void> {
|
} = {}): void {
|
||||||
// Parse the command-line arguments
|
// Parse the command-line arguments
|
||||||
const { argv: params } = yargs(argv.slice(2))
|
const { argv: params } = yargs(argv.slice(2))
|
||||||
.usage('node ./bin/server.js [args]')
|
.usage('node ./bin/server.js [args]')
|
||||||
@ -44,6 +45,10 @@ export class CliRunner {
|
|||||||
if (!args[key]) {
|
if (!args[key]) {
|
||||||
throw new Error(`Missing value for argument "${key}"`);
|
throw new Error(`Missing value for argument "${key}"`);
|
||||||
}
|
}
|
||||||
|
// Check if the argument only has 1 value
|
||||||
|
if (Array.isArray(args[key])) {
|
||||||
|
throw new Error(`Multiple values were provided for: "${key}", [${args[key]}]`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -71,7 +76,7 @@ export class CliRunner {
|
|||||||
const variables = this.createVariables(params);
|
const variables = this.createVariables(params);
|
||||||
|
|
||||||
// Create and execute the server initializer
|
// Create and execute the server initializer
|
||||||
await this.createInitializer(loaderProperties, configFile, variables)
|
this.createInitializer(loaderProperties, configFile, variables)
|
||||||
.then(
|
.then(
|
||||||
async(initializer): Promise<void> => initializer.handleSafe(),
|
async(initializer): Promise<void> => initializer.handleSafe(),
|
||||||
(error: Error): void => {
|
(error: Error): void => {
|
||||||
|
@ -31,10 +31,15 @@ describe('CliRunner', (): void => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('starts the server with default settings.', async(): Promise<void> => {
|
it('starts the server with default settings.', async(): Promise<void> => {
|
||||||
await new CliRunner().run({
|
new CliRunner().run({
|
||||||
argv: [ 'node', 'script' ],
|
argv: [ 'node', 'script' ],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Wait until initializer has been called, because we can't await CliRunner.run.
|
||||||
|
await new Promise((resolve): void => {
|
||||||
|
setImmediate(resolve);
|
||||||
|
});
|
||||||
|
|
||||||
expect(ComponentsManager.build).toHaveBeenCalledTimes(1);
|
expect(ComponentsManager.build).toHaveBeenCalledTimes(1);
|
||||||
expect(ComponentsManager.build).toHaveBeenCalledWith({
|
expect(ComponentsManager.build).toHaveBeenCalledWith({
|
||||||
dumpErrorState: true,
|
dumpErrorState: true,
|
||||||
@ -64,7 +69,7 @@ describe('CliRunner', (): void => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('accepts abbreviated flags.', async(): Promise<void> => {
|
it('accepts abbreviated flags.', async(): Promise<void> => {
|
||||||
await new CliRunner().run({
|
new CliRunner().run({
|
||||||
argv: [
|
argv: [
|
||||||
'node', 'script',
|
'node', 'script',
|
||||||
'-b', 'http://pod.example/',
|
'-b', 'http://pod.example/',
|
||||||
@ -79,6 +84,11 @@ describe('CliRunner', (): void => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Wait until initializer has been called, because we can't await CliRunner.run.
|
||||||
|
await new Promise((resolve): void => {
|
||||||
|
setImmediate(resolve);
|
||||||
|
});
|
||||||
|
|
||||||
expect(ComponentsManager.build).toHaveBeenCalledTimes(1);
|
expect(ComponentsManager.build).toHaveBeenCalledTimes(1);
|
||||||
expect(ComponentsManager.build).toHaveBeenCalledWith({
|
expect(ComponentsManager.build).toHaveBeenCalledWith({
|
||||||
dumpErrorState: true,
|
dumpErrorState: true,
|
||||||
@ -105,7 +115,7 @@ describe('CliRunner', (): void => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('accepts full flags.', async(): Promise<void> => {
|
it('accepts full flags.', async(): Promise<void> => {
|
||||||
await new CliRunner().run({
|
new CliRunner().run({
|
||||||
argv: [
|
argv: [
|
||||||
'node', 'script',
|
'node', 'script',
|
||||||
'--baseUrl', 'http://pod.example/',
|
'--baseUrl', 'http://pod.example/',
|
||||||
@ -120,6 +130,11 @@ describe('CliRunner', (): void => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Wait until initializer has been called, because we can't await CliRunner.run.
|
||||||
|
await new Promise((resolve): void => {
|
||||||
|
setImmediate(resolve);
|
||||||
|
});
|
||||||
|
|
||||||
expect(ComponentsManager.build).toHaveBeenCalledTimes(1);
|
expect(ComponentsManager.build).toHaveBeenCalledTimes(1);
|
||||||
expect(ComponentsManager.build).toHaveBeenCalledWith({
|
expect(ComponentsManager.build).toHaveBeenCalledWith({
|
||||||
dumpErrorState: true,
|
dumpErrorState: true,
|
||||||
@ -147,10 +162,15 @@ describe('CliRunner', (): void => {
|
|||||||
|
|
||||||
it('exits with output to stderr when instantiation fails.', async(): Promise<void> => {
|
it('exits with output to stderr when instantiation fails.', async(): Promise<void> => {
|
||||||
manager.instantiate.mockRejectedValueOnce(new Error('Fatal'));
|
manager.instantiate.mockRejectedValueOnce(new Error('Fatal'));
|
||||||
await new CliRunner().run({
|
new CliRunner().run({
|
||||||
argv: [ 'node', 'script' ],
|
argv: [ 'node', 'script' ],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Wait until initializer has been called, because we can't await CliRunner.run.
|
||||||
|
await new Promise((resolve): void => {
|
||||||
|
setImmediate(resolve);
|
||||||
|
});
|
||||||
|
|
||||||
expect(write).toHaveBeenCalledTimes(2);
|
expect(write).toHaveBeenCalledTimes(2);
|
||||||
expect(write).toHaveBeenNthCalledWith(1,
|
expect(write).toHaveBeenNthCalledWith(1,
|
||||||
expect.stringMatching(/^Error: could not instantiate server from .*config-default\.json/u));
|
expect.stringMatching(/^Error: could not instantiate server from .*config-default\.json/u));
|
||||||
@ -163,7 +183,12 @@ describe('CliRunner', (): void => {
|
|||||||
|
|
||||||
it('exits without output to stderr when initialization fails.', async(): Promise<void> => {
|
it('exits without output to stderr when initialization fails.', async(): Promise<void> => {
|
||||||
initializer.handleSafe.mockRejectedValueOnce(new Error('Fatal'));
|
initializer.handleSafe.mockRejectedValueOnce(new Error('Fatal'));
|
||||||
await new CliRunner().run();
|
new CliRunner().run();
|
||||||
|
|
||||||
|
// Wait until initializer has been called, because we can't await CliRunner.run.
|
||||||
|
await new Promise((resolve): void => {
|
||||||
|
setImmediate(resolve);
|
||||||
|
});
|
||||||
|
|
||||||
expect(write).toHaveBeenCalledTimes(0);
|
expect(write).toHaveBeenCalledTimes(0);
|
||||||
|
|
||||||
@ -171,34 +196,65 @@ describe('CliRunner', (): void => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('exits when unknown options are passed to the main executable.', async(): Promise<void> => {
|
it('exits when unknown options are passed to the main executable.', async(): Promise<void> => {
|
||||||
await new CliRunner().run({
|
new CliRunner().run({
|
||||||
argv: [
|
argv: [
|
||||||
'node', 'script', '--foo',
|
'node', 'script', '--foo',
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Wait until initializer has been called, because we can't await CliRunner.run.
|
||||||
|
await new Promise((resolve): void => {
|
||||||
|
setImmediate(resolve);
|
||||||
|
});
|
||||||
|
|
||||||
expect(exit).toHaveBeenCalledTimes(1);
|
expect(exit).toHaveBeenCalledTimes(1);
|
||||||
expect(exit).toHaveBeenCalledWith(1);
|
expect(exit).toHaveBeenCalledWith(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('exits when no value is passed to the main executable for an argument.', async(): Promise<void> => {
|
it('exits when no value is passed to the main executable for an argument.', async(): Promise<void> => {
|
||||||
await new CliRunner().run({
|
new CliRunner().run({
|
||||||
argv: [
|
argv: [
|
||||||
'node', 'script', '-s',
|
'node', 'script', '-s',
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Wait until initializer has been called, because we can't await CliRunner.run.
|
||||||
|
await new Promise((resolve): void => {
|
||||||
|
setImmediate(resolve);
|
||||||
|
});
|
||||||
|
|
||||||
expect(exit).toHaveBeenCalledTimes(1);
|
expect(exit).toHaveBeenCalledTimes(1);
|
||||||
expect(exit).toHaveBeenCalledWith(1);
|
expect(exit).toHaveBeenCalledWith(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('exits when unknown parameters are passed to the main executable.', async(): Promise<void> => {
|
it('exits when unknown parameters are passed to the main executable.', async(): Promise<void> => {
|
||||||
await new CliRunner().run({
|
new CliRunner().run({
|
||||||
argv: [
|
argv: [
|
||||||
'node', 'script', 'foo', 'bar', 'foo.txt', 'bar.txt',
|
'node', 'script', 'foo', 'bar', 'foo.txt', 'bar.txt',
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Wait until initializer has been called, because we can't await CliRunner.run.
|
||||||
|
await new Promise((resolve): void => {
|
||||||
|
setImmediate(resolve);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(exit).toHaveBeenCalledTimes(1);
|
||||||
|
expect(exit).toHaveBeenCalledWith(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('exits when multiple values for a parameter are passed.', async(): Promise<void> => {
|
||||||
|
new CliRunner().run({
|
||||||
|
argv: [
|
||||||
|
'node', 'script', '-ll',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait until initializer has been called, because we can't await CliRunner.run.
|
||||||
|
await new Promise((resolve): void => {
|
||||||
|
setImmediate(resolve);
|
||||||
|
});
|
||||||
|
|
||||||
expect(exit).toHaveBeenCalledTimes(1);
|
expect(exit).toHaveBeenCalledTimes(1);
|
||||||
expect(exit).toHaveBeenCalledWith(1);
|
expect(exit).toHaveBeenCalledWith(1);
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user