Skip to content

Commit

Permalink
Enforce character limit on description field/flag
Browse files Browse the repository at this point in the history
* This commit refactors the prompt validation to allow for multiple custom
validators
* This commit refactors the RegisterCommand tests to be more uniform
  with the BaseCommand test
  • Loading branch information
gregilo committed Feb 14, 2023
1 parent 5825c47 commit 4610f36
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 40 deletions.
44 changes: 41 additions & 3 deletions packages/cli/src/oclif/ZapierBaseCommand.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,53 @@ class ZapierBaseCommand extends Command {
this.log(renderList(items, { spacer: '\n', maxWidth: stdtermwidth }));
}

/**
*
* @param {Object} opts options object (as expected for this.prompt())
* @returns {string|boolean} Boolean if validation passes, string w/ error message if it doesn't
*/
_getCustomValidatation(opts) {
return (input) => {
const validators = {
required: (input) =>
input.trim() === '' ? 'This field is required.' : true,
charLimit: (input, charLimit) =>
input.length > charLimit
? `Please provide a value ${charLimit} characters or less.`
: true,
};
let aggregateResult = true;

for (const key in opts) {
if (typeof validators[key] === 'undefined') {
continue;
}

let individualResult;
if (validators[key].length > 1) {
individualResult = validators[key](input, opts[key]);
} else {
individualResult = validators[key](input);
}

if (individualResult !== true) {
aggregateResult = individualResult;
break;
}
}

return aggregateResult;
};
}

/**
* get user input
* @param {string} question the question to ask the user
* @param {object} opts `inquierer.js` opts ([read more](https://github.com/SBoudrias/Inquirer.js/#question))
*/
async prompt(question, opts = {}) {
if (typeof opts.required !== 'undefined' && opts.required) {
opts.validate = (input) =>
input.trim() === '' ? 'This field is required.' : true;
if (Object.keys(opts).length) {
opts.validate = this._getCustomValidatation(opts);
}
const { ans } = await inquirer.prompt({
type: 'string',
Expand Down
15 changes: 10 additions & 5 deletions packages/cli/src/oclif/commands/register.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ const { flags } = require('@oclif/command');

class RegisterCommand extends ZapierBaseCommand {
async perform() {
// Flag validation
this._validateEnumFlags();
if ('desc' in this.flags && this.flags.desc.length >= 140) {
throw new Error(
'Please provide a description that is 140 characters or less.'
);
}

const appMeta = await this._promptForAppMeta();

this.startSpinner(`Registering your new integration "${appMeta.title}"`);
Expand Down Expand Up @@ -69,7 +76,7 @@ class RegisterCommand extends ZapierBaseCommand {
if (!appMeta.description) {
appMeta.description = await this.prompt(
'Please provide a sentence describing your app in 140 characters or less.',
{ required: true }
{ required: true, charLimit: 140 }
);
}

Expand Down Expand Up @@ -148,13 +155,11 @@ RegisterCommand.flags = buildFlags({
}),
url: flags.string({
char: 'u',
description:
'The homepage URL of your app, e.g., https://example.com.',
description: 'The homepage URL of your app, e.g., https://example.com.',
}),
audience: flags.string({
char: 'a',
description:
'Are you building a public or private integration?',
description: 'Are you building a public or private integration?',
}),
role: flags.string({
char: 'r',
Expand Down
83 changes: 51 additions & 32 deletions packages/cli/src/tests/register.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,58 @@ const oclif = require('@oclif/test');
const constants = require('../constants');
const registerFieldChoices = require('./fixtures/registerFieldChoices');

describe('zapier register should validate enum fields that are passed in as flags', function () {
function getTestObj() {
return oclif.test.nock(constants.BASE_ENDPOINT, (mockApi) =>
mockApi
.get('/api/platform/cli/apps/fields-choices')
.reply(200, registerFieldChoices)
);
}
describe('RegisterCommand', () => {
describe('zapier register should enforce character limits on flags', function () {
oclif.test
.command([
'register',
'--desc',
'Cupidatat non elit non enim enim cupidatat ea in consequat exercitation do nisi occaecat amet id deserunt nostrud quis aliqua id fugiat sit elit.',
])
.catch((ctx) => {
oclif
.expect(ctx.message)
.to.contain(
'Please provide a description that is 140 characters or less.'
);
})
.it('zapier register should enforce character limit on desc flag');
});

getTestObj()
.command(['register', '--role', 'invalidRole'])
.catch((ctx) => {
oclif
.expect(ctx.message)
.to.contain('invalidRole is not a valid value for role');
})
.it('zapier register should throw error for invalid role');
describe('zapier register should validate enum fields that are passed in as flags', function () {
function getTestObj() {
return oclif.test.nock(constants.BASE_ENDPOINT, (mockApi) =>
mockApi
.get('/api/platform/cli/apps/fields-choices')
.reply(200, registerFieldChoices)
);
}

getTestObj()
.command(['register', '--category', 'invalidCategory'])
.catch((ctx) => {
oclif
.expect(ctx.message)
.to.contain('invalidCategory is not a valid value for category');
})
.it('zapier register should throw error for invalid category');
getTestObj()
.command(['register', '--role', 'invalidRole'])
.catch((ctx) => {
oclif
.expect(ctx.message)
.to.contain('invalidRole is not a valid value for role');
})
.it('zapier register should throw error for invalid role');

getTestObj()
.command(['register', '--audience', 'invalidAudience'])
.catch((ctx) => {
oclif
.expect(ctx.message)
.to.contain('invalidAudience is not a valid value for audience');
})
.it('zapier register should throw error for invalid audience');
getTestObj()
.command(['register', '--category', 'invalidCategory'])
.catch((ctx) => {
oclif
.expect(ctx.message)
.to.contain('invalidCategory is not a valid value for category');
})
.it('zapier register should throw error for invalid category');

getTestObj()
.command(['register', '--audience', 'invalidAudience'])
.catch((ctx) => {
oclif
.expect(ctx.message)
.to.contain('invalidAudience is not a valid value for audience');
})
.it('zapier register should throw error for invalid audience');
});
});

0 comments on commit 4610f36

Please sign in to comment.