diff --git a/packages/prompts/src/__snapshots__/index.test.ts.snap b/packages/prompts/src/__snapshots__/index.test.ts.snap index 34f90057..e692dba5 100644 --- a/packages/prompts/src/__snapshots__/index.test.ts.snap +++ b/packages/prompts/src/__snapshots__/index.test.ts.snap @@ -708,6 +708,146 @@ exports[`prompts (isCI = false) > multiselect > sliding window loops upwards 1`] ] `; +exports[`prompts (isCI = false) > password > renders and clears validation errors 1`] = ` +[ + "[?25l", + "│ +◆ foo +│ _ +└ +", + "", + "", + "", + "│ ▪_", + "", + "", + "", + "", + "▲ foo +│ ▪ +└ Password must be at least 2 characters +", + "", + "", + "", + "◆ foo +│ ▪▪_ +└ +", + "", + "", + "", + "◇ foo +│ ▪▪", + " +", + "[?25h", +] +`; + +exports[`prompts (isCI = false) > password > renders cancelled value 1`] = ` +[ + "[?25l", + "│ +◆ foo +│ _ +└ +", + "", + "", + "", + "│ ▪_", + "", + "", + "", + "", + "■ foo +│ ▪ +│", + " +", + "[?25h", +] +`; + +exports[`prompts (isCI = false) > password > renders custom mask 1`] = ` +[ + "[?25l", + "│ +◆ foo +│ _ +└ +", + "", + "", + "", + "│ *_", + "", + "", + "", + "", + "│ **_", + "", + "", + "", + "", + "◇ foo +│ **", + " +", + "[?25h", +] +`; + +exports[`prompts (isCI = false) > password > renders masked value 1`] = ` +[ + "[?25l", + "│ +◆ foo +│ _ +└ +", + "", + "", + "", + "│ ▪_", + "", + "", + "", + "", + "│ ▪▪_", + "", + "", + "", + "", + "◇ foo +│ ▪▪", + " +", + "[?25h", +] +`; + +exports[`prompts (isCI = false) > password > renders message 1`] = ` +[ + "[?25l", + "│ +◆ foo +│ _ +└ +", + "", + "", + "", + "◇ foo +│", + " +", + "[?25h", +] +`; + exports[`prompts (isCI = false) > select > can cancel 1`] = ` [ "[?25l", @@ -1873,6 +2013,146 @@ exports[`prompts (isCI = true) > multiselect > sliding window loops upwards 1`] ] `; +exports[`prompts (isCI = true) > password > renders and clears validation errors 1`] = ` +[ + "[?25l", + "│ +◆ foo +│ _ +└ +", + "", + "", + "", + "│ ▪_", + "", + "", + "", + "", + "▲ foo +│ ▪ +└ Password must be at least 2 characters +", + "", + "", + "", + "◆ foo +│ ▪▪_ +└ +", + "", + "", + "", + "◇ foo +│ ▪▪", + " +", + "[?25h", +] +`; + +exports[`prompts (isCI = true) > password > renders cancelled value 1`] = ` +[ + "[?25l", + "│ +◆ foo +│ _ +└ +", + "", + "", + "", + "│ ▪_", + "", + "", + "", + "", + "■ foo +│ ▪ +│", + " +", + "[?25h", +] +`; + +exports[`prompts (isCI = true) > password > renders custom mask 1`] = ` +[ + "[?25l", + "│ +◆ foo +│ _ +└ +", + "", + "", + "", + "│ *_", + "", + "", + "", + "", + "│ **_", + "", + "", + "", + "", + "◇ foo +│ **", + " +", + "[?25h", +] +`; + +exports[`prompts (isCI = true) > password > renders masked value 1`] = ` +[ + "[?25l", + "│ +◆ foo +│ _ +└ +", + "", + "", + "", + "│ ▪_", + "", + "", + "", + "", + "│ ▪▪_", + "", + "", + "", + "", + "◇ foo +│ ▪▪", + " +", + "[?25h", +] +`; + +exports[`prompts (isCI = true) > password > renders message 1`] = ` +[ + "[?25l", + "│ +◆ foo +│ _ +└ +", + "", + "", + "", + "◇ foo +│", + " +", + "[?25h", +] +`; + exports[`prompts (isCI = true) > select > can cancel 1`] = ` [ "[?25l", diff --git a/packages/prompts/src/index.test.ts b/packages/prompts/src/index.test.ts index 107f1b99..6af64e00 100644 --- a/packages/prompts/src/index.test.ts +++ b/packages/prompts/src/index.test.ts @@ -809,4 +809,94 @@ describe.each(['true', 'false'])('prompts (isCI = %s)', (isCI) => { expect(output.buffer).toMatchSnapshot(); }); }); + + describe('password', () => { + test('renders message', async () => { + const result = prompts.password({ + message: 'foo', + input, + output, + }); + + input.emit('keypress', '', { name: 'return' }); + + await result; + + expect(output.buffer).toMatchSnapshot(); + }); + + test('renders masked value', async () => { + const result = prompts.password({ + message: 'foo', + input, + output, + }); + + input.emit('keypress', 'x', { name: 'x' }); + input.emit('keypress', 'y', { name: 'y' }); + input.emit('keypress', '', { name: 'return' }); + + const value = await result; + + expect(value).toBe('xy'); + expect(output.buffer).toMatchSnapshot(); + }); + + test('renders custom mask', async () => { + const result = prompts.password({ + message: 'foo', + mask: '*', + input, + output, + }); + + input.emit('keypress', 'x', { name: 'x' }); + input.emit('keypress', 'y', { name: 'y' }); + input.emit('keypress', '', { name: 'return' }); + + await result; + + expect(output.buffer).toMatchSnapshot(); + }); + + test('renders and clears validation errors', async () => { + const result = prompts.password({ + message: 'foo', + validate: (value) => { + if (value.length < 2) { + return 'Password must be at least 2 characters'; + } + + return undefined; + }, + input, + output, + }); + + input.emit('keypress', 'x', { name: 'x' }); + input.emit('keypress', '', { name: 'return' }); + input.emit('keypress', 'y', { name: 'y' }); + input.emit('keypress', '', { name: 'return' }); + + await result; + + expect(output.buffer).toMatchSnapshot(); + }); + + test('renders cancelled value', async () => { + const result = prompts.password({ + message: 'foo', + input, + output, + }); + + input.emit('keypress', 'x', { name: 'x' }); + input.emit('keypress', '', { name: 'escape' }); + + const value = await result; + + expect(prompts.isCancel(value)).toBe(true); + expect(output.buffer).toMatchSnapshot(); + }); + }); });