[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 `TextPrompt` tests (#257)

authored by

James Garbutt and committed by
GitHub
(Mar 30, 2025, 2:27 PM -0500) 2a3755a1 6868c1c4

+114
+114
packages/core/test/prompts/text.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 TextPrompt } from '../../src/prompts/text.js'; 5 + import { MockReadable } from '../mock-readable.js'; 6 + import { MockWritable } from '../mock-writable.js'; 7 + 8 + describe('TextPrompt', () => { 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 TextPrompt({ 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 + test('sets default value on finalize if no value', async () => { 33 + const instance = new TextPrompt({ 34 + input, 35 + output, 36 + render: () => 'foo', 37 + defaultValue: 'bleep bloop', 38 + }); 39 + const resultPromise = instance.prompt(); 40 + input.emit('keypress', '', { name: 'return' }); 41 + const result = await resultPromise; 42 + expect(result).to.equal('bleep bloop'); 43 + }); 44 + 45 + test('keeps value on finalize', async () => { 46 + const instance = new TextPrompt({ 47 + input, 48 + output, 49 + render: () => 'foo', 50 + defaultValue: 'bleep bloop', 51 + }); 52 + const resultPromise = instance.prompt(); 53 + input.emit('keypress', 'x', { name: 'x' }); 54 + input.emit('keypress', '', { name: 'return' }); 55 + const result = await resultPromise; 56 + expect(result).to.equal('x'); 57 + }); 58 + 59 + describe('cursor', () => { 60 + test('can get cursor', () => { 61 + const instance = new TextPrompt({ 62 + input, 63 + output, 64 + render: () => 'foo', 65 + }); 66 + 67 + expect(instance.cursor).to.equal(0); 68 + }); 69 + }); 70 + 71 + describe('valueWithCursor', () => { 72 + test('returns value on submit', () => { 73 + const instance = new TextPrompt({ 74 + input, 75 + output, 76 + render: () => 'foo', 77 + }); 78 + instance.prompt(); 79 + input.emit('keypress', 'x', { name: 'x' }); 80 + input.emit('keypress', '', { name: 'return' }); 81 + expect(instance.valueWithCursor).to.equal('x'); 82 + }); 83 + 84 + test('highlights cursor position', () => { 85 + const instance = new TextPrompt({ 86 + input, 87 + output, 88 + render: () => 'foo', 89 + }); 90 + instance.prompt(); 91 + const keys = 'foo'; 92 + for (let i = 0; i < keys.length; i++) { 93 + input.emit('keypress', keys[i], { name: keys[i] }); 94 + } 95 + input.emit('keypress', 'left', { name: 'left' }); 96 + expect(instance.valueWithCursor).to.equal(`fo${color.inverse('o')}`); 97 + }); 98 + 99 + test('shows cursor at end if beyond value', () => { 100 + const instance = new TextPrompt({ 101 + input, 102 + output, 103 + render: () => 'foo', 104 + }); 105 + instance.prompt(); 106 + const keys = 'foo'; 107 + for (let i = 0; i < keys.length; i++) { 108 + input.emit('keypress', keys[i], { name: keys[i] }); 109 + } 110 + input.emit('keypress', 'right', { name: 'right' }); 111 + expect(instance.valueWithCursor).to.equal('foo█'); 112 + }); 113 + }); 114 + });