[READ-ONLY] Mirror of https://github.com/bombshell-dev/clack. Effortlessly build beautiful command-line apps bomb.sh/docs/clack/basics/getting-started/
cli command-line command-line-app node prompt prompts
5

Configure Feed

Select the types of activity you want to include in your feed.

test: add tests for `PasswordPrompt` (#258)

authored by

James Garbutt and committed by
GitHub
(Mar 30, 2025, 2:28 PM -0500) a87628cb 2a3755a1

+98
+98
packages/core/test/prompts/password.test.ts
··· 1 + import color from 'picocolors'; 2 + import { cursor } from 'sisteransi'; 3 + import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; 4 + import { default as PasswordPrompt } from '../../src/prompts/password.js'; 5 + import { MockReadable } from '../mock-readable.js'; 6 + import { MockWritable } from '../mock-writable.js'; 7 + 8 + describe('PasswordPrompt', () => { 9 + let input: MockReadable; 10 + let output: MockWritable; 11 + 12 + beforeEach(() => { 13 + input = new MockReadable(); 14 + output = new MockWritable(); 15 + }); 16 + 17 + afterEach(() => { 18 + vi.restoreAllMocks(); 19 + }); 20 + 21 + test('renders render() result', () => { 22 + const instance = new PasswordPrompt({ 23 + input, 24 + output, 25 + render: () => 'foo', 26 + }); 27 + // leave the promise hanging since we don't want to submit in this test 28 + instance.prompt(); 29 + expect(output.buffer).to.deep.equal([cursor.hide, 'foo']); 30 + }); 31 + 32 + describe('cursor', () => { 33 + test('can get cursor', () => { 34 + const instance = new PasswordPrompt({ 35 + input, 36 + output, 37 + render: () => 'foo', 38 + }); 39 + 40 + expect(instance.cursor).to.equal(0); 41 + }); 42 + }); 43 + 44 + describe('valueWithCursor', () => { 45 + test('returns masked value on submit', () => { 46 + const instance = new PasswordPrompt({ 47 + input, 48 + output, 49 + render: () => 'foo', 50 + }); 51 + instance.prompt(); 52 + const keys = 'foo'; 53 + for (let i = 0; i < keys.length; i++) { 54 + input.emit('keypress', keys[i], { name: keys[i] }); 55 + } 56 + input.emit('keypress', '', { name: 'return' }); 57 + expect(instance.valueWithCursor).to.equal('•••'); 58 + }); 59 + 60 + test('renders marker at end', () => { 61 + const instance = new PasswordPrompt({ 62 + input, 63 + output, 64 + render: () => 'foo', 65 + }); 66 + instance.prompt(); 67 + input.emit('keypress', 'x', { name: 'x' }); 68 + expect(instance.valueWithCursor).to.equal(`•${color.inverse(color.hidden('_'))}`); 69 + }); 70 + 71 + test('renders cursor inside value', () => { 72 + const instance = new PasswordPrompt({ 73 + input, 74 + output, 75 + render: () => 'foo', 76 + }); 77 + instance.prompt(); 78 + input.emit('keypress', 'x', { name: 'x' }); 79 + input.emit('keypress', 'y', { name: 'y' }); 80 + input.emit('keypress', 'z', { name: 'z' }); 81 + input.emit('keypress', 'left', { name: 'left' }); 82 + input.emit('keypress', 'left', { name: 'left' }); 83 + expect(instance.valueWithCursor).to.equal(`•${color.inverse('•')}•`); 84 + }); 85 + 86 + test('renders custom mask', () => { 87 + const instance = new PasswordPrompt({ 88 + input, 89 + output, 90 + render: () => 'foo', 91 + mask: 'X', 92 + }); 93 + instance.prompt(); 94 + input.emit('keypress', 'x', { name: 'x' }); 95 + expect(instance.valueWithCursor).to.equal(`X${color.inverse(color.hidden('_'))}`); 96 + }); 97 + }); 98 + });