diff --git a/src/commands/config/clear.js b/src/commands/config/clear.js index 93f308c..9d7f296 100755 --- a/src/commands/config/clear.js +++ b/src/commands/config/clear.js @@ -12,15 +12,15 @@ governing permissions and limitations under the License. const { Flags } = require('@oclif/core') const BaseCommand = require('../../base-command') -const { prompt } = require('../../prompt') +const { promptConfirm } = require('../../prompt') class ClearCommand extends BaseCommand { async run () { const { flags } = await this.parse(ClearCommand) if (!flags.force) { - const confirm = await prompt('are you sure? [yN]') - if (!confirm[0] || confirm[0].toLowerCase() !== 'y') { + const confirmed = await promptConfirm('are you sure?') + if (!confirmed) { return } } diff --git a/src/prompt.js b/src/prompt.js index 3ecbe7f..fc38897 100644 --- a/src/prompt.js +++ b/src/prompt.js @@ -10,10 +10,17 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const { input } = require('@inquirer/prompts') +const { input, confirm } = require('@inquirer/prompts') + +// @inquirer/core pipes a MuteStream to process.stdout on every prompt call, +// adding an 'error' listener each time. oclif's plugin loading fills most of +// the default 10-slot budget before we even get here, so bump the limit to +// avoid the MaxListenersExceededWarning. +process.stdout.setMaxListeners(Math.max(process.stdout.getMaxListeners(), 20)) +process.stderr.setMaxListeners(Math.max(process.stderr.getMaxListeners(), 20)) /** - * Prompts the user for input. + * Prompts the user for text input. * * @param {string} message - the prompt message to display * @returns {Promise} the user's input @@ -22,4 +29,15 @@ async function prompt (message) { return input({ message }) } -module.exports = { prompt } +/** + * Prompts the user for a yes/no confirmation. + * + * @param {string} message - the prompt message to display + * @param {boolean} defaultValue - the default value if the user just presses Enter (default: false) + * @returns {Promise} true if the user confirmed + */ +async function promptConfirm (message, defaultValue = false) { + return confirm({ message, default: defaultValue }) +} + +module.exports = { prompt, promptConfirm } diff --git a/test/commands/config/clear.js b/test/commands/config/clear.js index 9d2a655..249df46 100755 --- a/test/commands/config/clear.js +++ b/test/commands/config/clear.js @@ -14,9 +14,10 @@ const TheCommand = require('../../../src/commands/config/clear.js') const { mockSet } = require('@adobe/aio-lib-core-config/src/Config') jest.mock('../../../src/prompt', () => ({ - prompt: jest.fn() + prompt: jest.fn(), + promptConfirm: jest.fn() })) -const { prompt } = require('../../../src/prompt') +const { promptConfirm } = require('../../../src/prompt') describe('clear', () => { afterEach(() => { @@ -46,14 +47,14 @@ describe('clear', () => { }) test('prompt with yes', () => { - prompt.mockResolvedValue('y') + promptConfirm.mockResolvedValue(true) return TheCommand.run([]).then(() => { expect(mockSet).toHaveBeenCalledWith(null, null, false) }) }) test('prompt with no', () => { - prompt.mockResolvedValue('n') + promptConfirm.mockResolvedValue(false) return TheCommand.run([]).then(() => { expect(mockSet).not.toHaveBeenCalled() }) diff --git a/test/commands/prompt.js b/test/commands/prompt.js index 62056de..f7ef531 100644 --- a/test/commands/prompt.js +++ b/test/commands/prompt.js @@ -10,12 +10,13 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -const { prompt } = require('../../src/prompt') +const { prompt, promptConfirm } = require('../../src/prompt') jest.mock('@inquirer/prompts', () => ({ - input: jest.fn() + input: jest.fn(), + confirm: jest.fn() })) -const { input } = require('@inquirer/prompts') +const { input, confirm } = require('@inquirer/prompts') describe('prompt', () => { test('returns user input', async () => { @@ -27,3 +28,31 @@ describe('prompt', () => { expect(result).toEqual('user answer') }) }) + +describe('promptConfirm', () => { + test('returns true when confirmed', async () => { + confirm.mockResolvedValue(true) + + const result = await promptConfirm('are you sure?') + + expect(confirm).toHaveBeenCalledWith({ message: 'are you sure?', default: false }) + expect(result).toBe(true) + }) + + test('returns false when denied', async () => { + confirm.mockResolvedValue(false) + + const result = await promptConfirm('are you sure?') + + expect(confirm).toHaveBeenCalledWith({ message: 'are you sure?', default: false }) + expect(result).toBe(false) + }) + + test('passes custom default value', async () => { + confirm.mockResolvedValue(true) + + await promptConfirm('proceed?', true) + + expect(confirm).toHaveBeenCalledWith({ message: 'proceed?', default: true }) + }) +})