Skip to content

Commit

Permalink
Adds interactive mode as default. Closes pnp#5181
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam-it committed Sep 23, 2023
1 parent 14c7857 commit 8a35681
Show file tree
Hide file tree
Showing 188 changed files with 4,453 additions and 183 deletions.
2 changes: 1 addition & 1 deletion docs/docs/_clisettings.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ Setting name|Definition|Default value
`helpMode`|Defines what part of command's help to display. Allowed values are `options`, `examples`, `remarks`, `response`, `full`|`options`
`output`|Defines the default output when issuing a command. Allowed values are `json`, `text`, `csv`, `md`, `none`|`json`
`printErrorsAsPlainText`|When output mode is set to `json`, print error messages as plain-text rather than JSON|`true`
`prompt`|Prompts for missing values in required options and enables interactive selection when multiple values are available for a command that requires a specific value to be retrieved.|`false`
`prompt`|Prompts for missing values in required options and enables interactive selection when multiple values are available for a command that requires a specific value to be retrieved.|`true`
`showHelpOnFailure`|Automatically display help when executing a command failed|`true`
`showSpinner`|Display spinner when executing commands|`true`
4 changes: 2 additions & 2 deletions src/Command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export default abstract class Command {
}

private async validateRequiredOptions(args: CommandArgs, command: CommandInfo): Promise<string | boolean> {
const shouldPrompt = Cli.getInstance().getSettingWithDefaultValue<boolean>(settingsNames.prompt, false);
const shouldPrompt = Cli.getInstance().getSettingWithDefaultValue<boolean>(settingsNames.prompt, true);

let inquirer: typeof import('inquirer') | undefined;
let prompted: boolean = false;
Expand Down Expand Up @@ -192,7 +192,7 @@ export default abstract class Command {
}

let inquirer: typeof import('inquirer') | undefined;
const shouldPrompt = Cli.getInstance().getSettingWithDefaultValue<boolean>(settingsNames.prompt, false);
const shouldPrompt = Cli.getInstance().getSettingWithDefaultValue<boolean>(settingsNames.prompt, true);

const argsOptions: string[] = Object.keys(args.options);

Expand Down
32 changes: 28 additions & 4 deletions src/cli/Cli.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,13 @@ describe('Cli', () => {
});

it(`shows validation error when no option from a required set is specified`, (done) => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake(((settingName, defaultValue) => defaultValue));
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

cli
.execute(rootFolder, ['cli', 'mock', 'optionsets'])
Expand All @@ -738,7 +744,13 @@ describe('Cli', () => {
});

it(`shows validation error when multiple options from a required set are specified`, (done) => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake(((settingName, defaultValue) => defaultValue));
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

cli
.execute(rootFolder, ['cli', 'mock', 'optionsets', '--opt1', 'testvalue', '--opt2', 'testvalue'])
Expand Down Expand Up @@ -768,7 +780,13 @@ describe('Cli', () => {
});

it(`shows validation error when no option from a dependent set is set`, (done) => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake(((settingName, defaultValue) => defaultValue));
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

cli
.execute(rootFolder, ['cli', 'mock', 'optionsets', '--opt2', 'testvalue'])
Expand Down Expand Up @@ -798,7 +816,13 @@ describe('Cli', () => {
});

it(`shows validation error when multiple options from an optional set are specified`, (done) => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake(((settingName, defaultValue) => defaultValue));
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

cli
.execute(rootFolder, ['cli', 'mock', 'optionsets', '--opt1', 'testvalue', '--opt5', 'testvalue', '--opt6', 'testvalue'])
Expand Down
2 changes: 1 addition & 1 deletion src/cli/Cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,7 @@ export class Cli {
}

public static async handleMultipleResultsFound<T>(message: string, values: { [key: string]: T }): Promise<T> {
const prompt: boolean = Cli.getInstance().getSettingWithDefaultValue<boolean>(settingsNames.prompt, false);
const prompt: boolean = Cli.getInstance().getSettingWithDefaultValue<boolean>(settingsNames.prompt, true);
if (!prompt) {
throw new Error(`${message} Found: ${Object.keys(values).join(', ')}.`);
}
Expand Down
42 changes: 41 additions & 1 deletion src/m365/aad/commands/app/app-get.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { session } from '../../../../utils/session.js';
import { sinonUtil } from '../../../../utils/sinonUtil.js';
import commands from '../../commands.js';
import command from './app-get.js';
import { settingsNames } from '../../../../settingsNames.js';

describe(commands.APP_GET, () => {
let cli: Cli;
Expand Down Expand Up @@ -45,7 +46,6 @@ describe(commands.APP_GET, () => {
}
};
loggerLogSpy = sinon.spy(logger, 'log');
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake(((settingName, defaultValue) => defaultValue));
});

afterEach(() => {
Expand Down Expand Up @@ -105,6 +105,14 @@ describe(commands.APP_GET, () => {
});

it('handles error when multiple apps with the specified name found', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

sinon.stub(request, 'get').callsFake(async opts => {
if (opts.url === `https://graph.microsoft.com/v1.0/myorganization/applications?$filter=displayName eq 'My%20app'&$select=id`) {
return {
Expand Down Expand Up @@ -187,21 +195,53 @@ describe(commands.APP_GET, () => {
});

it('fails validation if appId and objectId specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: { appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', objectId: 'c75be2e1-0204-4f95-857d-51a37cf40be8' } }, commandInfo);
assert.notStrictEqual(actual, true);
});

it('fails validation if appId and name specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: { appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', name: 'My app' } }, commandInfo);
assert.notStrictEqual(actual, true);
});

it('fails validation if objectId and name specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: { objectId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', name: 'My app' } }, commandInfo);
assert.notStrictEqual(actual, true);
});

it('fails validation if neither appId, objectId, nor name specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: {} }, commandInfo);
assert.notStrictEqual(actual, true);
});
Expand Down
35 changes: 33 additions & 2 deletions src/m365/aad/commands/app/app-remove.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { session } from '../../../../utils/session.js';
import { sinonUtil } from '../../../../utils/sinonUtil.js';
import commands from '../../commands.js';
import command from './app-remove.js';
import { settingsNames } from '../../../../settingsNames.js';

