Skip to content

Commit

Permalink
Merge pull request #6038 from TylerSustare/increase-sls-plugin-instal…
Browse files Browse the repository at this point in the history
…l-error-handling

Add more specific sub command error handling.
  • Loading branch information
pmuens committed Apr 24, 2019
2 parents b042ef0 + df984cc commit 9258801
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 0 deletions.
14 changes: 14 additions & 0 deletions lib/classes/PluginManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,20 @@ class PluginManager {
&& (isNotEntrypoint || allowEntryPoints)) {
return current.commands[name];
}
// if user is using a top level command properly, but sub commands are not
if (this.serverless.cli.loadedCommands[commandOrAlias[0]]) {
const errorMessage = [`"${name}" is not a valid sub command. Run "serverless `];
for (let i = 0; commandOrAlias[i] !== name; i++) {
errorMessage.push(`${commandOrAlias[i]}`);
if (commandOrAlias[i + 1] !== name) {
errorMessage.push(' ');
}
}
errorMessage.push('" to see a more helpful error message for this command.');
throw new this.serverless.classes.Error(errorMessage.join(''));
}

// top level command isn't valid. give a suggestion
const commandName = commandOrAlias.slice(0, index + 1).join(' ');
const suggestedCommand = getCommandSuggestion(commandName,
this.serverless.cli.loadedCommands);
Expand Down
101 changes: 101 additions & 0 deletions lib/classes/PluginManager.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1586,6 +1586,107 @@ describe('PluginManager', () => {
});
});

describe('#getCommand()', () => {
beforeEach(() => {
pluginManager.addPlugin(SynchronousPluginMock);
pluginManager.serverless.cli.loadedCommands = {
create: {
usage: 'Create new Serverless service',
lifecycleEvents: [
'create',
],
options: {
template: {
usage: 'Template for the service. Available templates: ", "aws-nodejs", "..."',
shortcut: 't',
},
},
key: 'create',
pluginName: 'Create',
},
deploy: {
usage: 'Deploy a Serverless service',
configDependent: true,
lifecycleEvents: [
'cleanup',
'initialize',
],
options: {
conceal: {
usage: 'Hide secrets from the output (e.g. API Gateway key values)',
},
stage: {
usage: 'Stage of the service',
shortcut: 's',
},
},
key: 'deploy',
pluginName: 'Deploy',
commands: {
function: {
usage: 'Deploy a single function from the service',
lifecycleEvents: [
'initialize',
'packageFunction',
'deploy',
],
options: {
function: {
usage: 'Name of the function',
shortcut: 'f',
required: true,
},
},
key: 'deploy:function',
pluginName: 'Deploy',
},
list: {
usage: 'List deployed version of your Serverless Service',
lifecycleEvents: [
'log',
],
key: 'deploy:list',
pluginName: 'Deploy',
commands: {
functions: {
usage: 'List all the deployed functions and their versions',
lifecycleEvents: [
'log',
],
key: 'deploy:list:functions',
pluginName: 'Deploy',
},
},
},
},
},
};
});
it('should give a suggestion for an unknown command', (done) => {
try {
pluginManager.getCommand(['creet']);
done('Test failed. Expected an error to be thrown');
} catch (error) {
expect(error.name).to.eql('ServerlessError');
expect(error.message).to.eql('Serverless command "creet" not found. ' +
'Did you mean "create"? Run "serverless help" for a list of all available commands.');
done();
}
});

it('should not give a suggestion for valid top level command', (done) => {
try {
pluginManager.getCommand(['deploy', 'function-misspelled']);
done('Test failed. Expected an error to be thrown');
} catch (error) {
expect(error.name).to.eql('ServerlessError');
expect(error.message).to.eql('"function-misspelled" is not a valid sub command. '
+ 'Run "serverless deploy" to see a more helpful error message for this command.');
done();
}
});
});

describe('#spawn()', () => {
it('should throw an error when the given command is not available', () => {
pluginManager.addPlugin(EntrypointPluginMock);
Expand Down

0 comments on commit 9258801

Please sign in to comment.