describe(commands.APP_REMOVE, () => {
let cli: Cli;
Expand Down Expand Up @@ -52,8 +53,6 @@ describe(commands.APP_REMOVE, () => {

promptOptions = undefined;

sinon.stub(cli, 'getSettingWithDefaultValue').callsFake(((settingName, defaultValue) => defaultValue));

sinon.stub(request, 'get').callsFake(async (opts: any) => {
if ((opts.url as string).indexOf(`/v1.0/myorganization/applications?$filter=`) > -1) {
// fake call for getting app
Expand Down Expand Up @@ -103,16 +102,40 @@ describe(commands.APP_REMOVE, () => {
});

it('fails validation if appId and name specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: { appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', name: 'My app' } }, commandInfo);
assert.notStrictEqual(actual, true);
});

it('fails validation if objectId and name specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: { objectId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', name: 'My app' } }, commandInfo);
assert.notStrictEqual(actual, true);
});

it('fails validation if neither appId, objectId, nor name specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: {} }, commandInfo);
assert.notStrictEqual(actual, true);
});
Expand Down Expand Up @@ -238,6 +261,14 @@ describe(commands.APP_REMOVE, () => {
});

it('fails when multiple apps with same name exists', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

sinonUtil.restore(request.get);
sinon.stub(request, 'get').callsFake(async (opts) => {
if ((opts.url as string).indexOf(`/v1.0/myorganization/applications?$filter=`) > -1) {
Expand Down
42 changes: 41 additions & 1 deletion src/m365/aad/commands/app/app-role-add.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { session } from '../../../../utils/session.js';
import { sinonUtil } from '../../../../utils/sinonUtil.js';
import commands from '../../commands.js';
import command from './app-role-add.js';
import { settingsNames } from '../../../../settingsNames.js';

describe(commands.APP_ROLE_ADD, () => {
let cli: Cli;
Expand Down Expand Up @@ -42,7 +43,6 @@ describe(commands.APP_ROLE_ADD, () => {
log.push(msg);
}
};
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake(((settingName, defaultValue) => defaultValue));
});

afterEach(() => {
Expand Down Expand Up @@ -321,6 +321,14 @@ describe(commands.APP_ROLE_ADD, () => {
});

it('handles error when multiple apps with the specified appName found', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

sinon.stub(request, 'get').callsFake(async opts => {
if (opts.url === `https://graph.microsoft.com/v1.0/myorganization/applications?$filter=displayName eq 'My%20app'&$select=id`) {
return {
Expand Down Expand Up @@ -512,21 +520,53 @@ describe(commands.APP_ROLE_ADD, () => {
});

it('fails validation if appId and appObjectId specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: { appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', appObjectId: 'c75be2e1-0204-4f95-857d-51a37cf40be8', name: 'Managers', description: 'Managers', allowedMembers: 'userGroups', claim: 'managers' } }, commandInfo);
assert.notStrictEqual(actual, true);
});

it('fails validation if appId and appName specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: { appId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', appName: 'My app', name: 'Managers', description: 'Managers', allowedMembers: 'userGroups', claim: 'managers' } }, commandInfo);
assert.notStrictEqual(actual, true);
});

it('fails validation if appObjectId and appName specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: { appObjectId: '9b1b1e42-794b-4c71-93ac-5ed92488b67f', appName: 'My app', name: 'Managers', description: 'Managers', allowedMembers: 'userGroups', claim: 'managers' } }, commandInfo);
assert.notStrictEqual(actual, true);
});

it('fails validation if neither appId, appObjectId nor appName specified', async () => {
sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName, defaultValue) => {
if (settingName === settingsNames.prompt) {
return false;
}

return defaultValue;
});

const actual = await command.validate({ options: { name: 'Managers', description: 'Managers', allowedMembers: 'userGroups', claim: 'managers' } }, commandInfo);
assert.notStrictEqual(actual, true);
});
Expand Down
Loading

0 comments on commit 8a35681

Please sign in to comment.