[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(prompts): colocate tests and migrate to test-utils

Nate Moore (Apr 2, 2026, 7:17 PM EDT) eef2e42b fe20db05

+3287 -16620
+1 -1
packages/prompts/package.json
··· 48 48 ], 49 49 "packageManager": "pnpm@9.14.2", 50 50 "scripts": { 51 - "build": "bsh build", 51 + "build": "bsh build \"src/**/*.ts\" \"!src/**/*.test.ts\"", 52 52 "prepack": "pnpm build", 53 53 "test": "bsh test", 54 54 "lint": "bsh lint"
+260
packages/prompts/src/box.test.ts
··· 1 + import { styleText } from 'node:util'; 2 + import { updateSettings } from '@clack/core'; 3 + import { afterEach, beforeEach, describe, expect, test } from 'vitest'; 4 + import * as prompts from './index.js'; 5 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 6 + 7 + describe.each(['true', 'false'])('box (isCI = %s)', (isCI) => { 8 + let mocks: Mocks<{ input: true; output: true }>; 9 + 10 + beforeEach(() => { 11 + mocks = createMocks({ input: true, output: true, env: { CI: isCI } }); 12 + }); 13 + 14 + afterEach(() => { 15 + updateSettings({ withGuide: true }); 16 + }); 17 + 18 + test('renders message', () => { 19 + prompts.box('message', undefined, { 20 + input: mocks.input, 21 + output: mocks.output, 22 + }); 23 + 24 + expect(mocks.output.buffer).toMatchSnapshot(); 25 + }); 26 + 27 + test('renders message with title', () => { 28 + prompts.box('message', 'some title', { 29 + input: mocks.input, 30 + output: mocks.output, 31 + }); 32 + 33 + expect(mocks.output.buffer).toMatchSnapshot(); 34 + }); 35 + 36 + test('renders as wide as longest line with width: auto', () => { 37 + prompts.box('short\nsomewhat questionably long line', 'title', { 38 + input: mocks.input, 39 + output: mocks.output, 40 + width: 'auto', 41 + }); 42 + 43 + expect(mocks.output.buffer).toMatchSnapshot(); 44 + }); 45 + 46 + test('renders as specified width', () => { 47 + prompts.box('short\nsomewhat questionably long line', 'title', { 48 + input: mocks.input, 49 + output: mocks.output, 50 + width: 0.5, 51 + }); 52 + 53 + expect(mocks.output.buffer).toMatchSnapshot(); 54 + }); 55 + 56 + test('wraps content to fit within specified width', () => { 57 + prompts.box('foo bar'.repeat(20), 'title', { 58 + input: mocks.input, 59 + output: mocks.output, 60 + width: 0.5, 61 + }); 62 + 63 + expect(mocks.output.buffer).toMatchSnapshot(); 64 + }); 65 + 66 + test('renders specified titlePadding', () => { 67 + prompts.box('message', 'title', { 68 + input: mocks.input, 69 + output: mocks.output, 70 + titlePadding: 6, 71 + width: 'auto', 72 + }); 73 + 74 + expect(mocks.output.buffer).toMatchSnapshot(); 75 + }); 76 + 77 + test('renders specified contentPadding', () => { 78 + prompts.box('message', 'title', { 79 + input: mocks.input, 80 + output: mocks.output, 81 + contentPadding: 6, 82 + width: 'auto', 83 + }); 84 + 85 + expect(mocks.output.buffer).toMatchSnapshot(); 86 + }); 87 + 88 + test('renders without guide when withGuide is false', () => { 89 + prompts.box('message', 'title', { 90 + input: mocks.input, 91 + output: mocks.output, 92 + withGuide: false, 93 + width: 'auto', 94 + }); 95 + 96 + expect(mocks.output.buffer).toMatchSnapshot(); 97 + }); 98 + 99 + test('renders without guide when global withGuide is false', () => { 100 + updateSettings({ withGuide: false }); 101 + 102 + prompts.box('message', 'title', { 103 + input: mocks.input, 104 + output: mocks.output, 105 + width: 'auto', 106 + }); 107 + 108 + expect(mocks.output.buffer).toMatchSnapshot(); 109 + }); 110 + 111 + test('renders truncated long titles', () => { 112 + prompts.box('message', 'foo'.repeat(20), { 113 + input: mocks.input, 114 + output: mocks.output, 115 + width: 0.2, 116 + }); 117 + 118 + expect(mocks.output.buffer).toMatchSnapshot(); 119 + }); 120 + 121 + test('cannot have width larger than 100%', () => { 122 + prompts.box('message', 'title', { 123 + input: mocks.input, 124 + output: mocks.output, 125 + width: 1.1, 126 + }); 127 + 128 + expect(mocks.output.buffer).toMatchSnapshot(); 129 + }); 130 + 131 + test('renders rounded corners when rounded is true', () => { 132 + prompts.box('message', 'title', { 133 + input: mocks.input, 134 + output: mocks.output, 135 + rounded: true, 136 + width: 'auto', 137 + }); 138 + 139 + expect(mocks.output.buffer).toMatchSnapshot(); 140 + }); 141 + 142 + test('renders auto width with content longer than title', () => { 143 + prompts.box('message'.repeat(4), 'title', { 144 + input: mocks.input, 145 + output: mocks.output, 146 + width: 'auto', 147 + }); 148 + 149 + expect(mocks.output.buffer).toMatchSnapshot(); 150 + }); 151 + 152 + test('renders auto width with title longer than content', () => { 153 + prompts.box('message', 'title'.repeat(4), { 154 + input: mocks.input, 155 + output: mocks.output, 156 + width: 'auto', 157 + }); 158 + 159 + expect(mocks.output.buffer).toMatchSnapshot(); 160 + }); 161 + 162 + test('renders left aligned title', () => { 163 + prompts.box('message', 'title', { 164 + input: mocks.input, 165 + output: mocks.output, 166 + titleAlign: 'left', 167 + width: 'auto', 168 + }); 169 + 170 + expect(mocks.output.buffer).toMatchSnapshot(); 171 + }); 172 + 173 + test('renders right aligned title', () => { 174 + prompts.box('message', 'title', { 175 + input: mocks.input, 176 + output: mocks.output, 177 + titleAlign: 'right', 178 + width: 'auto', 179 + }); 180 + 181 + expect(mocks.output.buffer).toMatchSnapshot(); 182 + }); 183 + 184 + test('renders center aligned title', () => { 185 + prompts.box('message', 'title', { 186 + input: mocks.input, 187 + output: mocks.output, 188 + titleAlign: 'center', 189 + width: 'auto', 190 + }); 191 + 192 + expect(mocks.output.buffer).toMatchSnapshot(); 193 + }); 194 + 195 + test('renders left aligned content', () => { 196 + prompts.box('message', 'title', { 197 + input: mocks.input, 198 + output: mocks.output, 199 + contentAlign: 'left', 200 + width: 'auto', 201 + }); 202 + 203 + expect(mocks.output.buffer).toMatchSnapshot(); 204 + }); 205 + 206 + test('renders right aligned content', () => { 207 + prompts.box('message', 'title', { 208 + input: mocks.input, 209 + output: mocks.output, 210 + contentAlign: 'right', 211 + width: 'auto', 212 + }); 213 + 214 + expect(mocks.output.buffer).toMatchSnapshot(); 215 + }); 216 + 217 + test('renders center aligned content', () => { 218 + prompts.box('message', 'title', { 219 + input: mocks.input, 220 + output: mocks.output, 221 + contentAlign: 'center', 222 + width: 'auto', 223 + }); 224 + 225 + expect(mocks.output.buffer).toMatchSnapshot(); 226 + }); 227 + 228 + test('renders with formatBorder formatting', () => { 229 + prompts.box('message', 'title', { 230 + input: mocks.input, 231 + output: mocks.output, 232 + width: 'auto', 233 + formatBorder: (text: string) => styleText('red', text), 234 + }); 235 + 236 + expect(mocks.output.buffer).toMatchSnapshot(); 237 + }); 238 + 239 + test('renders wide characters with auto width', () => { 240 + const messages = ['이게 첫 번째 줄이에요', 'これは次の行です']; 241 + prompts.box(messages.join('\n'), '这是标题', { 242 + input: mocks.input, 243 + output: mocks.output, 244 + width: 'auto', 245 + }); 246 + 247 + expect(mocks.output.buffer).toMatchSnapshot(); 248 + }); 249 + 250 + test('renders wide characters with specified width', () => { 251 + const messages = ['이게 첫 번째 줄이에요', 'これは次の行です']; 252 + prompts.box(messages.join('\n'), '这是标题', { 253 + input: mocks.input, 254 + output: mocks.output, 255 + width: 0.2, 256 + }); 257 + 258 + expect(mocks.output.buffer).toMatchSnapshot(); 259 + }); 260 + });
+203
packages/prompts/src/confirm.test.ts
··· 1 + import { updateSettings } from '@clack/core'; 2 + import { afterEach, beforeEach, describe, expect, test } from 'vitest'; 3 + import * as prompts from './index.js'; 4 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 5 + 6 + describe.each(['true', 'false'])('confirm (isCI = %s)', (isCI) => { 7 + let mocks: Mocks<{ input: true; output: true }>; 8 + 9 + beforeEach(() => { 10 + mocks = createMocks({ input: true, output: true, env: { CI: isCI } }); 11 + }); 12 + 13 + afterEach(() => { 14 + updateSettings({ withGuide: true }); 15 + }); 16 + 17 + test('renders message with choices', async () => { 18 + const result = prompts.confirm({ 19 + message: 'foo', 20 + input: mocks.input, 21 + output: mocks.output, 22 + }); 23 + 24 + mocks.input.emit('keypress', '', { name: 'return' }); 25 + 26 + const value = await result; 27 + 28 + expect(value).toBe(true); 29 + expect(mocks.output.buffer).toMatchSnapshot(); 30 + }); 31 + 32 + test('renders custom active choice', async () => { 33 + const result = prompts.confirm({ 34 + message: 'foo', 35 + active: 'bleep', 36 + input: mocks.input, 37 + output: mocks.output, 38 + }); 39 + 40 + mocks.input.emit('keypress', '', { name: 'return' }); 41 + 42 + const value = await result; 43 + 44 + expect(value).toBe(true); 45 + expect(mocks.output.buffer).toMatchSnapshot(); 46 + }); 47 + 48 + test('renders custom inactive choice', async () => { 49 + const result = prompts.confirm({ 50 + message: 'foo', 51 + inactive: 'bleep', 52 + input: mocks.input, 53 + output: mocks.output, 54 + }); 55 + 56 + mocks.input.emit('keypress', '', { name: 'return' }); 57 + 58 + const value = await result; 59 + 60 + expect(value).toBe(true); 61 + expect(mocks.output.buffer).toMatchSnapshot(); 62 + }); 63 + 64 + test('renders options in vertical alignment', async () => { 65 + const result = prompts.confirm({ 66 + message: 'foo', 67 + vertical: true, 68 + input: mocks.input, 69 + output: mocks.output, 70 + }); 71 + 72 + mocks.input.emit('keypress', '', { name: 'return' }); 73 + 74 + const value = await result; 75 + 76 + expect(value).toBe(true); 77 + expect(mocks.output.buffer).toMatchSnapshot(); 78 + }); 79 + 80 + test('right arrow moves to next choice', async () => { 81 + const result = prompts.confirm({ 82 + message: 'foo', 83 + input: mocks.input, 84 + output: mocks.output, 85 + }); 86 + 87 + mocks.input.emit('keypress', 'right', { name: 'right' }); 88 + mocks.input.emit('keypress', '', { name: 'return' }); 89 + 90 + const value = await result; 91 + 92 + expect(value).toBe(false); 93 + expect(mocks.output.buffer).toMatchSnapshot(); 94 + }); 95 + 96 + test('left arrow moves to previous choice', async () => { 97 + const result = prompts.confirm({ 98 + message: 'foo', 99 + input: mocks.input, 100 + output: mocks.output, 101 + }); 102 + 103 + mocks.input.emit('keypress', 'right', { name: 'right' }); 104 + mocks.input.emit('keypress', 'left', { name: 'left' }); 105 + mocks.input.emit('keypress', '', { name: 'return' }); 106 + 107 + const value = await result; 108 + 109 + expect(value).toBe(true); 110 + expect(mocks.output.buffer).toMatchSnapshot(); 111 + }); 112 + 113 + test('can cancel', async () => { 114 + const result = prompts.confirm({ 115 + message: 'foo', 116 + input: mocks.input, 117 + output: mocks.output, 118 + }); 119 + 120 + mocks.input.emit('keypress', 'escape', { name: 'escape' }); 121 + 122 + const value = await result; 123 + 124 + expect(prompts.isCancel(value)).toBe(true); 125 + expect(mocks.output.buffer).toMatchSnapshot(); 126 + }); 127 + 128 + test('can set initialValue', async () => { 129 + const result = prompts.confirm({ 130 + message: 'foo', 131 + initialValue: false, 132 + input: mocks.input, 133 + output: mocks.output, 134 + }); 135 + 136 + mocks.input.emit('keypress', '', { name: 'return' }); 137 + 138 + const value = await result; 139 + 140 + expect(value).toBe(false); 141 + expect(mocks.output.buffer).toMatchSnapshot(); 142 + }); 143 + 144 + test('can be aborted by a signal', async () => { 145 + const controller = new AbortController(); 146 + const result = prompts.confirm({ 147 + message: 'yes?', 148 + input: mocks.input, 149 + output: mocks.output, 150 + signal: controller.signal, 151 + }); 152 + 153 + controller.abort(); 154 + const value = await result; 155 + expect(prompts.isCancel(value)).toBe(true); 156 + expect(mocks.output.buffer).toMatchSnapshot(); 157 + }); 158 + 159 + test('withGuide: false removes guide', async () => { 160 + const result = prompts.confirm({ 161 + message: 'foo', 162 + withGuide: false, 163 + input: mocks.input, 164 + output: mocks.output, 165 + }); 166 + 167 + mocks.input.emit('keypress', '', { name: 'return' }); 168 + 169 + await result; 170 + 171 + expect(mocks.output.buffer).toMatchSnapshot(); 172 + }); 173 + 174 + test('global withGuide: false removes guide', async () => { 175 + updateSettings({ withGuide: false }); 176 + 177 + const result = prompts.confirm({ 178 + message: 'foo', 179 + input: mocks.input, 180 + output: mocks.output, 181 + }); 182 + 183 + mocks.input.emit('keypress', '', { name: 'return' }); 184 + 185 + await result; 186 + 187 + expect(mocks.output.buffer).toMatchSnapshot(); 188 + }); 189 + 190 + test('renders multi-line messages correctly', async () => { 191 + const result = prompts.confirm({ 192 + message: 'foo\nbar\nbaz', 193 + input: mocks.input, 194 + output: mocks.output, 195 + }); 196 + 197 + mocks.input.emit('keypress', '', { name: 'return' }); 198 + 199 + await result; 200 + 201 + expect(mocks.output.buffer).toMatchSnapshot(); 202 + }); 203 + });
+401
packages/prompts/src/group-multi-select.test.ts
··· 1 + import { afterEach, beforeEach, describe, expect, test } from 'vitest'; 2 + import * as prompts from './index.js'; 3 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 4 + 5 + describe.each(['true', 'false'])('groupMultiselect (isCI = %s)', (isCI) => { 6 + let mocks: Mocks<{ input: true; output: true }>; 7 + 8 + beforeEach(() => { 9 + mocks = createMocks({ input: true, output: true, env: { CI: isCI } }); 10 + }); 11 + 12 + afterEach(() => { 13 + prompts.updateSettings({ withGuide: true }); 14 + }); 15 + 16 + test('renders message with options', async () => { 17 + const result = prompts.groupMultiselect({ 18 + message: 'foo', 19 + input: mocks.input, 20 + output: mocks.output, 21 + options: { 22 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 23 + group2: [{ value: 'group2value0' }], 24 + }, 25 + }); 26 + 27 + // Select the first non-group option 28 + mocks.input.emit('keypress', '', { name: 'down' }); 29 + mocks.input.emit('keypress', '', { name: 'space' }); 30 + 31 + // submit 32 + mocks.input.emit('keypress', '', { name: 'return' }); 33 + 34 + const value = await result; 35 + 36 + expect(value).toEqual(['group1value0']); 37 + expect(mocks.output.buffer).toMatchSnapshot(); 38 + }); 39 + 40 + test('can select multiple options', async () => { 41 + const result = prompts.groupMultiselect({ 42 + message: 'foo', 43 + input: mocks.input, 44 + output: mocks.output, 45 + options: { 46 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }, { value: 'group1value2' }], 47 + }, 48 + }); 49 + 50 + // Select the first non-group option 51 + mocks.input.emit('keypress', '', { name: 'down' }); 52 + mocks.input.emit('keypress', '', { name: 'space' }); 53 + // Select the second non-group option 54 + mocks.input.emit('keypress', '', { name: 'down' }); 55 + mocks.input.emit('keypress', '', { name: 'space' }); 56 + 57 + // submit 58 + mocks.input.emit('keypress', '', { name: 'return' }); 59 + 60 + const value = await result; 61 + 62 + expect(value).toEqual(['group1value0', 'group1value1']); 63 + expect(mocks.output.buffer).toMatchSnapshot(); 64 + }); 65 + 66 + test('can select a group', async () => { 67 + const result = prompts.groupMultiselect({ 68 + message: 'foo', 69 + input: mocks.input, 70 + output: mocks.output, 71 + options: { 72 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 73 + }, 74 + }); 75 + 76 + // Select the group as a whole 77 + mocks.input.emit('keypress', '', { name: 'space' }); 78 + 79 + // submit 80 + mocks.input.emit('keypress', '', { name: 'return' }); 81 + 82 + const value = await result; 83 + 84 + expect(value).toEqual(['group1value0', 'group1value1']); 85 + expect(mocks.output.buffer).toMatchSnapshot(); 86 + }); 87 + 88 + test('can select a group by selecting all members', async () => { 89 + const result = prompts.groupMultiselect({ 90 + message: 'foo', 91 + input: mocks.input, 92 + output: mocks.output, 93 + options: { 94 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 95 + }, 96 + }); 97 + 98 + // Select the first group option 99 + mocks.input.emit('keypress', '', { name: 'down' }); 100 + mocks.input.emit('keypress', '', { name: 'space' }); 101 + // Select the second group option 102 + mocks.input.emit('keypress', '', { name: 'down' }); 103 + mocks.input.emit('keypress', '', { name: 'space' }); 104 + 105 + // submit 106 + mocks.input.emit('keypress', '', { name: 'return' }); 107 + 108 + const value = await result; 109 + 110 + expect(value).toEqual(['group1value0', 'group1value1']); 111 + expect(mocks.output.buffer).toMatchSnapshot(); 112 + }); 113 + 114 + test('can deselect an option', async () => { 115 + const result = prompts.groupMultiselect({ 116 + message: 'foo', 117 + input: mocks.input, 118 + output: mocks.output, 119 + options: { 120 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 121 + }, 122 + }); 123 + 124 + // Select the first group option 125 + mocks.input.emit('keypress', '', { name: 'down' }); 126 + mocks.input.emit('keypress', '', { name: 'space' }); 127 + // Select the second group option 128 + mocks.input.emit('keypress', '', { name: 'down' }); 129 + mocks.input.emit('keypress', '', { name: 'space' }); 130 + // Deselect it 131 + mocks.input.emit('keypress', '', { name: 'space' }); 132 + 133 + // submit 134 + mocks.input.emit('keypress', '', { name: 'return' }); 135 + 136 + const value = await result; 137 + 138 + expect(value).toEqual(['group1value0']); 139 + expect(mocks.output.buffer).toMatchSnapshot(); 140 + }); 141 + 142 + test('renders error when nothing selected', async () => { 143 + const result = prompts.groupMultiselect({ 144 + message: 'foo', 145 + input: mocks.input, 146 + output: mocks.output, 147 + options: { 148 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 149 + }, 150 + }); 151 + 152 + // try submit 153 + mocks.input.emit('keypress', '', { name: 'return' }); 154 + // now select something and submit 155 + mocks.input.emit('keypress', '', { name: 'down' }); 156 + mocks.input.emit('keypress', '', { name: 'space' }); 157 + mocks.input.emit('keypress', '', { name: 'return' }); 158 + 159 + const value = await result; 160 + 161 + expect(value).toEqual(['group1value0']); 162 + expect(mocks.output.buffer).toMatchSnapshot(); 163 + }); 164 + 165 + describe('selectableGroups = false', () => { 166 + test('cannot select groups', async () => { 167 + const result = prompts.groupMultiselect({ 168 + message: 'foo', 169 + input: mocks.input, 170 + output: mocks.output, 171 + options: { 172 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 173 + }, 174 + selectableGroups: false, 175 + }); 176 + 177 + // first selectable item should be group's child 178 + mocks.input.emit('keypress', '', { name: 'space' }); 179 + mocks.input.emit('keypress', '', { name: 'return' }); 180 + 181 + const value = await result; 182 + 183 + expect(value).toEqual(['group1value0']); 184 + expect(mocks.output.buffer).toMatchSnapshot(); 185 + }); 186 + 187 + test('selecting all members of group does not select group', async () => { 188 + const result = prompts.groupMultiselect({ 189 + message: 'foo', 190 + input: mocks.input, 191 + output: mocks.output, 192 + options: { 193 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 194 + }, 195 + selectableGroups: false, 196 + }); 197 + 198 + // first selectable item should be group's child 199 + mocks.input.emit('keypress', '', { name: 'space' }); 200 + // select second item 201 + mocks.input.emit('keypress', '', { name: 'down' }); 202 + mocks.input.emit('keypress', '', { name: 'space' }); 203 + // submit 204 + mocks.input.emit('keypress', '', { name: 'return' }); 205 + 206 + const value = await result; 207 + 208 + expect(value).toEqual(['group1value0', 'group1value1']); 209 + expect(mocks.output.buffer).toMatchSnapshot(); 210 + }); 211 + }); 212 + 213 + test('can submit empty selection when require = false', async () => { 214 + const result = prompts.groupMultiselect({ 215 + message: 'foo', 216 + input: mocks.input, 217 + output: mocks.output, 218 + options: { 219 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 220 + }, 221 + required: false, 222 + }); 223 + 224 + mocks.input.emit('keypress', '', { name: 'return' }); 225 + 226 + const value = await result; 227 + 228 + expect(value).toEqual([]); 229 + expect(mocks.output.buffer).toMatchSnapshot(); 230 + }); 231 + 232 + test('cursorAt sets initial selection', async () => { 233 + const result = prompts.groupMultiselect({ 234 + message: 'foo', 235 + input: mocks.input, 236 + output: mocks.output, 237 + options: { 238 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 239 + }, 240 + cursorAt: 'group1value1', 241 + }); 242 + 243 + mocks.input.emit('keypress', '', { name: 'space' }); 244 + mocks.input.emit('keypress', '', { name: 'return' }); 245 + 246 + const value = await result; 247 + 248 + expect(value).toEqual(['group1value1']); 249 + expect(mocks.output.buffer).toMatchSnapshot(); 250 + }); 251 + 252 + test('initial values can be set', async () => { 253 + const result = prompts.groupMultiselect({ 254 + message: 'foo', 255 + input: mocks.input, 256 + output: mocks.output, 257 + options: { 258 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 259 + }, 260 + initialValues: ['group1value1'], 261 + }); 262 + 263 + mocks.input.emit('keypress', '', { name: 'return' }); 264 + 265 + const value = await result; 266 + 267 + expect(value).toEqual(['group1value1']); 268 + expect(mocks.output.buffer).toMatchSnapshot(); 269 + }); 270 + 271 + test('values can be non-primitive', async () => { 272 + const value0 = Symbol(); 273 + const value1 = Symbol(); 274 + const result = prompts.groupMultiselect({ 275 + message: 'foo', 276 + input: mocks.input, 277 + output: mocks.output, 278 + options: { 279 + group1: [ 280 + { value: value0, label: 'value0' }, 281 + { value: value1, label: 'value1' }, 282 + ], 283 + }, 284 + }); 285 + 286 + mocks.input.emit('keypress', '', { name: 'down' }); 287 + mocks.input.emit('keypress', '', { name: 'space' }); 288 + mocks.input.emit('keypress', '', { name: 'return' }); 289 + 290 + const value = await result; 291 + 292 + expect(value).toEqual([value0]); 293 + expect(mocks.output.buffer).toMatchSnapshot(); 294 + }); 295 + 296 + describe('groupSpacing', () => { 297 + test('renders spaced groups', async () => { 298 + const result = prompts.groupMultiselect({ 299 + message: 'foo', 300 + input: mocks.input, 301 + output: mocks.output, 302 + options: { 303 + group1: [{ value: 'group1value0' }], 304 + group2: [{ value: 'group2value0' }], 305 + }, 306 + groupSpacing: 2, 307 + }); 308 + 309 + mocks.input.emit('keypress', '', { name: 'down' }); 310 + mocks.input.emit('keypress', '', { name: 'space' }); 311 + mocks.input.emit('keypress', '', { name: 'return' }); 312 + 313 + await result; 314 + 315 + expect(mocks.output.buffer).toMatchSnapshot(); 316 + }); 317 + 318 + test('negative spacing is ignored', async () => { 319 + const result = prompts.groupMultiselect({ 320 + message: 'foo', 321 + input: mocks.input, 322 + output: mocks.output, 323 + options: { 324 + group1: [{ value: 'group1value0' }], 325 + group2: [{ value: 'group2value0' }], 326 + }, 327 + groupSpacing: -2, 328 + }); 329 + 330 + mocks.input.emit('keypress', '', { name: 'down' }); 331 + mocks.input.emit('keypress', '', { name: 'space' }); 332 + mocks.input.emit('keypress', '', { name: 'return' }); 333 + 334 + await result; 335 + 336 + expect(mocks.output.buffer).toMatchSnapshot(); 337 + }); 338 + }); 339 + 340 + test('can be aborted by a signal', async () => { 341 + const controller = new AbortController(); 342 + const result = prompts.groupMultiselect({ 343 + message: 'Select a fruit', 344 + options: { 345 + group1: [{ value: 'group1value0' }], 346 + group2: [{ value: 'group2value0' }], 347 + }, 348 + input: mocks.input, 349 + output: mocks.output, 350 + signal: controller.signal, 351 + }); 352 + 353 + controller.abort(); 354 + const value = await result; 355 + expect(prompts.isCancel(value)).toBe(true); 356 + expect(mocks.output.buffer).toMatchSnapshot(); 357 + }); 358 + 359 + test('withGuide: false removes guide', async () => { 360 + const result = prompts.groupMultiselect({ 361 + message: 'foo', 362 + input: mocks.input, 363 + output: mocks.output, 364 + withGuide: false, 365 + options: { 366 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 367 + }, 368 + }); 369 + 370 + mocks.input.emit('keypress', '', { name: 'down' }); 371 + mocks.input.emit('keypress', '', { name: 'space' }); 372 + mocks.input.emit('keypress', '', { name: 'return' }); 373 + 374 + const value = await result; 375 + 376 + expect(value).toEqual(['group1value0']); 377 + expect(mocks.output.buffer).toMatchSnapshot(); 378 + }); 379 + 380 + test('global withGuide: false removes guide', async () => { 381 + prompts.updateSettings({ withGuide: false }); 382 + 383 + const result = prompts.groupMultiselect({ 384 + message: 'foo', 385 + input: mocks.input, 386 + output: mocks.output, 387 + options: { 388 + group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 389 + }, 390 + }); 391 + 392 + mocks.input.emit('keypress', '', { name: 'down' }); 393 + mocks.input.emit('keypress', '', { name: 'space' }); 394 + mocks.input.emit('keypress', '', { name: 'return' }); 395 + 396 + const value = await result; 397 + 398 + expect(value).toEqual(['group1value0']); 399 + expect(mocks.output.buffer).toMatchSnapshot(); 400 + }); 401 + });
+159
packages/prompts/src/log.test.ts
··· 1 + import { styleText } from 'node:util'; 2 + import { beforeEach, describe, expect, test } from 'vitest'; 3 + import * as prompts from './index.js'; 4 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 5 + 6 + describe.each(['true', 'false'])('log (isCI = %s)', (isCI) => { 7 + let mocks: Mocks<{ output: true }>; 8 + 9 + beforeEach(() => { 10 + mocks = createMocks({ output: true, env: { CI: isCI } }); 11 + }); 12 + 13 + describe('message', () => { 14 + test('renders message', () => { 15 + prompts.log.message('message', { 16 + output: mocks.output, 17 + }); 18 + 19 + expect(mocks.output.buffer).toMatchSnapshot(); 20 + }); 21 + 22 + test('renders multiline message', () => { 23 + prompts.log.message('line 1\nline 2\nline 3', { 24 + output: mocks.output, 25 + }); 26 + 27 + expect(mocks.output.buffer).toMatchSnapshot(); 28 + }); 29 + 30 + test('renders message from array', () => { 31 + prompts.log.message(['line 1', 'line 2', 'line 3'], { 32 + output: mocks.output, 33 + }); 34 + 35 + expect(mocks.output.buffer).toMatchSnapshot(); 36 + }); 37 + 38 + test('renders message with custom symbols and spacing', () => { 39 + prompts.log.message('custom\nsymbols', { 40 + symbol: styleText('red', '>>'), 41 + secondarySymbol: styleText('yellow', '--'), 42 + output: mocks.output, 43 + }); 44 + 45 + expect(mocks.output.buffer).toMatchSnapshot(); 46 + }); 47 + 48 + test('renders message with guide disabled', () => { 49 + prompts.log.message('standalone message', { 50 + withGuide: false, 51 + output: mocks.output, 52 + }); 53 + 54 + expect(mocks.output.buffer).toMatchSnapshot(); 55 + }); 56 + 57 + test('renders multiline message with guide disabled', () => { 58 + prompts.log.message('line 1\nline 2\nline 3', { 59 + withGuide: false, 60 + output: mocks.output, 61 + }); 62 + 63 + expect(mocks.output.buffer).toMatchSnapshot(); 64 + }); 65 + 66 + test('renders message with custom spacing', () => { 67 + prompts.log.message('spaced message', { 68 + spacing: 3, 69 + output: mocks.output, 70 + }); 71 + 72 + expect(mocks.output.buffer).toMatchSnapshot(); 73 + }); 74 + 75 + test('renders empty message correctly', () => { 76 + prompts.log.message('', { 77 + output: mocks.output, 78 + }); 79 + 80 + expect(mocks.output.buffer).toMatchSnapshot(); 81 + }); 82 + 83 + test('renders empty message with guide disabled', () => { 84 + prompts.log.message('', { 85 + withGuide: false, 86 + output: mocks.output, 87 + }); 88 + 89 + expect(mocks.output.buffer).toMatchSnapshot(); 90 + }); 91 + 92 + test('renders empty lines correctly', () => { 93 + prompts.log.message('foo\n\nbar', { 94 + output: mocks.output, 95 + }); 96 + 97 + expect(mocks.output.buffer).toMatchSnapshot(); 98 + }); 99 + 100 + test('renders empty lines with guide disabled', () => { 101 + prompts.log.message('foo\n\nbar', { 102 + withGuide: false, 103 + output: mocks.output, 104 + }); 105 + 106 + expect(mocks.output.buffer).toMatchSnapshot(); 107 + }); 108 + }); 109 + 110 + describe('info', () => { 111 + test('renders info message', () => { 112 + prompts.log.info('info message', { 113 + output: mocks.output, 114 + }); 115 + 116 + expect(mocks.output.buffer).toMatchSnapshot(); 117 + }); 118 + }); 119 + 120 + describe('success', () => { 121 + test('renders success message', () => { 122 + prompts.log.success('success message', { 123 + output: mocks.output, 124 + }); 125 + 126 + expect(mocks.output.buffer).toMatchSnapshot(); 127 + }); 128 + }); 129 + 130 + describe('step', () => { 131 + test('renders step message', () => { 132 + prompts.log.step('step message', { 133 + output: mocks.output, 134 + }); 135 + 136 + expect(mocks.output.buffer).toMatchSnapshot(); 137 + }); 138 + }); 139 + 140 + describe('warn', () => { 141 + test('renders warn message', () => { 142 + prompts.log.warn('warn message', { 143 + output: mocks.output, 144 + }); 145 + 146 + expect(mocks.output.buffer).toMatchSnapshot(); 147 + }); 148 + }); 149 + 150 + describe('error', () => { 151 + test('renders error message', () => { 152 + prompts.log.error('error message', { 153 + output: mocks.output, 154 + }); 155 + 156 + expect(mocks.output.buffer).toMatchSnapshot(); 157 + }); 158 + }); 159 + });
+259
packages/prompts/src/multi-line.test.ts
··· 1 + import { updateSettings } from '@clack/core'; 2 + import { afterEach, beforeEach, describe, expect, test } from 'vitest'; 3 + import * as prompts from './index.js'; 4 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 5 + 6 + describe.each(['true', 'false'])('multiline (isCI = %s)', (isCI) => { 7 + let mocks: Mocks<{ input: true; output: true }>; 8 + 9 + beforeEach(() => { 10 + mocks = createMocks({ input: true, output: true, env: { CI: isCI } }); 11 + }); 12 + 13 + afterEach(() => { 14 + updateSettings({ withGuide: true }); 15 + }); 16 + 17 + test('renders message', async () => { 18 + const result = prompts.multiline({ 19 + message: 'foo', 20 + input: mocks.input, 21 + output: mocks.output, 22 + }); 23 + 24 + mocks.input.emit('keypress', '', { name: 'return' }); 25 + mocks.input.emit('keypress', '', { name: 'return' }); 26 + 27 + await result; 28 + 29 + expect(mocks.output.buffer).toMatchSnapshot(); 30 + }); 31 + 32 + test('renders placeholder if set', async () => { 33 + const result = prompts.multiline({ 34 + message: 'foo', 35 + placeholder: 'bar', 36 + input: mocks.input, 37 + output: mocks.output, 38 + }); 39 + 40 + mocks.input.emit('keypress', '', { name: 'return' }); 41 + mocks.input.emit('keypress', '', { name: 'return' }); 42 + 43 + const value = await result; 44 + 45 + expect(mocks.output.buffer).toMatchSnapshot(); 46 + expect(value).toBe(''); 47 + }); 48 + 49 + test('can cancel', async () => { 50 + const result = prompts.multiline({ 51 + message: 'foo', 52 + input: mocks.input, 53 + output: mocks.output, 54 + }); 55 + 56 + mocks.input.emit('keypress', 'escape', { name: 'escape' }); 57 + 58 + const value = await result; 59 + 60 + expect(prompts.isCancel(value)).toBe(true); 61 + expect(mocks.output.buffer).toMatchSnapshot(); 62 + }); 63 + 64 + test('renders cancelled value if one set', async () => { 65 + const result = prompts.multiline({ 66 + message: 'foo', 67 + input: mocks.input, 68 + output: mocks.output, 69 + }); 70 + 71 + mocks.input.emit('keypress', 'x', { name: 'x' }); 72 + mocks.input.emit('keypress', 'y', { name: 'y' }); 73 + mocks.input.emit('keypress', '', { name: 'escape' }); 74 + 75 + const value = await result; 76 + 77 + expect(prompts.isCancel(value)).toBe(true); 78 + expect(mocks.output.buffer).toMatchSnapshot(); 79 + }); 80 + 81 + test('renders submitted value', async () => { 82 + const result = prompts.multiline({ 83 + message: 'foo', 84 + input: mocks.input, 85 + output: mocks.output, 86 + }); 87 + 88 + mocks.input.emit('keypress', 'x', { name: 'x' }); 89 + mocks.input.emit('keypress', 'y', { name: 'y' }); 90 + mocks.input.emit('keypress', '', { name: 'return' }); 91 + mocks.input.emit('keypress', '', { name: 'return' }); 92 + 93 + const value = await result; 94 + 95 + expect(value).toBe('xy'); 96 + expect(mocks.output.buffer).toMatchSnapshot(); 97 + }); 98 + 99 + test('defaultValue sets the value but does not render', async () => { 100 + const result = prompts.multiline({ 101 + message: 'foo', 102 + defaultValue: 'bar', 103 + input: mocks.input, 104 + output: mocks.output, 105 + }); 106 + 107 + mocks.input.emit('keypress', '', { name: 'return' }); 108 + mocks.input.emit('keypress', '', { name: 'return' }); 109 + 110 + const value = await result; 111 + 112 + expect(value).toBe('bar'); 113 + expect(mocks.output.buffer).toMatchSnapshot(); 114 + }); 115 + 116 + test('validation errors render and clear', async () => { 117 + const result = prompts.multiline({ 118 + message: 'foo', 119 + validate: (val) => (val !== 'xy' ? 'should be xy' : undefined), 120 + input: mocks.input, 121 + output: mocks.output, 122 + }); 123 + 124 + mocks.input.emit('keypress', 'x', { name: 'x' }); 125 + mocks.input.emit('keypress', '', { name: 'return' }); 126 + mocks.input.emit('keypress', '', { name: 'return' }); 127 + mocks.input.emit('keypress', 'y', { name: 'y' }); 128 + mocks.input.emit('keypress', '', { name: 'return' }); 129 + mocks.input.emit('keypress', '', { name: 'return' }); 130 + 131 + const value = await result; 132 + 133 + expect(value).toBe('xy'); 134 + expect(mocks.output.buffer).toMatchSnapshot(); 135 + }); 136 + 137 + test('validation errors render and clear (using Error)', async () => { 138 + const result = prompts.multiline({ 139 + message: 'foo', 140 + validate: (val) => (val !== 'xy' ? new Error('should be xy') : undefined), 141 + input: mocks.input, 142 + output: mocks.output, 143 + }); 144 + 145 + mocks.input.emit('keypress', 'x', { name: 'x' }); 146 + mocks.input.emit('keypress', '', { name: 'return' }); 147 + mocks.input.emit('keypress', '', { name: 'return' }); 148 + mocks.input.emit('keypress', 'y', { name: 'y' }); 149 + mocks.input.emit('keypress', '', { name: 'return' }); 150 + mocks.input.emit('keypress', '', { name: 'return' }); 151 + 152 + const value = await result; 153 + 154 + expect(value).toBe('xy'); 155 + expect(mocks.output.buffer).toMatchSnapshot(); 156 + }); 157 + 158 + test('placeholder is not used as value when pressing enter', async () => { 159 + const result = prompts.multiline({ 160 + message: 'foo', 161 + placeholder: ' (submit to use default)', 162 + defaultValue: 'default-value', 163 + input: mocks.input, 164 + output: mocks.output, 165 + }); 166 + 167 + mocks.input.emit('keypress', '', { name: 'return' }); 168 + mocks.input.emit('keypress', '', { name: 'return' }); 169 + 170 + const value = await result; 171 + 172 + expect(value).toBe('default-value'); 173 + expect(mocks.output.buffer).toMatchSnapshot(); 174 + }); 175 + 176 + test('empty string when no value and no default', async () => { 177 + const result = prompts.multiline({ 178 + message: 'foo', 179 + placeholder: ' (submit to use default)', 180 + input: mocks.input, 181 + output: mocks.output, 182 + }); 183 + 184 + mocks.input.emit('keypress', '', { name: 'return' }); 185 + mocks.input.emit('keypress', '', { name: 'return' }); 186 + 187 + const value = await result; 188 + 189 + expect(value).toBe(''); 190 + expect(mocks.output.buffer).toMatchSnapshot(); 191 + }); 192 + 193 + test('can be aborted by a signal', async () => { 194 + const controller = new AbortController(); 195 + const result = prompts.multiline({ 196 + message: 'foo', 197 + input: mocks.input, 198 + output: mocks.output, 199 + signal: controller.signal, 200 + }); 201 + 202 + controller.abort(); 203 + const value = await result; 204 + expect(prompts.isCancel(value)).toBe(true); 205 + expect(mocks.output.buffer).toMatchSnapshot(); 206 + }); 207 + 208 + test('withGuide: false removes guide', async () => { 209 + const result = prompts.multiline({ 210 + message: 'foo', 211 + withGuide: false, 212 + input: mocks.input, 213 + output: mocks.output, 214 + }); 215 + 216 + mocks.input.emit('keypress', '', { name: 'return' }); 217 + mocks.input.emit('keypress', '', { name: 'return' }); 218 + 219 + await result; 220 + 221 + expect(mocks.output.buffer).toMatchSnapshot(); 222 + }); 223 + 224 + test('global withGuide: false removes guide', async () => { 225 + updateSettings({ withGuide: false }); 226 + 227 + const result = prompts.multiline({ 228 + message: 'foo', 229 + input: mocks.input, 230 + output: mocks.output, 231 + }); 232 + 233 + mocks.input.emit('keypress', '', { name: 'return' }); 234 + mocks.input.emit('keypress', '', { name: 'return' }); 235 + 236 + await result; 237 + 238 + expect(mocks.output.buffer).toMatchSnapshot(); 239 + }); 240 + 241 + test('renders submit button', async () => { 242 + const result = prompts.multiline({ 243 + message: 'foo', 244 + input: mocks.input, 245 + output: mocks.output, 246 + showSubmit: true, 247 + }); 248 + 249 + mocks.input.emit('keypress', 'x', { name: 'x' }); 250 + mocks.input.emit('keypress', 'y', { name: 'y' }); 251 + mocks.input.emit('keypress', '\t', { name: 'tab' }); 252 + mocks.input.emit('keypress', '', { name: 'return' }); 253 + 254 + const value = await result; 255 + 256 + expect(value).toBe('xy'); 257 + expect(mocks.output.buffer).toMatchSnapshot(); 258 + }); 259 + });
+427
packages/prompts/src/multi-select.test.ts
··· 1 + import { afterEach, beforeEach, describe, expect, test } from 'vitest'; 2 + import * as prompts from './index.js'; 3 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 4 + 5 + describe.each(['true', 'false'])('multiselect (isCI = %s)', (isCI) => { 6 + let mocks: Mocks<{ input: true; output: true }>; 7 + 8 + beforeEach(() => { 9 + mocks = createMocks({ input: true, output: true, env: { CI: isCI } }); 10 + }); 11 + 12 + afterEach(() => { 13 + prompts.updateSettings({ withGuide: true }); 14 + }); 15 + 16 + test('renders message', async () => { 17 + const result = prompts.multiselect({ 18 + message: 'foo', 19 + options: [{ value: 'opt0' }, { value: 'opt1' }], 20 + input: mocks.input, 21 + output: mocks.output, 22 + }); 23 + 24 + mocks.input.emit('keypress', '', { name: 'space' }); 25 + mocks.input.emit('keypress', '', { name: 'return' }); 26 + 27 + const value = await result; 28 + 29 + expect(value).toEqual(['opt0']); 30 + expect(mocks.output.buffer).toMatchSnapshot(); 31 + }); 32 + 33 + test('renders multiple selected options', async () => { 34 + const result = prompts.multiselect({ 35 + message: 'foo', 36 + options: [{ value: 'opt0' }, { value: 'opt1' }, { value: 'opt2' }], 37 + input: mocks.input, 38 + output: mocks.output, 39 + }); 40 + 41 + mocks.input.emit('keypress', '', { name: 'space' }); 42 + mocks.input.emit('keypress', '', { name: 'down' }); 43 + mocks.input.emit('keypress', '', { name: 'space' }); 44 + mocks.input.emit('keypress', '', { name: 'down' }); 45 + mocks.input.emit('keypress', '', { name: 'return' }); 46 + 47 + const value = await result; 48 + 49 + expect(value).toEqual(['opt0', 'opt1']); 50 + expect(mocks.output.buffer).toMatchSnapshot(); 51 + }); 52 + 53 + test('can cancel', async () => { 54 + const result = prompts.multiselect({ 55 + message: 'foo', 56 + options: [{ value: 'opt0' }, { value: 'opt1' }], 57 + input: mocks.input, 58 + output: mocks.output, 59 + }); 60 + 61 + mocks.input.emit('keypress', 'escape', { name: 'escape' }); 62 + 63 + const value = await result; 64 + 65 + expect(prompts.isCancel(value)).toBe(true); 66 + expect(mocks.output.buffer).toMatchSnapshot(); 67 + }); 68 + 69 + test('renders validation errors', async () => { 70 + const result = prompts.multiselect({ 71 + message: 'foo', 72 + options: [{ value: 'opt0' }, { value: 'opt1' }], 73 + input: mocks.input, 74 + output: mocks.output, 75 + }); 76 + 77 + // try submit with nothing selected 78 + mocks.input.emit('keypress', '', { name: 'return' }); 79 + // select and submit 80 + mocks.input.emit('keypress', '', { name: 'space' }); 81 + mocks.input.emit('keypress', '', { name: 'return' }); 82 + 83 + const value = await result; 84 + 85 + expect(value).toEqual(['opt0']); 86 + expect(mocks.output.buffer).toMatchSnapshot(); 87 + }); 88 + 89 + test('can submit without selection when required = false', async () => { 90 + const result = prompts.multiselect({ 91 + message: 'foo', 92 + options: [{ value: 'opt0' }, { value: 'opt1' }], 93 + required: false, 94 + input: mocks.input, 95 + output: mocks.output, 96 + }); 97 + 98 + mocks.input.emit('keypress', '', { name: 'return' }); 99 + 100 + const value = await result; 101 + 102 + expect(value).toEqual([]); 103 + expect(mocks.output.buffer).toMatchSnapshot(); 104 + }); 105 + 106 + test('can set cursorAt to preselect an option', async () => { 107 + const result = prompts.multiselect({ 108 + message: 'foo', 109 + options: [{ value: 'opt0' }, { value: 'opt1' }], 110 + cursorAt: 'opt1', 111 + input: mocks.input, 112 + output: mocks.output, 113 + }); 114 + 115 + mocks.input.emit('keypress', '', { name: 'space' }); 116 + mocks.input.emit('keypress', '', { name: 'return' }); 117 + 118 + const value = await result; 119 + 120 + expect(value).toEqual(['opt1']); 121 + expect(mocks.output.buffer).toMatchSnapshot(); 122 + }); 123 + 124 + test('can set initial values', async () => { 125 + const result = prompts.multiselect({ 126 + message: 'foo', 127 + options: [{ value: 'opt0' }, { value: 'opt1' }], 128 + initialValues: ['opt1'], 129 + input: mocks.input, 130 + output: mocks.output, 131 + }); 132 + 133 + mocks.input.emit('keypress', '', { name: 'return' }); 134 + 135 + const value = await result; 136 + 137 + expect(value).toEqual(['opt1']); 138 + expect(mocks.output.buffer).toMatchSnapshot(); 139 + }); 140 + 141 + test('maxItems renders a sliding window', async () => { 142 + const result = prompts.multiselect({ 143 + message: 'foo', 144 + options: [...Array(12).keys()].map((k) => ({ 145 + value: `opt${k}`, 146 + })), 147 + maxItems: 6, 148 + input: mocks.input, 149 + output: mocks.output, 150 + }); 151 + 152 + for (let i = 0; i < 6; i++) { 153 + mocks.input.emit('keypress', '', { name: 'down' }); 154 + } 155 + mocks.input.emit('keypress', '', { name: 'space' }); 156 + mocks.input.emit('keypress', '', { name: 'return' }); 157 + 158 + const value = await result; 159 + 160 + expect(value).toEqual(['opt6']); 161 + expect(mocks.output.buffer).toMatchSnapshot(); 162 + }); 163 + 164 + test('sliding window loops upwards', async () => { 165 + const result = prompts.multiselect({ 166 + message: 'foo', 167 + options: [...Array(12).keys()].map((k) => ({ 168 + value: `opt${k}`, 169 + })), 170 + maxItems: 6, 171 + input: mocks.input, 172 + output: mocks.output, 173 + }); 174 + 175 + mocks.input.emit('keypress', '', { name: 'up' }); 176 + mocks.input.emit('keypress', '', { name: 'space' }); 177 + mocks.input.emit('keypress', '', { name: 'return' }); 178 + 179 + const value = await result; 180 + 181 + expect(value).toEqual(['opt11']); 182 + expect(mocks.output.buffer).toMatchSnapshot(); 183 + }); 184 + 185 + test('sliding window loops downwards', async () => { 186 + const result = prompts.multiselect({ 187 + message: 'foo', 188 + options: [...Array(12).keys()].map((k) => ({ 189 + value: `opt${k}`, 190 + })), 191 + maxItems: 6, 192 + input: mocks.input, 193 + output: mocks.output, 194 + }); 195 + 196 + for (let i = 0; i < 12; i++) { 197 + mocks.input.emit('keypress', '', { name: 'down' }); 198 + } 199 + mocks.input.emit('keypress', '', { name: 'space' }); 200 + mocks.input.emit('keypress', '', { name: 'return' }); 201 + 202 + const value = await result; 203 + 204 + expect(value).toEqual(['opt0']); 205 + expect(mocks.output.buffer).toMatchSnapshot(); 206 + }); 207 + 208 + test('can set custom labels', async () => { 209 + const result = prompts.multiselect({ 210 + message: 'foo', 211 + options: [ 212 + { value: 'opt0', label: 'Option 0' }, 213 + { value: 'opt1', label: 'Option 1' }, 214 + ], 215 + input: mocks.input, 216 + output: mocks.output, 217 + }); 218 + 219 + mocks.input.emit('keypress', '', { name: 'space' }); 220 + mocks.input.emit('keypress', '', { name: 'return' }); 221 + 222 + const value = await result; 223 + 224 + expect(value).toEqual(['opt0']); 225 + expect(mocks.output.buffer).toMatchSnapshot(); 226 + }); 227 + 228 + test('can render option hints', async () => { 229 + const result = prompts.multiselect({ 230 + message: 'foo', 231 + options: [ 232 + { value: 'opt0', hint: 'Hint 0' }, 233 + { value: 'opt1', hint: 'Hint 1' }, 234 + ], 235 + input: mocks.input, 236 + output: mocks.output, 237 + }); 238 + 239 + mocks.input.emit('keypress', '', { name: 'space' }); 240 + mocks.input.emit('keypress', '', { name: 'return' }); 241 + 242 + const value = await result; 243 + 244 + expect(value).toEqual(['opt0']); 245 + expect(mocks.output.buffer).toMatchSnapshot(); 246 + }); 247 + 248 + test('shows hints for all selected options', async () => { 249 + const result = prompts.multiselect({ 250 + message: 'foo', 251 + options: [ 252 + { value: 'opt0', hint: 'Hint 0' }, 253 + { value: 'opt1', hint: 'Hint 1' }, 254 + { value: 'opt2', hint: 'Hint 2' }, 255 + ], 256 + initialValues: ['opt0', 'opt1'], 257 + input: mocks.input, 258 + output: mocks.output, 259 + }); 260 + 261 + // Check that both selected options show their hints 262 + mocks.input.emit('keypress', '', { name: 'down' }); 263 + mocks.input.emit('keypress', '', { name: 'down' }); 264 + mocks.input.emit('keypress', '', { name: 'return' }); 265 + 266 + const value = await result; 267 + 268 + expect(value).toEqual(['opt0', 'opt1']); 269 + expect(mocks.output.buffer).toMatchSnapshot(); 270 + }); 271 + 272 + test('renders multiple cancelled values', async () => { 273 + const result = prompts.multiselect({ 274 + message: 'foo', 275 + options: [{ value: 'opt0' }, { value: 'opt1' }, { value: 'opt2' }], 276 + input: mocks.input, 277 + output: mocks.output, 278 + }); 279 + 280 + mocks.input.emit('keypress', '', { name: 'space' }); 281 + mocks.input.emit('keypress', '', { name: 'down' }); 282 + mocks.input.emit('keypress', '', { name: 'space' }); 283 + mocks.input.emit('keypress', '', { name: 'escape' }); 284 + 285 + const value = await result; 286 + 287 + expect(prompts.isCancel(value)).toBe(true); 288 + expect(mocks.output.buffer).toMatchSnapshot(); 289 + }); 290 + 291 + test('can be aborted by a signal', async () => { 292 + const controller = new AbortController(); 293 + const result = prompts.multiselect({ 294 + message: 'foo', 295 + options: [{ value: 'opt0' }, { value: 'opt1' }], 296 + input: mocks.input, 297 + output: mocks.output, 298 + signal: controller.signal, 299 + }); 300 + 301 + controller.abort(); 302 + const value = await result; 303 + expect(prompts.isCancel(value)).toBe(true); 304 + expect(mocks.output.buffer).toMatchSnapshot(); 305 + }); 306 + 307 + test('renders disabled options', async () => { 308 + const result = prompts.multiselect({ 309 + message: 'foo', 310 + options: [ 311 + { value: 'opt0', disabled: true }, 312 + { value: 'opt1' }, 313 + { value: 'opt2', disabled: true, hint: 'Hint 2' }, 314 + ], 315 + input: mocks.input, 316 + output: mocks.output, 317 + }); 318 + 319 + mocks.input.emit('keypress', '', { name: 'space' }); 320 + mocks.input.emit('keypress', '', { name: 'return' }); 321 + 322 + const value = await result; 323 + 324 + expect(value).toEqual(['opt1']); 325 + expect(mocks.output.buffer).toMatchSnapshot(); 326 + }); 327 + 328 + test('wraps long messages', async () => { 329 + mocks.output.columns = 40; 330 + 331 + const result = prompts.multiselect({ 332 + message: 'foo '.repeat(20).trim(), 333 + options: [{ value: 'opt0' }, { value: 'opt1' }], 334 + input: mocks.input, 335 + output: mocks.output, 336 + }); 337 + 338 + mocks.input.emit('keypress', '', { name: 'space' }); 339 + mocks.input.emit('keypress', '', { name: 'return' }); 340 + 341 + const value = await result; 342 + 343 + expect(value).toEqual(['opt0']); 344 + expect(mocks.output.buffer).toMatchSnapshot(); 345 + }); 346 + 347 + test('wraps cancelled state with long options', async () => { 348 + mocks.output.columns = 40; 349 + 350 + const result = prompts.multiselect({ 351 + message: 'foo', 352 + options: [ 353 + { value: 'opt0', label: 'Option 0 '.repeat(10).trim() }, 354 + { value: 'opt1', label: 'Option 1 '.repeat(10).trim() }, 355 + ], 356 + input: mocks.input, 357 + output: mocks.output, 358 + }); 359 + 360 + mocks.input.emit('keypress', '', { name: 'space' }); 361 + mocks.input.emit('keypress', 'escape', { name: 'escape' }); 362 + 363 + const value = await result; 364 + 365 + expect(prompts.isCancel(value)).toBe(true); 366 + expect(mocks.output.buffer).toMatchSnapshot(); 367 + }); 368 + 369 + test('wraps success state with long options', async () => { 370 + mocks.output.columns = 40; 371 + 372 + const result = prompts.multiselect({ 373 + message: 'foo', 374 + options: [ 375 + { value: 'opt0', label: 'Option 0 '.repeat(10).trim() }, 376 + { value: 'opt1', label: 'Option 1 '.repeat(10).trim() }, 377 + ], 378 + input: mocks.input, 379 + output: mocks.output, 380 + }); 381 + 382 + mocks.input.emit('keypress', '', { name: 'space' }); 383 + mocks.input.emit('keypress', '', { name: 'return' }); 384 + 385 + const value = await result; 386 + 387 + expect(value).toEqual(['opt0']); 388 + expect(mocks.output.buffer).toMatchSnapshot(); 389 + }); 390 + 391 + test('withGuide: false removes guide', async () => { 392 + const result = prompts.multiselect({ 393 + message: 'foo', 394 + options: [{ value: 'opt0' }, { value: 'opt1' }], 395 + withGuide: false, 396 + input: mocks.input, 397 + output: mocks.output, 398 + }); 399 + 400 + mocks.input.emit('keypress', '', { name: 'space' }); 401 + mocks.input.emit('keypress', '', { name: 'return' }); 402 + 403 + const value = await result; 404 + 405 + expect(value).toEqual(['opt0']); 406 + expect(mocks.output.buffer).toMatchSnapshot(); 407 + }); 408 + 409 + test('global withGuide: false removes guide', async () => { 410 + prompts.updateSettings({ withGuide: false }); 411 + 412 + const result = prompts.multiselect({ 413 + message: 'foo', 414 + options: [{ value: 'opt0' }, { value: 'opt1' }], 415 + input: mocks.input, 416 + output: mocks.output, 417 + }); 418 + 419 + mocks.input.emit('keypress', '', { name: 'space' }); 420 + mocks.input.emit('keypress', '', { name: 'return' }); 421 + 422 + const value = await result; 423 + 424 + expect(value).toEqual(['opt0']); 425 + expect(mocks.output.buffer).toMatchSnapshot(); 426 + }); 427 + });
+106
packages/prompts/src/note.test.ts
··· 1 + import { styleText } from 'node:util'; 2 + import { beforeEach, describe, expect, test } from 'vitest'; 3 + import * as prompts from './index.js'; 4 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 5 + 6 + describe.each(['true', 'false'])('note (isCI = %s)', (isCI) => { 7 + let mocks: Mocks<{ input: true; output: true }>; 8 + 9 + beforeEach(() => { 10 + mocks = createMocks({ input: true, output: true, env: { CI: isCI } }); 11 + }); 12 + 13 + test('renders message with title', () => { 14 + prompts.note('message', 'title', { 15 + input: mocks.input, 16 + output: mocks.output, 17 + }); 18 + 19 + expect(mocks.output.buffer).toMatchSnapshot(); 20 + }); 21 + 22 + test('renders as wide as longest line', () => { 23 + prompts.note('short\nsomewhat questionably long line', 'title', { 24 + input: mocks.input, 25 + output: mocks.output, 26 + }); 27 + 28 + expect(mocks.output.buffer).toMatchSnapshot(); 29 + }); 30 + 31 + test('formatter which adds length works', () => { 32 + prompts.note('line 0\nline 1\nline 2', 'title', { 33 + format: (line) => `* ${line} *`, 34 + input: mocks.input, 35 + output: mocks.output, 36 + }); 37 + 38 + expect(mocks.output.buffer).toMatchSnapshot(); 39 + }); 40 + 41 + test('formatter which adds colors works', () => { 42 + prompts.note('line 0\nline 1\nline 2', 'title', { 43 + format: (line) => styleText('red', line), 44 + input: mocks.input, 45 + output: mocks.output, 46 + }); 47 + 48 + expect(mocks.output.buffer).toMatchSnapshot(); 49 + }); 50 + 51 + test("don't overflow", () => { 52 + const message = `${'test string '.repeat(32)}\n`.repeat(4).trim(); 53 + mocks.output.columns = 75; 54 + prompts.note(message, 'title', { 55 + input: mocks.input, 56 + output: mocks.output, 57 + }); 58 + 59 + expect(mocks.output.buffer).toMatchSnapshot(); 60 + }); 61 + 62 + test("don't overflow with formatter", () => { 63 + const message = `${'test string '.repeat(32)}\n`.repeat(4).trim(); 64 + mocks.output.columns = 75; 65 + prompts.note(message, 'title', { 66 + format: (line) => styleText('red', `* ${styleText('cyan', line)} *`), 67 + input: mocks.input, 68 + output: mocks.output, 69 + }); 70 + 71 + expect(mocks.output.buffer).toMatchSnapshot(); 72 + }); 73 + 74 + test('handle wide characters', () => { 75 + const messages = ['이게 첫 번째 줄이에요', 'これは次の行です']; 76 + mocks.output.columns = 10; 77 + prompts.note(messages.join('\n'), '这是标题', { 78 + input: mocks.input, 79 + output: mocks.output, 80 + }); 81 + 82 + expect(mocks.output.buffer).toMatchSnapshot(); 83 + }); 84 + 85 + test('handle wide characters with formatter', () => { 86 + const messages = ['이게 첫 번째 줄이에요', 'これは次の行です']; 87 + mocks.output.columns = 10; 88 + prompts.note(messages.join('\n'), '这是标题', { 89 + format: (line) => styleText('red', `* ${styleText('cyan', line)} *`), 90 + input: mocks.input, 91 + output: mocks.output, 92 + }); 93 + 94 + expect(mocks.output.buffer).toMatchSnapshot(); 95 + }); 96 + 97 + test('without guide', () => { 98 + prompts.note('message', 'title', { 99 + input: mocks.input, 100 + output: mocks.output, 101 + withGuide: false, 102 + }); 103 + 104 + expect(mocks.output.buffer).toMatchSnapshot(); 105 + }); 106 + });
+172
packages/prompts/src/password.test.ts
··· 1 + import { updateSettings } from '@clack/core'; 2 + import { afterEach, beforeEach, describe, expect, test } from 'vitest'; 3 + import * as prompts from './index.js'; 4 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 5 + 6 + describe.each(['true', 'false'])('password (isCI = %s)', (isCI) => { 7 + let mocks: Mocks<{ input: true; output: true }>; 8 + 9 + beforeEach(() => { 10 + mocks = createMocks({ input: true, output: true, env: { CI: isCI } }); 11 + }); 12 + 13 + afterEach(() => { 14 + updateSettings({ withGuide: true }); 15 + }); 16 + 17 + test('renders message', async () => { 18 + const result = prompts.password({ 19 + message: 'foo', 20 + input: mocks.input, 21 + output: mocks.output, 22 + }); 23 + 24 + mocks.input.emit('keypress', '', { name: 'return' }); 25 + 26 + await result; 27 + 28 + expect(mocks.output.buffer).toMatchSnapshot(); 29 + }); 30 + 31 + test('renders masked value', async () => { 32 + const result = prompts.password({ 33 + message: 'foo', 34 + input: mocks.input, 35 + output: mocks.output, 36 + }); 37 + 38 + mocks.input.emit('keypress', 'x', { name: 'x' }); 39 + mocks.input.emit('keypress', 'y', { name: 'y' }); 40 + mocks.input.emit('keypress', '', { name: 'return' }); 41 + 42 + const value = await result; 43 + 44 + expect(value).toBe('xy'); 45 + expect(mocks.output.buffer).toMatchSnapshot(); 46 + }); 47 + 48 + test('renders custom mask', async () => { 49 + const result = prompts.password({ 50 + message: 'foo', 51 + mask: '*', 52 + input: mocks.input, 53 + output: mocks.output, 54 + }); 55 + 56 + mocks.input.emit('keypress', 'x', { name: 'x' }); 57 + mocks.input.emit('keypress', 'y', { name: 'y' }); 58 + mocks.input.emit('keypress', '', { name: 'return' }); 59 + 60 + await result; 61 + 62 + expect(mocks.output.buffer).toMatchSnapshot(); 63 + }); 64 + 65 + test('renders and clears validation errors', async () => { 66 + const result = prompts.password({ 67 + message: 'foo', 68 + validate: (value) => { 69 + if (!value || value.length < 2) { 70 + return 'Password must be at least 2 characters'; 71 + } 72 + 73 + return undefined; 74 + }, 75 + input: mocks.input, 76 + output: mocks.output, 77 + }); 78 + 79 + mocks.input.emit('keypress', 'x', { name: 'x' }); 80 + mocks.input.emit('keypress', '', { name: 'return' }); 81 + mocks.input.emit('keypress', 'y', { name: 'y' }); 82 + mocks.input.emit('keypress', '', { name: 'return' }); 83 + 84 + const value = await result; 85 + 86 + expect(value).toBe('xy'); 87 + expect(mocks.output.buffer).toMatchSnapshot(); 88 + }); 89 + 90 + test('renders cancelled value', async () => { 91 + const result = prompts.password({ 92 + message: 'foo', 93 + input: mocks.input, 94 + output: mocks.output, 95 + }); 96 + 97 + mocks.input.emit('keypress', 'x', { name: 'x' }); 98 + mocks.input.emit('keypress', '', { name: 'escape' }); 99 + 100 + const value = await result; 101 + 102 + expect(prompts.isCancel(value)).toBe(true); 103 + expect(mocks.output.buffer).toMatchSnapshot(); 104 + }); 105 + 106 + test('can be aborted by a signal', async () => { 107 + const controller = new AbortController(); 108 + const result = prompts.password({ 109 + message: 'foo', 110 + input: mocks.input, 111 + output: mocks.output, 112 + signal: controller.signal, 113 + }); 114 + 115 + controller.abort(); 116 + const value = await result; 117 + expect(prompts.isCancel(value)).toBe(true); 118 + expect(mocks.output.buffer).toMatchSnapshot(); 119 + }); 120 + 121 + test('clears input on error when clearOnError is true', async () => { 122 + const result = prompts.password({ 123 + message: 'foo', 124 + input: mocks.input, 125 + output: mocks.output, 126 + validate: (v) => (v === 'yz' ? undefined : 'Error'), 127 + clearOnError: true, 128 + }); 129 + 130 + mocks.input.emit('keypress', 'x', { name: 'x' }); 131 + mocks.input.emit('keypress', '', { name: 'return' }); 132 + mocks.input.emit('keypress', 'y', { name: 'y' }); 133 + mocks.input.emit('keypress', 'z', { name: 'z' }); 134 + mocks.input.emit('keypress', '', { name: 'return' }); 135 + 136 + const value = await result; 137 + 138 + expect(value).toBe('yz'); 139 + expect(mocks.output.buffer).toMatchSnapshot(); 140 + }); 141 + 142 + test('withGuide: false removes guide', async () => { 143 + const result = prompts.password({ 144 + message: 'foo', 145 + withGuide: false, 146 + input: mocks.input, 147 + output: mocks.output, 148 + }); 149 + 150 + mocks.input.emit('keypress', '', { name: 'return' }); 151 + 152 + await result; 153 + 154 + expect(mocks.output.buffer).toMatchSnapshot(); 155 + }); 156 + 157 + test('global withGuide: false removes guide', async () => { 158 + updateSettings({ withGuide: false }); 159 + 160 + const result = prompts.password({ 161 + message: 'foo', 162 + input: mocks.input, 163 + output: mocks.output, 164 + }); 165 + 166 + mocks.input.emit('keypress', '', { name: 'return' }); 167 + 168 + await result; 169 + 170 + expect(mocks.output.buffer).toMatchSnapshot(); 171 + }); 172 + });
+267
packages/prompts/src/path.test.ts
··· 1 + import { vol } from 'memfs'; 2 + import { beforeEach, describe, expect, test, vi } from 'vitest'; 3 + import * as prompts from './index.js'; 4 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 5 + 6 + vi.mock('node:fs'); 7 + 8 + describe.each(['true', 'false'])('text (isCI = %s)', (isCI) => { 9 + let mocks: Mocks<{ input: true; output: true }>; 10 + 11 + beforeEach(() => { 12 + mocks = createMocks({ input: true, output: true, env: { CI: isCI } }); 13 + vol.reset(); 14 + vol.fromJSON( 15 + { 16 + './foo/bar.txt': '1', 17 + './foo/baz.text': '2', 18 + './hello/world.jpg': '3', 19 + './hello/john.jpg': '4', 20 + './hello/jeanne.png': '5', 21 + './root.zip': '6', 22 + './bar': '7', 23 + }, 24 + '/tmp' 25 + ); 26 + }); 27 + 28 + test('renders message', async () => { 29 + const result = prompts.path({ 30 + message: 'foo', 31 + input: mocks.input, 32 + output: mocks.output, 33 + root: '/tmp/', 34 + }); 35 + 36 + mocks.input.emit('keypress', '', { name: 'return' }); 37 + 38 + const value = await result; 39 + 40 + expect(mocks.output.buffer).toMatchSnapshot(); 41 + expect(value).toBe('/tmp/bar'); 42 + }); 43 + 44 + test('can cancel', async () => { 45 + const result = prompts.path({ 46 + message: 'foo', 47 + root: '/tmp/', 48 + input: mocks.input, 49 + output: mocks.output, 50 + }); 51 + 52 + mocks.input.emit('keypress', 'escape', { name: 'escape' }); 53 + 54 + const value = await result; 55 + 56 + expect(prompts.isCancel(value)).toBe(true); 57 + expect(mocks.output.buffer).toMatchSnapshot(); 58 + }); 59 + 60 + test('renders cancelled value if one set', async () => { 61 + const result = prompts.path({ 62 + message: 'foo', 63 + input: mocks.input, 64 + output: mocks.output, 65 + root: '/tmp/', 66 + }); 67 + 68 + mocks.input.emit('keypress', 'x', { name: 'x' }); 69 + mocks.input.emit('keypress', 'y', { name: 'y' }); 70 + mocks.input.emit('keypress', '', { name: 'escape' }); 71 + 72 + const value = await result; 73 + 74 + expect(prompts.isCancel(value)).toBe(true); 75 + expect(mocks.output.buffer).toMatchSnapshot(); 76 + }); 77 + 78 + test('renders submitted value', async () => { 79 + const result = prompts.path({ 80 + message: 'foo', 81 + root: '/tmp/', 82 + input: mocks.input, 83 + output: mocks.output, 84 + }); 85 + 86 + mocks.input.emit('keypress', 'b', { name: 'b' }); 87 + mocks.input.emit('keypress', 'a', { name: 'a' }); 88 + mocks.input.emit('keypress', '', { name: 'return' }); 89 + 90 + const value = await result; 91 + 92 + expect(value).toBe('/tmp/bar'); 93 + expect(mocks.output.buffer).toMatchSnapshot(); 94 + }); 95 + 96 + test('cannot submit unknown value', async () => { 97 + const result = prompts.path({ 98 + message: 'foo', 99 + root: '/tmp/', 100 + input: mocks.input, 101 + output: mocks.output, 102 + }); 103 + 104 + mocks.input.emit('keypress', '_', { name: '_' }); 105 + mocks.input.emit('keypress', '', { name: 'return' }); 106 + mocks.input.emit('keypress', '', { name: 'h', ctrl: true }); 107 + mocks.input.emit('keypress', 'b', { name: 'b' }); 108 + mocks.input.emit('keypress', '', { name: 'return' }); 109 + 110 + const value = await result; 111 + 112 + expect(value).toBe('/tmp/bar'); 113 + expect(mocks.output.buffer).toMatchSnapshot(); 114 + }); 115 + 116 + test('initialValue sets the value', async () => { 117 + const result = prompts.path({ 118 + message: 'foo', 119 + initialValue: '/tmp/bar', 120 + root: '/tmp/', 121 + input: mocks.input, 122 + output: mocks.output, 123 + }); 124 + 125 + mocks.input.emit('keypress', '', { name: 'return' }); 126 + 127 + const value = await result; 128 + 129 + expect(value).toBe('/tmp/bar'); 130 + expect(mocks.output.buffer).toMatchSnapshot(); 131 + }); 132 + 133 + test('directory mode only allows selecting directories', async () => { 134 + const result = prompts.path({ 135 + message: 'foo', 136 + root: '/tmp/', 137 + directory: true, 138 + input: mocks.input, 139 + output: mocks.output, 140 + }); 141 + 142 + mocks.input.emit('keypress', 'f', { name: 'f' }); 143 + mocks.input.emit('keypress', '', { name: 'return' }); 144 + 145 + const value = await result; 146 + 147 + expect(value).toBe('/tmp/foo'); 148 + }); 149 + 150 + test('directory mode submits initial directory value on enter', async () => { 151 + const result = prompts.path({ 152 + message: 'foo', 153 + root: '/tmp/', 154 + initialValue: '/tmp', 155 + directory: true, 156 + input: mocks.input, 157 + output: mocks.output, 158 + }); 159 + 160 + mocks.input.emit('keypress', '', { name: 'return' }); 161 + 162 + const value = await result; 163 + 164 + expect(value).toBe('/tmp'); 165 + }); 166 + 167 + test('directory mode traverses into child when trailing slash entered', async () => { 168 + const result = prompts.path({ 169 + message: 'foo', 170 + root: '/tmp/', 171 + initialValue: '/tmp', 172 + directory: true, 173 + input: mocks.input, 174 + output: mocks.output, 175 + }); 176 + 177 + mocks.input.emit('keypress', '/', { name: '/' }); 178 + mocks.input.emit('keypress', '', { name: 'return' }); 179 + 180 + const value = await result; 181 + 182 + expect(value).toBe('/tmp/foo'); 183 + }); 184 + 185 + test('directory mode can navigate from initial directory to child directory', async () => { 186 + const result = prompts.path({ 187 + message: 'foo', 188 + root: '/tmp/', 189 + initialValue: '/tmp/', 190 + directory: true, 191 + input: mocks.input, 192 + output: mocks.output, 193 + }); 194 + 195 + mocks.input.emit('keypress', 'f', { name: 'f' }); 196 + mocks.input.emit('keypress', '', { name: 'return' }); 197 + 198 + const value = await result; 199 + 200 + expect(value).toBe('/tmp/foo'); 201 + }); 202 + 203 + test('default mode allows selecting files', async () => { 204 + const result = prompts.path({ 205 + message: 'foo', 206 + root: '/tmp/', 207 + input: mocks.input, 208 + output: mocks.output, 209 + }); 210 + 211 + mocks.input.emit('keypress', 'r', { name: 'r' }); 212 + mocks.input.emit('keypress', 'o', { name: 'o' }); 213 + mocks.input.emit('keypress', 'o', { name: 'o' }); 214 + mocks.input.emit('keypress', 't', { name: 't' }); 215 + mocks.input.emit('keypress', '', { name: 'return' }); 216 + 217 + const value = await result; 218 + 219 + expect(value).toBe('/tmp/root.zip'); 220 + }); 221 + 222 + test('validation errors render and clear', async () => { 223 + const result = prompts.path({ 224 + message: 'foo', 225 + root: '/tmp/', 226 + validate: (val) => (val !== '/tmp/bar' ? 'should be /tmp/bar' : undefined), 227 + input: mocks.input, 228 + output: mocks.output, 229 + }); 230 + 231 + // to match `root.zip` 232 + mocks.input.emit('keypress', 'r', { name: 'r' }); 233 + mocks.input.emit('keypress', '', { name: 'return' }); 234 + // delete what we had 235 + mocks.input.emit('keypress', '', { name: 'h', ctrl: true }); 236 + mocks.input.emit('keypress', 'b', { name: 'b' }); 237 + mocks.input.emit('keypress', '', { name: 'return' }); 238 + 239 + const value = await result; 240 + 241 + expect(value).toBe('/tmp/bar'); 242 + expect(mocks.output.buffer).toMatchSnapshot(); 243 + }); 244 + 245 + test('validation errors render and clear (using Error)', async () => { 246 + const result = prompts.path({ 247 + message: 'foo', 248 + root: '/tmp/', 249 + validate: (val) => (val !== '/tmp/bar' ? new Error('should be /tmp/bar') : undefined), 250 + input: mocks.input, 251 + output: mocks.output, 252 + }); 253 + 254 + // to match `root.zip` 255 + mocks.input.emit('keypress', 'r', { name: 'r' }); 256 + mocks.input.emit('keypress', '', { name: 'return' }); 257 + // delete what we had 258 + mocks.input.emit('keypress', '', { name: 'h', ctrl: true }); 259 + mocks.input.emit('keypress', 'b', { name: 'b' }); 260 + mocks.input.emit('keypress', '', { name: 'return' }); 261 + 262 + const value = await result; 263 + 264 + expect(value).toBe('/tmp/bar'); 265 + expect(mocks.output.buffer).toMatchSnapshot(); 266 + }); 267 + });
+355
packages/prompts/src/select.test.ts
··· 1 + import { updateSettings } from '@clack/core'; 2 + import { afterEach, beforeEach, describe, expect, test } from 'vitest'; 3 + import * as prompts from './index.js'; 4 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 5 + 6 + describe.each(['true', 'false'])('select (isCI = %s)', (isCI) => { 7 + let mocks: Mocks<{ input: true; output: true }>; 8 + 9 + beforeEach(() => { 10 + mocks = createMocks({ input: true, output: true, env: { CI: isCI } }); 11 + }); 12 + 13 + afterEach(() => { 14 + updateSettings({ withGuide: true }); 15 + }); 16 + 17 + test('renders options and message', async () => { 18 + const result = prompts.select({ 19 + message: 'foo', 20 + options: [{ value: 'opt0' }, { value: 'opt1' }], 21 + input: mocks.input, 22 + output: mocks.output, 23 + }); 24 + 25 + mocks.input.emit('keypress', '', { name: 'return' }); 26 + 27 + const value = await result; 28 + 29 + expect(value).toBe('opt0'); 30 + expect(mocks.output.buffer).toMatchSnapshot(); 31 + }); 32 + 33 + test('down arrow selects next option', async () => { 34 + const result = prompts.select({ 35 + message: 'foo', 36 + options: [{ value: 'opt0' }, { value: 'opt1' }], 37 + input: mocks.input, 38 + output: mocks.output, 39 + }); 40 + 41 + mocks.input.emit('keypress', '', { name: 'down' }); 42 + mocks.input.emit('keypress', '', { name: 'return' }); 43 + 44 + const value = await result; 45 + 46 + expect(value).toBe('opt1'); 47 + expect(mocks.output.buffer).toMatchSnapshot(); 48 + }); 49 + 50 + test('up arrow selects previous option', async () => { 51 + const result = prompts.select({ 52 + message: 'foo', 53 + options: [{ value: 'opt0' }, { value: 'opt1' }], 54 + input: mocks.input, 55 + output: mocks.output, 56 + }); 57 + 58 + mocks.input.emit('keypress', '', { name: 'down' }); 59 + mocks.input.emit('keypress', '', { name: 'up' }); 60 + mocks.input.emit('keypress', '', { name: 'return' }); 61 + 62 + const value = await result; 63 + 64 + expect(value).toBe('opt0'); 65 + expect(mocks.output.buffer).toMatchSnapshot(); 66 + }); 67 + 68 + test('can cancel', async () => { 69 + const result = prompts.select({ 70 + message: 'foo', 71 + options: [{ value: 'opt0' }, { value: 'opt1' }], 72 + input: mocks.input, 73 + output: mocks.output, 74 + }); 75 + 76 + mocks.input.emit('keypress', 'escape', { name: 'escape' }); 77 + 78 + const value = await result; 79 + 80 + expect(prompts.isCancel(value)).toBe(true); 81 + expect(mocks.output.buffer).toMatchSnapshot(); 82 + }); 83 + 84 + test('renders option labels', async () => { 85 + const result = prompts.select({ 86 + message: 'foo', 87 + options: [ 88 + { value: 'opt0', label: 'Option 0' }, 89 + { value: 'opt1', label: 'Option 1' }, 90 + ], 91 + input: mocks.input, 92 + output: mocks.output, 93 + }); 94 + 95 + mocks.input.emit('keypress', '', { name: 'return' }); 96 + 97 + const value = await result; 98 + 99 + expect(value).toBe('opt0'); 100 + expect(mocks.output.buffer).toMatchSnapshot(); 101 + }); 102 + 103 + test('renders option hints', async () => { 104 + const result = prompts.select({ 105 + message: 'foo', 106 + options: [ 107 + { value: 'opt0', hint: 'Hint 0' }, 108 + { value: 'opt1', hint: 'Hint 1' }, 109 + ], 110 + input: mocks.input, 111 + output: mocks.output, 112 + }); 113 + 114 + mocks.input.emit('keypress', '', { name: 'return' }); 115 + 116 + const value = await result; 117 + 118 + expect(value).toBe('opt0'); 119 + expect(mocks.output.buffer).toMatchSnapshot(); 120 + }); 121 + 122 + test('can be aborted by a signal', async () => { 123 + const controller = new AbortController(); 124 + const result = prompts.select({ 125 + message: 'foo', 126 + options: [{ value: 'opt0' }, { value: 'opt1' }], 127 + input: mocks.input, 128 + output: mocks.output, 129 + signal: controller.signal, 130 + }); 131 + 132 + controller.abort(); 133 + const value = await result; 134 + expect(prompts.isCancel(value)).toBe(true); 135 + expect(mocks.output.buffer).toMatchSnapshot(); 136 + }); 137 + 138 + test('renders disabled options', async () => { 139 + const result = prompts.select({ 140 + message: 'foo', 141 + options: [ 142 + { value: 'opt0', label: 'Option 0', disabled: true }, 143 + { value: 'opt1', label: 'Option 1' }, 144 + { value: 'opt2', label: 'Option 2', disabled: true, hint: 'Hint 2' }, 145 + ], 146 + input: mocks.input, 147 + output: mocks.output, 148 + }); 149 + 150 + mocks.input.emit('keypress', '', { name: 'return' }); 151 + 152 + const value = await result; 153 + 154 + expect(value).toBe('opt1'); 155 + expect(mocks.output.buffer).toMatchSnapshot(); 156 + }); 157 + 158 + test('wraps long results', async () => { 159 + mocks.output.columns = 40; 160 + 161 + const result = prompts.select({ 162 + message: 'foo', 163 + options: [ 164 + { 165 + value: 'opt0', 166 + label: 'foo '.repeat(30).trim(), 167 + }, 168 + { value: 'opt1', label: 'Option 1' }, 169 + ], 170 + input: mocks.input, 171 + output: mocks.output, 172 + }); 173 + 174 + mocks.input.emit('keypress', '', { name: 'return' }); 175 + 176 + await result; 177 + 178 + expect(mocks.output.buffer).toMatchSnapshot(); 179 + }); 180 + 181 + test('wraps long cancelled message', async () => { 182 + mocks.output.columns = 40; 183 + 184 + const result = prompts.select({ 185 + message: 'foo', 186 + options: [ 187 + { 188 + value: 'opt0', 189 + label: 'foo '.repeat(30).trim(), 190 + }, 191 + { value: 'opt1', label: 'Option 1' }, 192 + ], 193 + input: mocks.input, 194 + output: mocks.output, 195 + }); 196 + 197 + mocks.input.emit('keypress', 'escape', { name: 'escape' }); 198 + 199 + await result; 200 + 201 + expect(mocks.output.buffer).toMatchSnapshot(); 202 + }); 203 + 204 + test('wraps long messages', async () => { 205 + mocks.output.columns = 40; 206 + 207 + const result = prompts.select({ 208 + message: 'foo '.repeat(20).trim(), 209 + options: [{ value: 'opt0' }, { value: 'opt1' }], 210 + input: mocks.input, 211 + output: mocks.output, 212 + }); 213 + 214 + mocks.input.emit('keypress', '', { name: 'return' }); 215 + 216 + const value = await result; 217 + 218 + expect(value).toEqual('opt0'); 219 + expect(mocks.output.buffer).toMatchSnapshot(); 220 + }); 221 + 222 + test('renders multi-line option labels', async () => { 223 + const result = prompts.select({ 224 + message: 'foo', 225 + options: [ 226 + { value: 'opt0', label: 'Option 0\nwith multiple lines' }, 227 + { value: 'opt1', label: 'Option 1' }, 228 + ], 229 + input: mocks.input, 230 + output: mocks.output, 231 + }); 232 + 233 + mocks.input.emit('keypress', '', { name: 'down' }); 234 + mocks.input.emit('keypress', '', { name: 'return' }); 235 + 236 + await result; 237 + 238 + expect(mocks.output.buffer).toMatchSnapshot(); 239 + }); 240 + 241 + test('handles mixed size re-renders', async () => { 242 + mocks.output.rows = 10; 243 + 244 + const result = prompts.select({ 245 + message: 'Whatever', 246 + options: [ 247 + { 248 + value: 'longopt', 249 + label: Array.from({ length: 8 }, () => 'Long Option').join('\n'), 250 + }, 251 + ...Array.from({ length: 4 }, (_, i) => ({ 252 + value: `opt${i}`, 253 + label: `Option ${i}`, 254 + })), 255 + ], 256 + input: mocks.input, 257 + output: mocks.output, 258 + }); 259 + 260 + mocks.input.emit('keypress', '', { name: 'up' }); 261 + mocks.input.emit('keypress', '', { name: 'return' }); 262 + 263 + await result; 264 + 265 + expect(mocks.output.buffer).toMatchSnapshot(); 266 + }); 267 + 268 + test('correctly limits options when message wraps to multiple lines', async () => { 269 + // Simulate a narrow terminal that forces the message to wrap 270 + mocks.output.columns = 30; 271 + mocks.output.rows = 12; 272 + 273 + const result = prompts.select({ 274 + // Long message that will wrap to multiple lines in a 30-column terminal 275 + message: 'This is a very long message that will wrap to multiple lines', 276 + options: Array.from({ length: 10 }, (_, i) => ({ 277 + value: `opt${i}`, 278 + label: `Option ${i}`, 279 + })), 280 + input: mocks.input, 281 + output: mocks.output, 282 + }); 283 + 284 + // Scroll down through options to trigger the bug scenario 285 + mocks.input.emit('keypress', '', { name: 'down' }); 286 + mocks.input.emit('keypress', '', { name: 'down' }); 287 + mocks.input.emit('keypress', '', { name: 'down' }); 288 + mocks.input.emit('keypress', '', { name: 'down' }); 289 + mocks.input.emit('keypress', '', { name: 'return' }); 290 + 291 + const value = await result; 292 + 293 + expect(value).toBe('opt4'); 294 + expect(mocks.output.buffer).toMatchSnapshot(); 295 + }); 296 + 297 + test('withGuide: false removes guide', async () => { 298 + const result = prompts.select({ 299 + message: 'foo', 300 + options: [{ value: 'opt0' }, { value: 'opt1' }], 301 + withGuide: false, 302 + input: mocks.input, 303 + output: mocks.output, 304 + }); 305 + 306 + mocks.input.emit('keypress', '', { name: 'return' }); 307 + 308 + await result; 309 + 310 + expect(mocks.output.buffer).toMatchSnapshot(); 311 + }); 312 + 313 + test('global withGuide: false removes guide', async () => { 314 + updateSettings({ withGuide: false }); 315 + 316 + const result = prompts.select({ 317 + message: 'foo', 318 + options: [{ value: 'opt0' }, { value: 'opt1' }], 319 + input: mocks.input, 320 + output: mocks.output, 321 + }); 322 + 323 + mocks.input.emit('keypress', '', { name: 'return' }); 324 + 325 + await result; 326 + 327 + expect(mocks.output.buffer).toMatchSnapshot(); 328 + }); 329 + 330 + test('correctly limits options with explicit multiline message', async () => { 331 + mocks.output.rows = 12; 332 + 333 + const result = prompts.select({ 334 + // Explicit multiline message 335 + message: 'Choose an option:\nLine 2 of the message\nLine 3 of the message', 336 + options: Array.from({ length: 10 }, (_, i) => ({ 337 + value: `opt${i}`, 338 + label: `Option ${i}`, 339 + })), 340 + input: mocks.input, 341 + output: mocks.output, 342 + }); 343 + 344 + // Scroll down to test that options don't overflow 345 + mocks.input.emit('keypress', '', { name: 'down' }); 346 + mocks.input.emit('keypress', '', { name: 'down' }); 347 + mocks.input.emit('keypress', '', { name: 'down' }); 348 + mocks.input.emit('keypress', '', { name: 'return' }); 349 + 350 + const value = await result; 351 + 352 + expect(value).toBe('opt3'); 353 + expect(mocks.output.buffer).toMatchSnapshot(); 354 + }); 355 + });
+228
packages/prompts/src/text.test.ts
··· 1 + import { updateSettings } from '@clack/core'; 2 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 3 + import { afterEach, beforeEach, describe, expect, test } from 'vitest'; 4 + import * as prompts from './index.js'; 5 + 6 + describe.each(['true', 'false'])('text (isCI = %s)', (isCI) => { 7 + let mocks: Mocks<{ input: true; output: true }>; 8 + 9 + beforeEach(() => { 10 + mocks = createMocks({ input: true, output: true, env: { CI: isCI } }); 11 + }); 12 + 13 + afterEach(() => { 14 + updateSettings({ withGuide: true }); 15 + }); 16 + 17 + test('renders message', async () => { 18 + const result = prompts.text({ 19 + message: 'foo', 20 + input: mocks.input, 21 + output: mocks.output, 22 + }); 23 + 24 + mocks.input.emit('keypress', '', { name: 'return' }); 25 + 26 + await result; 27 + 28 + expect(mocks.output.buffer).toMatchSnapshot(); 29 + }); 30 + 31 + test('renders placeholder if set', async () => { 32 + const result = prompts.text({ 33 + message: 'foo', 34 + placeholder: 'bar', 35 + input: mocks.input, 36 + output: mocks.output, 37 + }); 38 + 39 + mocks.input.emit('keypress', '', { name: 'return' }); 40 + 41 + const value = await result; 42 + 43 + expect(mocks.output.buffer).toMatchSnapshot(); 44 + expect(value).toBe(''); 45 + }); 46 + 47 + test('can cancel', async () => { 48 + const result = prompts.text({ 49 + message: 'foo', 50 + input: mocks.input, 51 + output: mocks.output, 52 + }); 53 + 54 + mocks.input.emit('keypress', 'escape', { name: 'escape' }); 55 + 56 + const value = await result; 57 + 58 + expect(prompts.isCancel(value)).toBe(true); 59 + expect(mocks.output.buffer).toMatchSnapshot(); 60 + }); 61 + 62 + test('renders cancelled value if one set', async () => { 63 + const result = prompts.text({ 64 + message: 'foo', 65 + input: mocks.input, 66 + output: mocks.output, 67 + }); 68 + 69 + mocks.input.emit('keypress', 'x', { name: 'x' }); 70 + mocks.input.emit('keypress', 'y', { name: 'y' }); 71 + mocks.input.emit('keypress', '', { name: 'escape' }); 72 + 73 + const value = await result; 74 + 75 + expect(prompts.isCancel(value)).toBe(true); 76 + expect(mocks.output.buffer).toMatchSnapshot(); 77 + }); 78 + 79 + test('renders submitted value', async () => { 80 + const result = prompts.text({ 81 + message: 'foo', 82 + input: mocks.input, 83 + output: mocks.output, 84 + }); 85 + 86 + mocks.input.emit('keypress', 'x', { name: 'x' }); 87 + mocks.input.emit('keypress', 'y', { name: 'y' }); 88 + mocks.input.emit('keypress', '', { name: 'return' }); 89 + 90 + const value = await result; 91 + 92 + expect(value).toBe('xy'); 93 + expect(mocks.output.buffer).toMatchSnapshot(); 94 + }); 95 + 96 + test('defaultValue sets the value but does not render', async () => { 97 + const result = prompts.text({ 98 + message: 'foo', 99 + defaultValue: 'bar', 100 + input: mocks.input, 101 + output: mocks.output, 102 + }); 103 + 104 + mocks.input.emit('keypress', '', { name: 'return' }); 105 + 106 + const value = await result; 107 + 108 + expect(value).toBe('bar'); 109 + expect(mocks.output.buffer).toMatchSnapshot(); 110 + }); 111 + 112 + test('validation errors render and clear', async () => { 113 + const result = prompts.text({ 114 + message: 'foo', 115 + validate: (val) => (val !== 'xy' ? 'should be xy' : undefined), 116 + input: mocks.input, 117 + output: mocks.output, 118 + }); 119 + 120 + mocks.input.emit('keypress', 'x', { name: 'x' }); 121 + mocks.input.emit('keypress', '', { name: 'return' }); 122 + mocks.input.emit('keypress', 'y', { name: 'y' }); 123 + mocks.input.emit('keypress', '', { name: 'return' }); 124 + 125 + const value = await result; 126 + 127 + expect(value).toBe('xy'); 128 + expect(mocks.output.buffer).toMatchSnapshot(); 129 + }); 130 + 131 + test('validation errors render and clear (using Error)', async () => { 132 + const result = prompts.text({ 133 + message: 'foo', 134 + validate: (val) => (val !== 'xy' ? new Error('should be xy') : undefined), 135 + input: mocks.input, 136 + output: mocks.output, 137 + }); 138 + 139 + mocks.input.emit('keypress', 'x', { name: 'x' }); 140 + mocks.input.emit('keypress', '', { name: 'return' }); 141 + mocks.input.emit('keypress', 'y', { name: 'y' }); 142 + mocks.input.emit('keypress', '', { name: 'return' }); 143 + 144 + const value = await result; 145 + 146 + expect(value).toBe('xy'); 147 + expect(mocks.output.buffer).toMatchSnapshot(); 148 + }); 149 + 150 + test('placeholder is not used as value when pressing enter', async () => { 151 + const result = prompts.text({ 152 + message: 'foo', 153 + placeholder: ' (hit Enter to use default)', 154 + defaultValue: 'default-value', 155 + input: mocks.input, 156 + output: mocks.output, 157 + }); 158 + 159 + mocks.input.emit('keypress', '', { name: 'return' }); 160 + 161 + const value = await result; 162 + 163 + expect(value).toBe('default-value'); 164 + expect(mocks.output.buffer).toMatchSnapshot(); 165 + }); 166 + 167 + test('empty string when no value and no default', async () => { 168 + const result = prompts.text({ 169 + message: 'foo', 170 + placeholder: ' (hit Enter to use default)', 171 + input: mocks.input, 172 + output: mocks.output, 173 + }); 174 + 175 + mocks.input.emit('keypress', '', { name: 'return' }); 176 + 177 + const value = await result; 178 + 179 + expect(value).toBe(''); 180 + expect(mocks.output.buffer).toMatchSnapshot(); 181 + }); 182 + 183 + test('can be aborted by a signal', async () => { 184 + const controller = new AbortController(); 185 + const result = prompts.text({ 186 + message: 'foo', 187 + input: mocks.input, 188 + output: mocks.output, 189 + signal: controller.signal, 190 + }); 191 + 192 + controller.abort(); 193 + const value = await result; 194 + expect(prompts.isCancel(value)).toBe(true); 195 + expect(mocks.output.buffer).toMatchSnapshot(); 196 + }); 197 + 198 + test('withGuide: false removes guide', async () => { 199 + const result = prompts.text({ 200 + message: 'foo', 201 + withGuide: false, 202 + input: mocks.input, 203 + output: mocks.output, 204 + }); 205 + 206 + mocks.input.emit('keypress', '', { name: 'return' }); 207 + 208 + await result; 209 + 210 + expect(mocks.output.buffer).toMatchSnapshot(); 211 + }); 212 + 213 + test('global withGuide: false removes guide', async () => { 214 + updateSettings({ withGuide: false }); 215 + 216 + const result = prompts.text({ 217 + message: 'foo', 218 + input: mocks.input, 219 + output: mocks.output, 220 + }); 221 + 222 + mocks.input.emit('keypress', '', { name: 'return' }); 223 + 224 + await result; 225 + 226 + expect(mocks.output.buffer).toMatchSnapshot(); 227 + }); 228 + });
-895
packages/prompts/test/__snapshots__/autocomplete.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`autocomplete > autocompleteMultiselect respects global withGuide: false 1`] = ` 4 - [ 5 - "<cursor.hide>", 6 - "<cyan>◆</fg> Select fruits 7 - 8 - <dim>Search:</bold> _ 9 - <dim>◻</bold> Apple 10 - <dim>◻</bold> <dim>Banana</bold> 11 - <dim>◻</bold> <dim>Cherry</bold> 12 - <dim>◻</bold> <dim>Grape</bold> 13 - <dim>◻</bold> <dim>Orange</bold> 14 - <dim>↑/↓</bold> to navigate • <dim>Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 15 - ", 16 - "<cursor.backward count=999><cursor.up count=9>", 17 - "<cursor.down count=2>", 18 - "<erase.down>", 19 - "<dim>Search:</bold> <dim></bold> 20 - <dim>◻</bold> <dim>Apple</bold> 21 - <dim>◻</bold> Banana 22 - <dim>◻</bold> <dim>Cherry</bold> 23 - <dim>◻</bold> <dim>Grape</bold> 24 - <dim>◻</bold> <dim>Orange</bold> 25 - <dim>↑/↓</bold> to navigate • <dim>Space/Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 26 - ", 27 - "<cursor.backward count=999><cursor.up count=9>", 28 - "<cursor.down count=4>", 29 - "<erase.line><cursor.left count=1>", 30 - "<green>◼</fg> Banana", 31 - "<cursor.down count=5>", 32 - "<cursor.backward count=999><cursor.up count=9>", 33 - "<erase.down>", 34 - "<green>◇</fg> Select fruits 35 - <dim>1 items selected</bold>", 36 - " 37 - ", 38 - "<cursor.show>", 39 - ] 40 - `; 41 - 42 - exports[`autocomplete > autocompleteMultiselect respects withGuide: false 1`] = ` 43 - [ 44 - "<cursor.hide>", 45 - "<cyan>◆</fg> Select fruits 46 - 47 - <dim>Search:</bold> _ 48 - <dim>◻</bold> Apple 49 - <dim>◻</bold> <dim>Banana</bold> 50 - <dim>◻</bold> <dim>Cherry</bold> 51 - <dim>◻</bold> <dim>Grape</bold> 52 - <dim>◻</bold> <dim>Orange</bold> 53 - <dim>↑/↓</bold> to navigate • <dim>Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 54 - ", 55 - "<cursor.backward count=999><cursor.up count=9>", 56 - "<cursor.down count=2>", 57 - "<erase.down>", 58 - "<dim>Search:</bold> <dim></bold> 59 - <dim>◻</bold> <dim>Apple</bold> 60 - <dim>◻</bold> Banana 61 - <dim>◻</bold> <dim>Cherry</bold> 62 - <dim>◻</bold> <dim>Grape</bold> 63 - <dim>◻</bold> <dim>Orange</bold> 64 - <dim>↑/↓</bold> to navigate • <dim>Space/Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 65 - ", 66 - "<cursor.backward count=999><cursor.up count=9>", 67 - "<cursor.down count=4>", 68 - "<erase.line><cursor.left count=1>", 69 - "<green>◼</fg> Banana", 70 - "<cursor.down count=5>", 71 - "<cursor.backward count=999><cursor.up count=9>", 72 - "<erase.down>", 73 - "<green>◇</fg> Select fruits 74 - <dim>1 items selected</bold>", 75 - " 76 - ", 77 - "<cursor.show>", 78 - ] 79 - `; 80 - 81 - exports[`autocomplete > can be aborted by a signal 1`] = ` 82 - [ 83 - "<cursor.hide>", 84 - "<dim>│</fg> 85 - <cyan>◆</fg> foo 86 - <cyan>│</fg> 87 - <cyan>│</fg> <dim>Search:</bold> _ 88 - <cyan>│</fg> <green>●</fg> Apple 89 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 90 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 91 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 92 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 93 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 94 - <cyan>└</fg>", 95 - " 96 - ", 97 - "<cursor.show>", 98 - ] 99 - `; 100 - 101 - exports[`autocomplete > cannot select disabled options when only one left 1`] = ` 102 - [ 103 - "<cursor.hide>", 104 - "<dim>│</fg> 105 - <cyan>◆</fg> Select a fruit 106 - <cyan>│</fg> 107 - <cyan>│</fg> <dim>Search:</bold> _ 108 - <cyan>│</fg> <green>●</fg> Apple 109 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 110 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 111 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 112 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 113 - <cyan>│</fg> <dim>○</fg> <dim>Kiwi</fg> 114 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 115 - <cyan>└</fg>", 116 - "<cursor.backward count=999><cursor.up count=11>", 117 - "<cursor.down count=3>", 118 - "<erase.down>", 119 - "<cyan>│</fg> <dim>Search:</bold> k█<dim> (1 match)</bold> 120 - <cyan>│</fg> <dim>○</fg> <dim>Kiwi</fg> 121 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 122 - <cyan>└</fg>", 123 - "<cursor.backward count=999><cursor.up count=6>", 124 - "<cursor.down count=1>", 125 - "<erase.down>", 126 - "<green>◇</fg> Select a fruit 127 - <dim>│</fg>", 128 - " 129 - ", 130 - "<cursor.show>", 131 - ] 132 - `; 133 - 134 - exports[`autocomplete > displays disabled options correctly 1`] = ` 135 - [ 136 - "<cursor.hide>", 137 - "<dim>│</fg> 138 - <cyan>◆</fg> Select a fruit 139 - <cyan>│</fg> 140 - <cyan>│</fg> <dim>Search:</bold> _ 141 - <cyan>│</fg> <green>●</fg> Apple 142 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 143 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 144 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 145 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 146 - <cyan>│</fg> <dim>○</fg> <dim>Kiwi</fg> 147 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 148 - <cyan>└</fg>", 149 - "<cursor.backward count=999><cursor.up count=11>", 150 - "<cursor.down count=3>", 151 - "<erase.down>", 152 - "<cyan>│</fg> <dim>Search:</bold> 153 - <cyan>│</fg> <dim>○</bold> <dim>Apple</bold> 154 - <cyan>│</fg> <green>●</fg> Banana 155 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 156 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 157 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 158 - <cyan>│</fg> <dim>○</fg> <dim>Kiwi</fg> 159 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 160 - <cyan>└</fg>", 161 - "<cursor.backward count=999><cursor.up count=11>", 162 - "<cursor.down count=5>", 163 - "<erase.down>", 164 - "<cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 165 - <cyan>│</fg> <green>●</fg> Cherry 166 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 167 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 168 - <cyan>│</fg> <dim>○</fg> <dim>Kiwi</fg> 169 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 170 - <cyan>└</fg>", 171 - "<cursor.backward count=999><cursor.up count=11>", 172 - "<cursor.down count=6>", 173 - "<erase.down>", 174 - "<cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 175 - <cyan>│</fg> <green>●</fg> Grape 176 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 177 - <cyan>│</fg> <dim>○</fg> <dim>Kiwi</fg> 178 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 179 - <cyan>└</fg>", 180 - "<cursor.backward count=999><cursor.up count=11>", 181 - "<cursor.down count=7>", 182 - "<erase.down>", 183 - "<cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 184 - <cyan>│</fg> <green>●</fg> Orange 185 - <cyan>│</fg> <dim>○</fg> <dim>Kiwi</fg> 186 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 187 - <cyan>└</fg>", 188 - "<cursor.backward count=999><cursor.up count=11>", 189 - "<cursor.down count=4>", 190 - "<erase.down>", 191 - "<cyan>│</fg> <green>●</fg> Apple 192 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 193 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 194 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 195 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 196 - <cyan>│</fg> <dim>○</fg> <dim>Kiwi</fg> 197 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 198 - <cyan>└</fg>", 199 - "<cursor.backward count=999><cursor.up count=11>", 200 - "<cursor.down count=1>", 201 - "<erase.down>", 202 - "<green>◇</fg> Select a fruit 203 - <dim>│</fg> <dim>Apple</bold>", 204 - " 205 - ", 206 - "<cursor.show>", 207 - ] 208 - `; 209 - 210 - exports[`autocomplete > limits displayed options when maxItems is set 1`] = ` 211 - [ 212 - "<cursor.hide>", 213 - "<dim>│</fg> 214 - <cyan>◆</fg> Select an option 215 - <cyan>│</fg> 216 - <cyan>│</fg> <dim>Search:</bold> _ 217 - <cyan>│</fg> <green>●</fg> Option 0 218 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 219 - <cyan>│</fg> <dim>○</bold> <dim>Option 2</bold> 220 - <cyan>│</fg> <dim>○</bold> <dim>Option 3</bold> 221 - <cyan>│</fg> <dim>○</bold> <dim>Option 4</bold> 222 - <cyan>│</fg> <dim>...</bold> 223 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 224 - <cyan>└</fg>", 225 - "<cursor.backward count=999><cursor.up count=11>", 226 - "<cursor.down count=1>", 227 - "<erase.down>", 228 - "<green>◇</fg> Select an option 229 - <dim>│</fg> <dim>Option 0</bold>", 230 - " 231 - ", 232 - "<cursor.show>", 233 - ] 234 - `; 235 - 236 - exports[`autocomplete > placeholder is shown if set 1`] = ` 237 - [ 238 - "<cursor.hide>", 239 - "<dim>│</fg> 240 - <cyan>◆</fg> Select a fruit 241 - <cyan>│</fg> 242 - <cyan>│</fg> <dim>Search:</bold> <dim>Type to search...</bold> 243 - <cyan>│</fg> <green>●</fg> Apple 244 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 245 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 246 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 247 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 248 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 249 - <cyan>└</fg>", 250 - "<cursor.backward count=999><cursor.up count=10>", 251 - "<cursor.down count=3>", 252 - "<erase.down>", 253 - "<cyan>│</fg> <dim>Search:</bold> g█<dim> (2 matches)</bold> 254 - <cyan>│</fg> <green>●</fg> Grape 255 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 256 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 257 - <cyan>└</fg>", 258 - "<cursor.backward count=999><cursor.up count=7>", 259 - "<cursor.down count=1>", 260 - "<erase.down>", 261 - "<green>◇</fg> Select a fruit 262 - <dim>│</fg> <dim>Grape</bold>", 263 - " 264 - ", 265 - "<cursor.show>", 266 - ] 267 - `; 268 - 269 - exports[`autocomplete > renders bottom ellipsis when items do not fit 1`] = ` 270 - [ 271 - "<cursor.hide>", 272 - "<dim>│</fg> 273 - <cyan>◆</fg> Select an option 274 - <cyan>│</fg> 275 - <cyan>│</fg> <dim>Search:</bold> _ 276 - <cyan>│</fg> <green>●</fg> Line 0 277 - <cyan>│</fg> Line 1 278 - <cyan>│</fg> Line 2 279 - <cyan>│</fg> Line 3 280 - <cyan>│</fg> <dim>...</bold> 281 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 282 - <cyan>└</fg>", 283 - "<cursor.backward count=999><cursor.up count=10>", 284 - "<erase.down>", 285 - "<green>◇</fg> Select an option 286 - <dim>│</fg> <dim>Line 0 287 - Line 1 288 - Line 2 289 - Line 3</bold>", 290 - " 291 - ", 292 - "<cursor.show>", 293 - ] 294 - `; 295 - 296 - exports[`autocomplete > renders initial UI with message and instructions 1`] = ` 297 - [ 298 - "<cursor.hide>", 299 - "<dim>│</fg> 300 - <cyan>◆</fg> Select a fruit 301 - <cyan>│</fg> 302 - <cyan>│</fg> <dim>Search:</bold> _ 303 - <cyan>│</fg> <green>●</fg> Apple 304 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 305 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 306 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 307 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 308 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 309 - <cyan>└</fg>", 310 - "<cursor.backward count=999><cursor.up count=10>", 311 - "<cursor.down count=1>", 312 - "<erase.down>", 313 - "<green>◇</fg> Select a fruit 314 - <dim>│</fg> <dim>Apple</bold>", 315 - " 316 - ", 317 - "<cursor.show>", 318 - ] 319 - `; 320 - 321 - exports[`autocomplete > renders placeholder if set 1`] = ` 322 - [ 323 - "<cursor.hide>", 324 - "<dim>│</fg> 325 - <cyan>◆</fg> Select a fruit 326 - <cyan>│</fg> 327 - <cyan>│</fg> <dim>Search:</bold> <dim>Type to search...</bold> 328 - <cyan>│</fg> <green>●</fg> Apple 329 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 330 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 331 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 332 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 333 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 334 - <cyan>└</fg>", 335 - "<cursor.backward count=999><cursor.up count=10>", 336 - "<cursor.down count=1>", 337 - "<erase.down>", 338 - "<green>◇</fg> Select a fruit 339 - <dim>│</fg> <dim>Apple</bold>", 340 - " 341 - ", 342 - "<cursor.show>", 343 - ] 344 - `; 345 - 346 - exports[`autocomplete > renders top ellipsis when scrolled down and its do not fit 1`] = ` 347 - [ 348 - "<cursor.hide>", 349 - "<dim>│</fg> 350 - <cyan>◆</fg> Select an option 351 - <cyan>│</fg> 352 - <cyan>│</fg> <dim>Search:</bold> _ 353 - <cyan>│</fg> <dim>...</bold> 354 - <cyan>│</fg> <green>●</fg> Option 2 355 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 356 - <cyan>└</fg>", 357 - "<cursor.backward count=999><cursor.up count=7>", 358 - "<erase.down>", 359 - "<dim>│</fg> 360 - <green>◇</fg> Select an option 361 - <dim>│</fg> <dim>Option 2</bold>", 362 - " 363 - ", 364 - "<cursor.show>", 365 - ] 366 - `; 367 - 368 - exports[`autocomplete > shows hint when option has hint and is focused 1`] = ` 369 - [ 370 - "<cursor.hide>", 371 - "<dim>│</fg> 372 - <cyan>◆</fg> Select a fruit 373 - <cyan>│</fg> 374 - <cyan>│</fg> <dim>Search:</bold> _ 375 - <cyan>│</fg> <green>●</fg> Apple 376 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 377 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 378 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 379 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 380 - <cyan>│</fg> <dim>○</bold> <dim>Kiwi</bold> 381 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 382 - <cyan>└</fg>", 383 - "<cursor.backward count=999><cursor.up count=11>", 384 - "<cursor.down count=3>", 385 - "<erase.down>", 386 - "<cyan>│</fg> <dim>Search:</bold> 387 - <cyan>│</fg> <dim>○</bold> <dim>Apple</bold> 388 - <cyan>│</fg> <green>●</fg> Banana 389 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 390 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 391 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 392 - <cyan>│</fg> <dim>○</bold> <dim>Kiwi</bold> 393 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 394 - <cyan>└</fg>", 395 - "<cursor.backward count=999><cursor.up count=11>", 396 - "<cursor.down count=5>", 397 - "<erase.down>", 398 - "<cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 399 - <cyan>│</fg> <green>●</fg> Cherry 400 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 401 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 402 - <cyan>│</fg> <dim>○</bold> <dim>Kiwi</bold> 403 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 404 - <cyan>└</fg>", 405 - "<cursor.backward count=999><cursor.up count=11>", 406 - "<cursor.down count=6>", 407 - "<erase.down>", 408 - "<cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 409 - <cyan>│</fg> <green>●</fg> Grape 410 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 411 - <cyan>│</fg> <dim>○</bold> <dim>Kiwi</bold> 412 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 413 - <cyan>└</fg>", 414 - "<cursor.backward count=999><cursor.up count=11>", 415 - "<cursor.down count=7>", 416 - "<erase.down>", 417 - "<cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 418 - <cyan>│</fg> <green>●</fg> Orange 419 - <cyan>│</fg> <dim>○</bold> <dim>Kiwi</bold> 420 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 421 - <cyan>└</fg>", 422 - "<cursor.backward count=999><cursor.up count=11>", 423 - "<cursor.down count=8>", 424 - "<erase.down>", 425 - "<cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 426 - <cyan>│</fg> <green>●</fg> Kiwi<dim> (New Zealand)</bold> 427 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 428 - <cyan>└</fg>", 429 - "<cursor.backward count=999><cursor.up count=11>", 430 - "<cursor.down count=1>", 431 - "<erase.down>", 432 - "<green>◇</fg> Select a fruit 433 - <dim>│</fg> <dim>Kiwi</bold>", 434 - " 435 - ", 436 - "<cursor.show>", 437 - ] 438 - `; 439 - 440 - exports[`autocomplete > shows no matches message when search has no results 1`] = ` 441 - [ 442 - "<cursor.hide>", 443 - "<dim>│</fg> 444 - <cyan>◆</fg> Select a fruit 445 - <cyan>│</fg> 446 - <cyan>│</fg> <dim>Search:</bold> _ 447 - <cyan>│</fg> <green>●</fg> Apple 448 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 449 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 450 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 451 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 452 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 453 - <cyan>└</fg>", 454 - "<cursor.backward count=999><cursor.up count=10>", 455 - "<cursor.down count=3>", 456 - "<erase.down>", 457 - "<cyan>│</fg> <dim>Search:</bold> z█<dim> (0 matches)</bold> 458 - <cyan>│</fg> <yellow>No matches found</fg> 459 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 460 - <cyan>└</fg>", 461 - "<cursor.backward count=999><cursor.up count=6>", 462 - "<cursor.down count=1>", 463 - "<erase.down>", 464 - "<green>◇</fg> Select a fruit 465 - <dim>│</fg>", 466 - " 467 - ", 468 - "<cursor.show>", 469 - ] 470 - `; 471 - 472 - exports[`autocomplete > shows selected value in submit state 1`] = ` 473 - [ 474 - "<cursor.hide>", 475 - "<dim>│</fg> 476 - <cyan>◆</fg> Select a fruit 477 - <cyan>│</fg> 478 - <cyan>│</fg> <dim>Search:</bold> _ 479 - <cyan>│</fg> <green>●</fg> Apple 480 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 481 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 482 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 483 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 484 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 485 - <cyan>└</fg>", 486 - "<cursor.backward count=999><cursor.up count=10>", 487 - "<cursor.down count=3>", 488 - "<erase.down>", 489 - "<cyan>│</fg> <dim>Search:</bold> 490 - <cyan>│</fg> <dim>○</bold> <dim>Apple</bold> 491 - <cyan>│</fg> <green>●</fg> Banana 492 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 493 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 494 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 495 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 496 - <cyan>└</fg>", 497 - "<cursor.backward count=999><cursor.up count=10>", 498 - "<cursor.down count=1>", 499 - "<erase.down>", 500 - "<green>◇</fg> Select a fruit 501 - <dim>│</fg> <dim>Banana</bold>", 502 - " 503 - ", 504 - "<cursor.show>", 505 - ] 506 - `; 507 - 508 - exports[`autocomplete > shows strikethrough in cancel state 1`] = ` 509 - [ 510 - "<cursor.hide>", 511 - "<dim>│</fg> 512 - <cyan>◆</fg> Select a fruit 513 - <cyan>│</fg> 514 - <cyan>│</fg> <dim>Search:</bold> _ 515 - <cyan>│</fg> <green>●</fg> Apple 516 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 517 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 518 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 519 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 520 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 521 - <cyan>└</fg>", 522 - "<cursor.backward count=999><cursor.up count=10>", 523 - "<cursor.down count=1>", 524 - "<erase.down>", 525 - "<red>■</fg> Select a fruit 526 - <dim>│</fg>", 527 - " 528 - ", 529 - "<cursor.show>", 530 - ] 531 - `; 532 - 533 - exports[`autocomplete > supports initialValue 1`] = ` 534 - [ 535 - "<cursor.hide>", 536 - "<dim>│</fg> 537 - <cyan>◆</fg> Select a fruit 538 - <cyan>│</fg> 539 - <cyan>│</fg> <dim>Search:</bold> _ 540 - <cyan>│</fg> <dim>○</bold> <dim>Apple</bold> 541 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 542 - <cyan>│</fg> <green>●</fg> Cherry 543 - <cyan>│</fg> <dim>○</bold> <dim>Grape</bold> 544 - <cyan>│</fg> <dim>○</bold> <dim>Orange</bold> 545 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 546 - <cyan>└</fg>", 547 - "<cursor.backward count=999><cursor.up count=10>", 548 - "<cursor.down count=1>", 549 - "<erase.down>", 550 - "<green>◇</fg> Select a fruit 551 - <dim>│</fg> <dim>Cherry</bold>", 552 - " 553 - ", 554 - "<cursor.show>", 555 - ] 556 - `; 557 - 558 - exports[`autocomplete with custom filter > falls back to default filter when not provided 1`] = ` 559 - [ 560 - "<cursor.hide>", 561 - "<dim>│</fg> 562 - <cyan>◆</fg> Select a fruit 563 - <cyan>│</fg> 564 - <cyan>│</fg> <dim>Search:</bold> _ 565 - <cyan>│</fg> <green>●</fg> Apple 566 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 567 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 568 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 569 - <cyan>└</fg>", 570 - "<cursor.backward count=999><cursor.up count=8>", 571 - "<cursor.down count=3>", 572 - "<erase.down>", 573 - "<cyan>│</fg> <dim>Search:</bold> a█<dim> (2 matches)</bold> 574 - <cyan>│</fg> <green>●</fg> Apple 575 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 576 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 577 - <cyan>└</fg>", 578 - "<cursor.backward count=999><cursor.up count=7>", 579 - "<cursor.down count=1>", 580 - "<erase.down>", 581 - "<green>◇</fg> Select a fruit 582 - <dim>│</fg> <dim>Apple</bold>", 583 - " 584 - ", 585 - "<cursor.show>", 586 - ] 587 - `; 588 - 589 - exports[`autocomplete with custom filter > uses custom filter function when provided 1`] = ` 590 - [ 591 - "<cursor.hide>", 592 - "<dim>│</fg> 593 - <cyan>◆</fg> Select a fruit 594 - <cyan>│</fg> 595 - <cyan>│</fg> <dim>Search:</bold> _ 596 - <cyan>│</fg> <green>●</fg> Apple 597 - <cyan>│</fg> <dim>○</bold> <dim>Banana</bold> 598 - <cyan>│</fg> <dim>○</bold> <dim>Cherry</bold> 599 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 600 - <cyan>└</fg>", 601 - "<cursor.backward count=999><cursor.up count=8>", 602 - "<cursor.down count=3>", 603 - "<erase.down>", 604 - "<cyan>│</fg> <dim>Search:</bold> a█<dim> (1 match)</bold> 605 - <cyan>│</fg> <green>●</fg> Apple 606 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 607 - <cyan>└</fg>", 608 - "<cursor.backward count=999><cursor.up count=6>", 609 - "<cursor.down count=1>", 610 - "<erase.down>", 611 - "<green>◇</fg> Select a fruit 612 - <dim>│</fg> <dim>Apple</bold>", 613 - " 614 - ", 615 - "<cursor.show>", 616 - ] 617 - `; 618 - 619 - exports[`autocompleteMultiselect > can be aborted by a signal 1`] = ` 620 - [ 621 - "<cursor.hide>", 622 - "<dim>│</fg> 623 - <cyan>◆</fg> foo 624 - <cyan>│</fg> 625 - <cyan>│</fg> <dim>Search:</bold> _ 626 - <cyan>│</fg> <dim>◻</bold> Apple 627 - <cyan>│</fg> <dim>◻</bold> <dim>Banana</bold> 628 - <cyan>│</fg> <dim>◻</bold> <dim>Cherry</bold> 629 - <cyan>│</fg> <dim>◻</bold> <dim>Grape</bold> 630 - <cyan>│</fg> <dim>◻</bold> <dim>Orange</bold> 631 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 632 - <cyan>└</fg>", 633 - " 634 - ", 635 - "<cursor.show>", 636 - ] 637 - `; 638 - 639 - exports[`autocompleteMultiselect > can use navigation keys to select options 1`] = ` 640 - [ 641 - "<cursor.hide>", 642 - "<dim>│</fg> 643 - <cyan>◆</fg> Select fruits 644 - <cyan>│</fg> 645 - <cyan>│</fg> <dim>Search:</bold> _ 646 - <cyan>│</fg> <dim>◻</bold> Apple 647 - <cyan>│</fg> <dim>◻</bold> <dim>Banana</bold> 648 - <cyan>│</fg> <dim>◻</bold> <dim>Cherry</bold> 649 - <cyan>│</fg> <dim>◻</bold> <dim>Grape</bold> 650 - <cyan>│</fg> <dim>◻</bold> <dim>Orange</bold> 651 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 652 - <cyan>└</fg>", 653 - "<cursor.backward count=999><cursor.up count=10>", 654 - "<cursor.down count=3>", 655 - "<erase.down>", 656 - "<cyan>│</fg> <dim>Search:</bold> <dim></bold> 657 - <cyan>│</fg> <dim>◻</bold> <dim>Apple</bold> 658 - <cyan>│</fg> <dim>◻</bold> Banana 659 - <cyan>│</fg> <dim>◻</bold> <dim>Cherry</bold> 660 - <cyan>│</fg> <dim>◻</bold> <dim>Grape</bold> 661 - <cyan>│</fg> <dim>◻</bold> <dim>Orange</bold> 662 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Space/Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 663 - <cyan>└</fg>", 664 - "<cursor.backward count=999><cursor.up count=10>", 665 - "<cursor.down count=5>", 666 - "<erase.line><cursor.left count=1>", 667 - "<cyan>│</fg> <green>◼</fg> Banana", 668 - "<cursor.down count=5>", 669 - "<cursor.backward count=999><cursor.up count=10>", 670 - "<cursor.down count=5>", 671 - "<erase.down>", 672 - "<cyan>│</fg> <green>◼</fg> <dim>Banana</bold> 673 - <cyan>│</fg> <dim>◻</bold> Cherry 674 - <cyan>│</fg> <dim>◻</bold> <dim>Grape</bold> 675 - <cyan>│</fg> <dim>◻</bold> <dim>Orange</bold> 676 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Space/Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 677 - <cyan>└</fg>", 678 - "<cursor.backward count=999><cursor.up count=10>", 679 - "<cursor.down count=6>", 680 - "<erase.line><cursor.left count=1>", 681 - "<cyan>│</fg> <green>◼</fg> Cherry", 682 - "<cursor.down count=4>", 683 - "<cursor.backward count=999><cursor.up count=10>", 684 - "<cursor.down count=1>", 685 - "<erase.down>", 686 - "<green>◇</fg> Select fruits 687 - <dim>│</fg> <dim>2 items selected</bold>", 688 - " 689 - ", 690 - "<cursor.show>", 691 - ] 692 - `; 693 - 694 - exports[`autocompleteMultiselect > cannot select disabled options when only one left 1`] = ` 695 - [ 696 - "<cursor.hide>", 697 - "<dim>│</fg> 698 - <cyan>◆</fg> Select a fruit 699 - <cyan>│</fg> 700 - <cyan>│</fg> <dim>Search:</bold> _ 701 - <cyan>│</fg> <dim>◻</bold> Apple 702 - <cyan>│</fg> <dim>◻</bold> <dim>Banana</bold> 703 - <cyan>│</fg> <dim>◻</bold> <dim>Cherry</bold> 704 - <cyan>│</fg> <dim>◻</bold> <dim>Grape</bold> 705 - <cyan>│</fg> <dim>◻</bold> <dim>Orange</bold> 706 - <cyan>│</fg> <dim>◻</fg> <dim>Kiwi</fg> 707 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 708 - <cyan>└</fg>", 709 - "<cursor.backward count=999><cursor.up count=11>", 710 - "<cursor.down count=3>", 711 - "<erase.down>", 712 - "<cyan>│</fg> <dim>Search:</bold> k█<dim> (1 match)</bold> 713 - <cyan>│</fg> <dim>◻</fg> <dim>Kiwi</fg> 714 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 715 - <cyan>└</fg>", 716 - "<cursor.backward count=999><cursor.up count=6>", 717 - "<cursor.down count=1>", 718 - "<erase.down>", 719 - "<green>◇</fg> Select a fruit 720 - <dim>│</fg> <dim>0 items selected</bold>", 721 - " 722 - ", 723 - "<cursor.show>", 724 - ] 725 - `; 726 - 727 - exports[`autocompleteMultiselect > displays disabled options correctly 1`] = ` 728 - [ 729 - "<cursor.hide>", 730 - "<dim>│</fg> 731 - <cyan>◆</fg> Select a fruit 732 - <cyan>│</fg> 733 - <cyan>│</fg> <dim>Search:</bold> _ 734 - <cyan>│</fg> <dim>◻</bold> Apple 735 - <cyan>│</fg> <dim>◻</bold> <dim>Banana</bold> 736 - <cyan>│</fg> <dim>◻</bold> <dim>Cherry</bold> 737 - <cyan>│</fg> <dim>◻</bold> <dim>Grape</bold> 738 - <cyan>│</fg> <dim>◻</bold> <dim>Orange</bold> 739 - <cyan>│</fg> <dim>◻</fg> <dim>Kiwi</fg> 740 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 741 - <cyan>└</fg>", 742 - "<cursor.backward count=999><cursor.up count=11>", 743 - "<cursor.down count=3>", 744 - "<erase.down>", 745 - "<cyan>│</fg> <dim>Search:</bold> <dim></bold> 746 - <cyan>│</fg> <dim>◻</bold> <dim>Apple</bold> 747 - <cyan>│</fg> <dim>◻</bold> Banana 748 - <cyan>│</fg> <dim>◻</bold> <dim>Cherry</bold> 749 - <cyan>│</fg> <dim>◻</bold> <dim>Grape</bold> 750 - <cyan>│</fg> <dim>◻</bold> <dim>Orange</bold> 751 - <cyan>│</fg> <dim>◻</fg> <dim>Kiwi</fg> 752 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Space/Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 753 - <cyan>└</fg>", 754 - "<cursor.backward count=999><cursor.up count=11>", 755 - "<cursor.down count=5>", 756 - "<erase.down>", 757 - "<cyan>│</fg> <dim>◻</bold> <dim>Banana</bold> 758 - <cyan>│</fg> <dim>◻</bold> Cherry 759 - <cyan>│</fg> <dim>◻</bold> <dim>Grape</bold> 760 - <cyan>│</fg> <dim>◻</bold> <dim>Orange</bold> 761 - <cyan>│</fg> <dim>◻</fg> <dim>Kiwi</fg> 762 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Space/Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 763 - <cyan>└</fg>", 764 - "<cursor.backward count=999><cursor.up count=11>", 765 - "<cursor.down count=6>", 766 - "<erase.down>", 767 - "<cyan>│</fg> <dim>◻</bold> <dim>Cherry</bold> 768 - <cyan>│</fg> <dim>◻</bold> Grape 769 - <cyan>│</fg> <dim>◻</bold> <dim>Orange</bold> 770 - <cyan>│</fg> <dim>◻</fg> <dim>Kiwi</fg> 771 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Space/Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 772 - <cyan>└</fg>", 773 - "<cursor.backward count=999><cursor.up count=11>", 774 - "<cursor.down count=7>", 775 - "<erase.down>", 776 - "<cyan>│</fg> <dim>◻</bold> <dim>Grape</bold> 777 - <cyan>│</fg> <dim>◻</bold> Orange 778 - <cyan>│</fg> <dim>◻</fg> <dim>Kiwi</fg> 779 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Space/Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 780 - <cyan>└</fg>", 781 - "<cursor.backward count=999><cursor.up count=11>", 782 - "<cursor.down count=4>", 783 - "<erase.down>", 784 - "<cyan>│</fg> <dim>◻</bold> Apple 785 - <cyan>│</fg> <dim>◻</bold> <dim>Banana</bold> 786 - <cyan>│</fg> <dim>◻</bold> <dim>Cherry</bold> 787 - <cyan>│</fg> <dim>◻</bold> <dim>Grape</bold> 788 - <cyan>│</fg> <dim>◻</bold> <dim>Orange</bold> 789 - <cyan>│</fg> <dim>◻</fg> <dim>Kiwi</fg> 790 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Space/Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 791 - <cyan>└</fg>", 792 - "<cursor.backward count=999><cursor.up count=11>", 793 - "<cursor.down count=4>", 794 - "<erase.line><cursor.left count=1>", 795 - "<cyan>│</fg> <green>◼</fg> Apple", 796 - "<cursor.down count=7>", 797 - "<cursor.backward count=999><cursor.up count=11>", 798 - "<cursor.down count=1>", 799 - "<erase.down>", 800 - "<green>◇</fg> Select a fruit 801 - <dim>│</fg> <dim>1 items selected</bold>", 802 - " 803 - ", 804 - "<cursor.show>", 805 - ] 806 - `; 807 - 808 - exports[`autocompleteMultiselect > renders error when empty selection & required is true 1`] = ` 809 - [ 810 - "<cursor.hide>", 811 - "<dim>│</fg> 812 - <cyan>◆</fg> Select a fruit 813 - <cyan>│</fg> 814 - <cyan>│</fg> <dim>Search:</bold> _ 815 - <cyan>│</fg> <dim>◻</bold> Apple 816 - <cyan>│</fg> <dim>◻</bold> <dim>Banana</bold> 817 - <cyan>│</fg> <dim>◻</bold> <dim>Cherry</bold> 818 - <cyan>│</fg> <dim>◻</bold> <dim>Grape</bold> 819 - <cyan>│</fg> <dim>◻</bold> <dim>Orange</bold> 820 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 821 - <cyan>└</fg>", 822 - "<cursor.backward count=999><cursor.up count=10>", 823 - "<cursor.down count=1>", 824 - "<erase.down>", 825 - "<yellow>▲</fg> Select a fruit 826 - <yellow>│</fg> 827 - <yellow>│</fg> <dim>Search:</bold> _ 828 - <yellow>│</fg> <yellow>Please select at least one item</fg> 829 - <yellow>│</fg> <dim>◻</bold> Apple 830 - <yellow>│</fg> <dim>◻</bold> <dim>Banana</bold> 831 - <yellow>│</fg> <dim>◻</bold> <dim>Cherry</bold> 832 - <yellow>│</fg> <dim>◻</bold> <dim>Grape</bold> 833 - <yellow>│</fg> <dim>◻</bold> <dim>Orange</bold> 834 - <yellow>│</fg> <dim>↑/↓</bold> to navigate • <dim>Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 835 - <yellow>└</fg>", 836 - "<cursor.backward count=999><cursor.up count=11>", 837 - "<cursor.down count=1>", 838 - "<erase.down>", 839 - "<cyan>◆</fg> Select a fruit 840 - <cyan>│</fg> 841 - <cyan>│</fg> <dim>Search:</bold> _ 842 - <cyan>│</fg> <green>◼</fg> Apple 843 - <cyan>│</fg> <dim>◻</bold> <dim>Banana</bold> 844 - <cyan>│</fg> <dim>◻</bold> <dim>Cherry</bold> 845 - <cyan>│</fg> <dim>◻</bold> <dim>Grape</bold> 846 - <cyan>│</fg> <dim>◻</bold> <dim>Orange</bold> 847 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 848 - <cyan>└</fg>", 849 - "<cursor.backward count=999><cursor.up count=10>", 850 - "<cursor.down count=1>", 851 - "<erase.down>", 852 - "<green>◇</fg> Select a fruit 853 - <dim>│</fg> <dim>1 items selected</bold>", 854 - " 855 - ", 856 - "<cursor.show>", 857 - ] 858 - `; 859 - 860 - exports[`autocompleteMultiselect > supports custom filter function 1`] = ` 861 - [ 862 - "<cursor.hide>", 863 - "<dim>│</fg> 864 - <cyan>◆</fg> Select fruits 865 - <cyan>│</fg> 866 - <cyan>│</fg> <dim>Search:</bold> _ 867 - <cyan>│</fg> <dim>◻</bold> Apple 868 - <cyan>│</fg> <dim>◻</bold> <dim>Banana</bold> 869 - <cyan>│</fg> <dim>◻</bold> <dim>Cherry</bold> 870 - <cyan>│</fg> <dim>◻</bold> <dim>Grape</bold> 871 - <cyan>│</fg> <dim>◻</bold> <dim>Orange</bold> 872 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 873 - <cyan>└</fg>", 874 - "<cursor.backward count=999><cursor.up count=10>", 875 - "<cursor.down count=3>", 876 - "<erase.down>", 877 - "<cyan>│</fg> <dim>Search:</bold> a█<dim> (1 match)</bold> 878 - <cyan>│</fg> <dim>◻</bold> Apple 879 - <cyan>│</fg> <dim>↑/↓</bold> to navigate • <dim>Tab:</bold> select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 880 - <cyan>└</fg>", 881 - "<cursor.backward count=999><cursor.up count=6>", 882 - "<cursor.down count=4>", 883 - "<erase.line><cursor.left count=1>", 884 - "<cyan>│</fg> <green>◼</fg> Apple", 885 - "<cursor.down count=2>", 886 - "<cursor.backward count=999><cursor.up count=6>", 887 - "<cursor.down count=1>", 888 - "<erase.down>", 889 - "<green>◇</fg> Select fruits 890 - <dim>│</fg> <dim>1 items selected</bold>", 891 - " 892 - ", 893 - "<cursor.show>", 894 - ] 895 - `;
-551
packages/prompts/test/__snapshots__/box.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`box (isCI = false) > cannot have width larger than 100% 1`] = ` 4 - [ 5 - "│ ┌─title──────────────────────────────────────────────────────────────────────┐ 6 - ", 7 - "│ │ message │ 8 - ", 9 - "│ └────────────────────────────────────────────────────────────────────────────┘ 10 - ", 11 - ] 12 - `; 13 - 14 - exports[`box (isCI = false) > renders as specified width 1`] = ` 15 - [ 16 - "│ ┌─title──────────────────────────────┐ 17 - ", 18 - "│ │ short │ 19 - ", 20 - "│ │ somewhat questionably long line │ 21 - ", 22 - "│ └────────────────────────────────────┘ 23 - ", 24 - ] 25 - `; 26 - 27 - exports[`box (isCI = false) > renders as wide as longest line with width: auto 1`] = ` 28 - [ 29 - "│ ┌─title──────────────────────────────┐ 30 - ", 31 - "│ │ short │ 32 - ", 33 - "│ │ somewhat questionably long line │ 34 - ", 35 - "│ └────────────────────────────────────┘ 36 - ", 37 - ] 38 - `; 39 - 40 - exports[`box (isCI = false) > renders auto width with content longer than title 1`] = ` 41 - [ 42 - "│ ┌─title──────────────────────────┐ 43 - ", 44 - "│ │ messagemessagemessagemessage │ 45 - ", 46 - "│ └────────────────────────────────┘ 47 - ", 48 - ] 49 - `; 50 - 51 - exports[`box (isCI = false) > renders auto width with title longer than content 1`] = ` 52 - [ 53 - "│ ┌─titletitletitletitle─┐ 54 - ", 55 - "│ │ message │ 56 - ", 57 - "│ └──────────────────────┘ 58 - ", 59 - ] 60 - `; 61 - 62 - exports[`box (isCI = false) > renders center aligned content 1`] = ` 63 - [ 64 - "│ ┌─title──────┐ 65 - ", 66 - "│ │ message │ 67 - ", 68 - "│ └────────────┘ 69 - ", 70 - ] 71 - `; 72 - 73 - exports[`box (isCI = false) > renders center aligned title 1`] = ` 74 - [ 75 - "│ ┌───title────┐ 76 - ", 77 - "│ │ message │ 78 - ", 79 - "│ └────────────┘ 80 - ", 81 - ] 82 - `; 83 - 84 - exports[`box (isCI = false) > renders left aligned content 1`] = ` 85 - [ 86 - "│ ┌─title──────┐ 87 - ", 88 - "│ │ message │ 89 - ", 90 - "│ └────────────┘ 91 - ", 92 - ] 93 - `; 94 - 95 - exports[`box (isCI = false) > renders left aligned title 1`] = ` 96 - [ 97 - "│ ┌─title──────┐ 98 - ", 99 - "│ │ message │ 100 - ", 101 - "│ └────────────┘ 102 - ", 103 - ] 104 - `; 105 - 106 - exports[`box (isCI = false) > renders message 1`] = ` 107 - [ 108 - "│ ┌────────────────────────────────────────────────────────────────────────────┐ 109 - ", 110 - "│ │ message │ 111 - ", 112 - "│ └────────────────────────────────────────────────────────────────────────────┘ 113 - ", 114 - ] 115 - `; 116 - 117 - exports[`box (isCI = false) > renders message with title 1`] = ` 118 - [ 119 - "│ ┌─some title─────────────────────────────────────────────────────────────────┐ 120 - ", 121 - "│ │ message │ 122 - ", 123 - "│ └────────────────────────────────────────────────────────────────────────────┘ 124 - ", 125 - ] 126 - `; 127 - 128 - exports[`box (isCI = false) > renders right aligned content 1`] = ` 129 - [ 130 - "│ ┌─title──────┐ 131 - ", 132 - "│ │ message │ 133 - ", 134 - "│ └────────────┘ 135 - ", 136 - ] 137 - `; 138 - 139 - exports[`box (isCI = false) > renders right aligned title 1`] = ` 140 - [ 141 - "│ ┌──────title─┐ 142 - ", 143 - "│ │ message │ 144 - ", 145 - "│ └────────────┘ 146 - ", 147 - ] 148 - `; 149 - 150 - exports[`box (isCI = false) > renders rounded corners when rounded is true 1`] = ` 151 - [ 152 - "│ ╭─title──────╮ 153 - ", 154 - "│ │ message │ 155 - ", 156 - "│ ╰────────────╯ 157 - ", 158 - ] 159 - `; 160 - 161 - exports[`box (isCI = false) > renders specified contentPadding 1`] = ` 162 - [ 163 - "│ ┌─title──────────────┐ 164 - ", 165 - "│ │ message │ 166 - ", 167 - "│ └────────────────────┘ 168 - ", 169 - ] 170 - `; 171 - 172 - exports[`box (isCI = false) > renders specified titlePadding 1`] = ` 173 - [ 174 - "│ ┌──────title───────┐ 175 - ", 176 - "│ │ message │ 177 - ", 178 - "│ └──────────────────┘ 179 - ", 180 - ] 181 - `; 182 - 183 - exports[`box (isCI = false) > renders truncated long titles 1`] = ` 184 - [ 185 - "│ ┌─foofoof...─┐ 186 - ", 187 - "│ │ message │ 188 - ", 189 - "│ └────────────┘ 190 - ", 191 - ] 192 - `; 193 - 194 - exports[`box (isCI = false) > renders wide characters with auto width 1`] = ` 195 - [ 196 - "│ ┌─这是标题─────────────────┐ 197 - ", 198 - "│ │ 이게 첫 번째 줄이에요 │ 199 - ", 200 - "│ │ これは次の行です │ 201 - ", 202 - "│ └──────────────────────────┘ 203 - ", 204 - ] 205 - `; 206 - 207 - exports[`box (isCI = false) > renders wide characters with specified width 1`] = ` 208 - [ 209 - "│ ┌─这是标题───┐ 210 - ", 211 - "│ │ 이게 첫 │ 212 - ", 213 - "│ │ 번째 │ 214 - ", 215 - "│ │ 줄이에요 │ 216 - ", 217 - "│ │ これは次 │ 218 - ", 219 - "│ │ の行です │ 220 - ", 221 - "│ └────────────┘ 222 - ", 223 - ] 224 - `; 225 - 226 - exports[`box (isCI = false) > renders with formatBorder formatting 1`] = ` 227 - [ 228 - "│ <red>┌</fg><red>─</fg>title<red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>┐</fg> 229 - ", 230 - "│ <red>│</fg> message <red>│</fg> 231 - ", 232 - "│ <red>└</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>┘</fg> 233 - ", 234 - ] 235 - `; 236 - 237 - exports[`box (isCI = false) > renders without guide when global withGuide is false 1`] = ` 238 - [ 239 - "┌─title──────┐ 240 - ", 241 - "│ message │ 242 - ", 243 - "└────────────┘ 244 - ", 245 - ] 246 - `; 247 - 248 - exports[`box (isCI = false) > renders without guide when withGuide is false 1`] = ` 249 - [ 250 - "┌─title──────┐ 251 - ", 252 - "│ message │ 253 - ", 254 - "└────────────┘ 255 - ", 256 - ] 257 - `; 258 - 259 - exports[`box (isCI = false) > wraps content to fit within specified width 1`] = ` 260 - [ 261 - "│ ┌─title──────────────────────────────┐ 262 - ", 263 - "│ │ foo barfoo barfoo barfoo barfoo │ 264 - ", 265 - "│ │ barfoo barfoo barfoo barfoo │ 266 - ", 267 - "│ │ barfoo barfoo barfoo barfoo │ 268 - ", 269 - "│ │ barfoo barfoo barfoo barfoo │ 270 - ", 271 - "│ │ barfoo barfoo barfoo bar │ 272 - ", 273 - "│ └────────────────────────────────────┘ 274 - ", 275 - ] 276 - `; 277 - 278 - exports[`box (isCI = true) > cannot have width larger than 100% 1`] = ` 279 - [ 280 - "│ ┌─title──────────────────────────────────────────────────────────────────────┐ 281 - ", 282 - "│ │ message │ 283 - ", 284 - "│ └────────────────────────────────────────────────────────────────────────────┘ 285 - ", 286 - ] 287 - `; 288 - 289 - exports[`box (isCI = true) > renders as specified width 1`] = ` 290 - [ 291 - "│ ┌─title──────────────────────────────┐ 292 - ", 293 - "│ │ short │ 294 - ", 295 - "│ │ somewhat questionably long line │ 296 - ", 297 - "│ └────────────────────────────────────┘ 298 - ", 299 - ] 300 - `; 301 - 302 - exports[`box (isCI = true) > renders as wide as longest line with width: auto 1`] = ` 303 - [ 304 - "│ ┌─title──────────────────────────────┐ 305 - ", 306 - "│ │ short │ 307 - ", 308 - "│ │ somewhat questionably long line │ 309 - ", 310 - "│ └────────────────────────────────────┘ 311 - ", 312 - ] 313 - `; 314 - 315 - exports[`box (isCI = true) > renders auto width with content longer than title 1`] = ` 316 - [ 317 - "│ ┌─title──────────────────────────┐ 318 - ", 319 - "│ │ messagemessagemessagemessage │ 320 - ", 321 - "│ └────────────────────────────────┘ 322 - ", 323 - ] 324 - `; 325 - 326 - exports[`box (isCI = true) > renders auto width with title longer than content 1`] = ` 327 - [ 328 - "│ ┌─titletitletitletitle─┐ 329 - ", 330 - "│ │ message │ 331 - ", 332 - "│ └──────────────────────┘ 333 - ", 334 - ] 335 - `; 336 - 337 - exports[`box (isCI = true) > renders center aligned content 1`] = ` 338 - [ 339 - "│ ┌─title──────┐ 340 - ", 341 - "│ │ message │ 342 - ", 343 - "│ └────────────┘ 344 - ", 345 - ] 346 - `; 347 - 348 - exports[`box (isCI = true) > renders center aligned title 1`] = ` 349 - [ 350 - "│ ┌───title────┐ 351 - ", 352 - "│ │ message │ 353 - ", 354 - "│ └────────────┘ 355 - ", 356 - ] 357 - `; 358 - 359 - exports[`box (isCI = true) > renders left aligned content 1`] = ` 360 - [ 361 - "│ ┌─title──────┐ 362 - ", 363 - "│ │ message │ 364 - ", 365 - "│ └────────────┘ 366 - ", 367 - ] 368 - `; 369 - 370 - exports[`box (isCI = true) > renders left aligned title 1`] = ` 371 - [ 372 - "│ ┌─title──────┐ 373 - ", 374 - "│ │ message │ 375 - ", 376 - "│ └────────────┘ 377 - ", 378 - ] 379 - `; 380 - 381 - exports[`box (isCI = true) > renders message 1`] = ` 382 - [ 383 - "│ ┌────────────────────────────────────────────────────────────────────────────┐ 384 - ", 385 - "│ │ message │ 386 - ", 387 - "│ └────────────────────────────────────────────────────────────────────────────┘ 388 - ", 389 - ] 390 - `; 391 - 392 - exports[`box (isCI = true) > renders message with title 1`] = ` 393 - [ 394 - "│ ┌─some title─────────────────────────────────────────────────────────────────┐ 395 - ", 396 - "│ │ message │ 397 - ", 398 - "│ └────────────────────────────────────────────────────────────────────────────┘ 399 - ", 400 - ] 401 - `; 402 - 403 - exports[`box (isCI = true) > renders right aligned content 1`] = ` 404 - [ 405 - "│ ┌─title──────┐ 406 - ", 407 - "│ │ message │ 408 - ", 409 - "│ └────────────┘ 410 - ", 411 - ] 412 - `; 413 - 414 - exports[`box (isCI = true) > renders right aligned title 1`] = ` 415 - [ 416 - "│ ┌──────title─┐ 417 - ", 418 - "│ │ message │ 419 - ", 420 - "│ └────────────┘ 421 - ", 422 - ] 423 - `; 424 - 425 - exports[`box (isCI = true) > renders rounded corners when rounded is true 1`] = ` 426 - [ 427 - "│ ╭─title──────╮ 428 - ", 429 - "│ │ message │ 430 - ", 431 - "│ ╰────────────╯ 432 - ", 433 - ] 434 - `; 435 - 436 - exports[`box (isCI = true) > renders specified contentPadding 1`] = ` 437 - [ 438 - "│ ┌─title──────────────┐ 439 - ", 440 - "│ │ message │ 441 - ", 442 - "│ └────────────────────┘ 443 - ", 444 - ] 445 - `; 446 - 447 - exports[`box (isCI = true) > renders specified titlePadding 1`] = ` 448 - [ 449 - "│ ┌──────title───────┐ 450 - ", 451 - "│ │ message │ 452 - ", 453 - "│ └──────────────────┘ 454 - ", 455 - ] 456 - `; 457 - 458 - exports[`box (isCI = true) > renders truncated long titles 1`] = ` 459 - [ 460 - "│ ┌─foofoof...─┐ 461 - ", 462 - "│ │ message │ 463 - ", 464 - "│ └────────────┘ 465 - ", 466 - ] 467 - `; 468 - 469 - exports[`box (isCI = true) > renders wide characters with auto width 1`] = ` 470 - [ 471 - "│ ┌─这是标题─────────────────┐ 472 - ", 473 - "│ │ 이게 첫 번째 줄이에요 │ 474 - ", 475 - "│ │ これは次の行です │ 476 - ", 477 - "│ └──────────────────────────┘ 478 - ", 479 - ] 480 - `; 481 - 482 - exports[`box (isCI = true) > renders wide characters with specified width 1`] = ` 483 - [ 484 - "│ ┌─这是标题───┐ 485 - ", 486 - "│ │ 이게 첫 │ 487 - ", 488 - "│ │ 번째 │ 489 - ", 490 - "│ │ 줄이에요 │ 491 - ", 492 - "│ │ これは次 │ 493 - ", 494 - "│ │ の行です │ 495 - ", 496 - "│ └────────────┘ 497 - ", 498 - ] 499 - `; 500 - 501 - exports[`box (isCI = true) > renders with formatBorder formatting 1`] = ` 502 - [ 503 - "│ <red>┌</fg><red>─</fg>title<red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>┐</fg> 504 - ", 505 - "│ <red>│</fg> message <red>│</fg> 506 - ", 507 - "│ <red>└</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>─</fg><red>┘</fg> 508 - ", 509 - ] 510 - `; 511 - 512 - exports[`box (isCI = true) > renders without guide when global withGuide is false 1`] = ` 513 - [ 514 - "┌─title──────┐ 515 - ", 516 - "│ message │ 517 - ", 518 - "└────────────┘ 519 - ", 520 - ] 521 - `; 522 - 523 - exports[`box (isCI = true) > renders without guide when withGuide is false 1`] = ` 524 - [ 525 - "┌─title──────┐ 526 - ", 527 - "│ message │ 528 - ", 529 - "└────────────┘ 530 - ", 531 - ] 532 - `; 533 - 534 - exports[`box (isCI = true) > wraps content to fit within specified width 1`] = ` 535 - [ 536 - "│ ┌─title──────────────────────────────┐ 537 - ", 538 - "│ │ foo barfoo barfoo barfoo barfoo │ 539 - ", 540 - "│ │ barfoo barfoo barfoo barfoo │ 541 - ", 542 - "│ │ barfoo barfoo barfoo barfoo │ 543 - ", 544 - "│ │ barfoo barfoo barfoo barfoo │ 545 - ", 546 - "│ │ barfoo barfoo barfoo bar │ 547 - ", 548 - "│ └────────────────────────────────────┘ 549 - ", 550 - ] 551 - `;
-481
packages/prompts/test/__snapshots__/confirm.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`confirm (isCI = false) > can be aborted by a signal 1`] = ` 4 - [ 5 - "<cursor.hide>", 6 - "<dim>│</fg> 7 - <cyan>◆</fg> yes? 8 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 9 - <cyan>└</fg> 10 - ", 11 - " 12 - ", 13 - "<cursor.show>", 14 - ] 15 - `; 16 - 17 - exports[`confirm (isCI = false) > can cancel 1`] = ` 18 - [ 19 - "<cursor.hide>", 20 - "<dim>│</fg> 21 - <cyan>◆</fg> foo 22 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 23 - <cyan>└</fg> 24 - ", 25 - "<cursor.backward count=999><cursor.up count=4>", 26 - "<cursor.down count=1>", 27 - "<erase.down>", 28 - "<red>■</fg> foo 29 - <dim>│</fg> <dim>No</bold> 30 - <dim>│</fg>", 31 - " 32 - ", 33 - "<cursor.show>", 34 - ] 35 - `; 36 - 37 - exports[`confirm (isCI = false) > can set initialValue 1`] = ` 38 - [ 39 - "<cursor.hide>", 40 - "<dim>│</fg> 41 - <cyan>◆</fg> foo 42 - <cyan>│</fg> <dim>○</bold> <dim>Yes</bold> <dim>/</bold> <green>●</fg> No 43 - <cyan>└</fg> 44 - ", 45 - "<cursor.backward count=999><cursor.up count=4>", 46 - "<cursor.down count=1>", 47 - "<erase.down>", 48 - "<green>◇</fg> foo 49 - <dim>│</fg> <dim>No</bold>", 50 - " 51 - ", 52 - "<cursor.show>", 53 - ] 54 - `; 55 - 56 - exports[`confirm (isCI = false) > global withGuide: false removes guide 1`] = ` 57 - [ 58 - "<cursor.hide>", 59 - "<cyan>◆</fg> foo 60 - <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 61 - 62 - ", 63 - "<cursor.backward count=999><cursor.up count=3>", 64 - "<erase.down>", 65 - "<green>◇</fg> foo 66 - <dim>Yes</bold>", 67 - " 68 - ", 69 - "<cursor.show>", 70 - ] 71 - `; 72 - 73 - exports[`confirm (isCI = false) > left arrow moves to previous choice 1`] = ` 74 - [ 75 - "<cursor.hide>", 76 - "<dim>│</fg> 77 - <cyan>◆</fg> foo 78 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 79 - <cyan>└</fg> 80 - ", 81 - "<cursor.backward count=999><cursor.up count=4>", 82 - "<cursor.down count=2>", 83 - "<erase.line><cursor.left count=1>", 84 - "<cyan>│</fg> <dim>○</bold> <dim>Yes</bold> <dim>/</bold> <green>●</fg> No", 85 - "<cursor.down count=2>", 86 - "<cursor.backward count=999><cursor.up count=4>", 87 - "<cursor.down count=2>", 88 - "<erase.line><cursor.left count=1>", 89 - "<cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold>", 90 - "<cursor.down count=2>", 91 - "<cursor.backward count=999><cursor.up count=4>", 92 - "<cursor.down count=1>", 93 - "<erase.down>", 94 - "<green>◇</fg> foo 95 - <dim>│</fg> <dim>Yes</bold>", 96 - " 97 - ", 98 - "<cursor.show>", 99 - ] 100 - `; 101 - 102 - exports[`confirm (isCI = false) > renders custom active choice 1`] = ` 103 - [ 104 - "<cursor.hide>", 105 - "<dim>│</fg> 106 - <cyan>◆</fg> foo 107 - <cyan>│</fg> <green>●</fg> bleep <dim>/</bold> <dim>○</bold> <dim>No</bold> 108 - <cyan>└</fg> 109 - ", 110 - "<cursor.backward count=999><cursor.up count=4>", 111 - "<cursor.down count=1>", 112 - "<erase.down>", 113 - "<green>◇</fg> foo 114 - <dim>│</fg> <dim>bleep</bold>", 115 - " 116 - ", 117 - "<cursor.show>", 118 - ] 119 - `; 120 - 121 - exports[`confirm (isCI = false) > renders custom inactive choice 1`] = ` 122 - [ 123 - "<cursor.hide>", 124 - "<dim>│</fg> 125 - <cyan>◆</fg> foo 126 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>bleep</bold> 127 - <cyan>└</fg> 128 - ", 129 - "<cursor.backward count=999><cursor.up count=4>", 130 - "<cursor.down count=1>", 131 - "<erase.down>", 132 - "<green>◇</fg> foo 133 - <dim>│</fg> <dim>Yes</bold>", 134 - " 135 - ", 136 - "<cursor.show>", 137 - ] 138 - `; 139 - 140 - exports[`confirm (isCI = false) > renders message with choices 1`] = ` 141 - [ 142 - "<cursor.hide>", 143 - "<dim>│</fg> 144 - <cyan>◆</fg> foo 145 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 146 - <cyan>└</fg> 147 - ", 148 - "<cursor.backward count=999><cursor.up count=4>", 149 - "<cursor.down count=1>", 150 - "<erase.down>", 151 - "<green>◇</fg> foo 152 - <dim>│</fg> <dim>Yes</bold>", 153 - " 154 - ", 155 - "<cursor.show>", 156 - ] 157 - `; 158 - 159 - exports[`confirm (isCI = false) > renders multi-line messages correctly 1`] = ` 160 - [ 161 - "<cursor.hide>", 162 - "<dim>│</fg> 163 - <cyan>◆</fg> foo 164 - <dim>│</fg> bar 165 - <dim>│</fg> baz 166 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 167 - <cyan>└</fg> 168 - ", 169 - "<cursor.backward count=999><cursor.up count=6>", 170 - "<cursor.down count=1>", 171 - "<erase.down>", 172 - "<green>◇</fg> foo 173 - <dim>│</fg> bar 174 - <dim>│</fg> baz 175 - <dim>│</fg> <dim>Yes</bold>", 176 - " 177 - ", 178 - "<cursor.show>", 179 - ] 180 - `; 181 - 182 - exports[`confirm (isCI = false) > renders options in vertical alignment 1`] = ` 183 - [ 184 - "<cursor.hide>", 185 - "<dim>│</fg> 186 - <cyan>◆</fg> foo 187 - <cyan>│</fg> <green>●</fg> Yes 188 - <cyan>│</fg> <dim>○</bold> <dim>No</bold> 189 - <cyan>└</fg> 190 - ", 191 - "<cursor.backward count=999><cursor.up count=5>", 192 - "<cursor.down count=1>", 193 - "<erase.down>", 194 - "<green>◇</fg> foo 195 - <dim>│</fg> <dim>Yes</bold>", 196 - " 197 - ", 198 - "<cursor.show>", 199 - ] 200 - `; 201 - 202 - exports[`confirm (isCI = false) > right arrow moves to next choice 1`] = ` 203 - [ 204 - "<cursor.hide>", 205 - "<dim>│</fg> 206 - <cyan>◆</fg> foo 207 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 208 - <cyan>└</fg> 209 - ", 210 - "<cursor.backward count=999><cursor.up count=4>", 211 - "<cursor.down count=2>", 212 - "<erase.line><cursor.left count=1>", 213 - "<cyan>│</fg> <dim>○</bold> <dim>Yes</bold> <dim>/</bold> <green>●</fg> No", 214 - "<cursor.down count=2>", 215 - "<cursor.backward count=999><cursor.up count=4>", 216 - "<cursor.down count=1>", 217 - "<erase.down>", 218 - "<green>◇</fg> foo 219 - <dim>│</fg> <dim>No</bold>", 220 - " 221 - ", 222 - "<cursor.show>", 223 - ] 224 - `; 225 - 226 - exports[`confirm (isCI = false) > withGuide: false removes guide 1`] = ` 227 - [ 228 - "<cursor.hide>", 229 - "<cyan>◆</fg> foo 230 - <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 231 - 232 - ", 233 - "<cursor.backward count=999><cursor.up count=3>", 234 - "<erase.down>", 235 - "<green>◇</fg> foo 236 - <dim>Yes</bold>", 237 - " 238 - ", 239 - "<cursor.show>", 240 - ] 241 - `; 242 - 243 - exports[`confirm (isCI = true) > can be aborted by a signal 1`] = ` 244 - [ 245 - "<cursor.hide>", 246 - "<dim>│</fg> 247 - <cyan>◆</fg> yes? 248 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 249 - <cyan>└</fg> 250 - ", 251 - " 252 - ", 253 - "<cursor.show>", 254 - ] 255 - `; 256 - 257 - exports[`confirm (isCI = true) > can cancel 1`] = ` 258 - [ 259 - "<cursor.hide>", 260 - "<dim>│</fg> 261 - <cyan>◆</fg> foo 262 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 263 - <cyan>└</fg> 264 - ", 265 - "<cursor.backward count=999><cursor.up count=4>", 266 - "<cursor.down count=1>", 267 - "<erase.down>", 268 - "<red>■</fg> foo 269 - <dim>│</fg> <dim>No</bold> 270 - <dim>│</fg>", 271 - " 272 - ", 273 - "<cursor.show>", 274 - ] 275 - `; 276 - 277 - exports[`confirm (isCI = true) > can set initialValue 1`] = ` 278 - [ 279 - "<cursor.hide>", 280 - "<dim>│</fg> 281 - <cyan>◆</fg> foo 282 - <cyan>│</fg> <dim>○</bold> <dim>Yes</bold> <dim>/</bold> <green>●</fg> No 283 - <cyan>└</fg> 284 - ", 285 - "<cursor.backward count=999><cursor.up count=4>", 286 - "<cursor.down count=1>", 287 - "<erase.down>", 288 - "<green>◇</fg> foo 289 - <dim>│</fg> <dim>No</bold>", 290 - " 291 - ", 292 - "<cursor.show>", 293 - ] 294 - `; 295 - 296 - exports[`confirm (isCI = true) > global withGuide: false removes guide 1`] = ` 297 - [ 298 - "<cursor.hide>", 299 - "<cyan>◆</fg> foo 300 - <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 301 - 302 - ", 303 - "<cursor.backward count=999><cursor.up count=3>", 304 - "<erase.down>", 305 - "<green>◇</fg> foo 306 - <dim>Yes</bold>", 307 - " 308 - ", 309 - "<cursor.show>", 310 - ] 311 - `; 312 - 313 - exports[`confirm (isCI = true) > left arrow moves to previous choice 1`] = ` 314 - [ 315 - "<cursor.hide>", 316 - "<dim>│</fg> 317 - <cyan>◆</fg> foo 318 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 319 - <cyan>└</fg> 320 - ", 321 - "<cursor.backward count=999><cursor.up count=4>", 322 - "<cursor.down count=2>", 323 - "<erase.line><cursor.left count=1>", 324 - "<cyan>│</fg> <dim>○</bold> <dim>Yes</bold> <dim>/</bold> <green>●</fg> No", 325 - "<cursor.down count=2>", 326 - "<cursor.backward count=999><cursor.up count=4>", 327 - "<cursor.down count=2>", 328 - "<erase.line><cursor.left count=1>", 329 - "<cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold>", 330 - "<cursor.down count=2>", 331 - "<cursor.backward count=999><cursor.up count=4>", 332 - "<cursor.down count=1>", 333 - "<erase.down>", 334 - "<green>◇</fg> foo 335 - <dim>│</fg> <dim>Yes</bold>", 336 - " 337 - ", 338 - "<cursor.show>", 339 - ] 340 - `; 341 - 342 - exports[`confirm (isCI = true) > renders custom active choice 1`] = ` 343 - [ 344 - "<cursor.hide>", 345 - "<dim>│</fg> 346 - <cyan>◆</fg> foo 347 - <cyan>│</fg> <green>●</fg> bleep <dim>/</bold> <dim>○</bold> <dim>No</bold> 348 - <cyan>└</fg> 349 - ", 350 - "<cursor.backward count=999><cursor.up count=4>", 351 - "<cursor.down count=1>", 352 - "<erase.down>", 353 - "<green>◇</fg> foo 354 - <dim>│</fg> <dim>bleep</bold>", 355 - " 356 - ", 357 - "<cursor.show>", 358 - ] 359 - `; 360 - 361 - exports[`confirm (isCI = true) > renders custom inactive choice 1`] = ` 362 - [ 363 - "<cursor.hide>", 364 - "<dim>│</fg> 365 - <cyan>◆</fg> foo 366 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>bleep</bold> 367 - <cyan>└</fg> 368 - ", 369 - "<cursor.backward count=999><cursor.up count=4>", 370 - "<cursor.down count=1>", 371 - "<erase.down>", 372 - "<green>◇</fg> foo 373 - <dim>│</fg> <dim>Yes</bold>", 374 - " 375 - ", 376 - "<cursor.show>", 377 - ] 378 - `; 379 - 380 - exports[`confirm (isCI = true) > renders message with choices 1`] = ` 381 - [ 382 - "<cursor.hide>", 383 - "<dim>│</fg> 384 - <cyan>◆</fg> foo 385 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 386 - <cyan>└</fg> 387 - ", 388 - "<cursor.backward count=999><cursor.up count=4>", 389 - "<cursor.down count=1>", 390 - "<erase.down>", 391 - "<green>◇</fg> foo 392 - <dim>│</fg> <dim>Yes</bold>", 393 - " 394 - ", 395 - "<cursor.show>", 396 - ] 397 - `; 398 - 399 - exports[`confirm (isCI = true) > renders multi-line messages correctly 1`] = ` 400 - [ 401 - "<cursor.hide>", 402 - "<dim>│</fg> 403 - <cyan>◆</fg> foo 404 - <dim>│</fg> bar 405 - <dim>│</fg> baz 406 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 407 - <cyan>└</fg> 408 - ", 409 - "<cursor.backward count=999><cursor.up count=6>", 410 - "<cursor.down count=1>", 411 - "<erase.down>", 412 - "<green>◇</fg> foo 413 - <dim>│</fg> bar 414 - <dim>│</fg> baz 415 - <dim>│</fg> <dim>Yes</bold>", 416 - " 417 - ", 418 - "<cursor.show>", 419 - ] 420 - `; 421 - 422 - exports[`confirm (isCI = true) > renders options in vertical alignment 1`] = ` 423 - [ 424 - "<cursor.hide>", 425 - "<dim>│</fg> 426 - <cyan>◆</fg> foo 427 - <cyan>│</fg> <green>●</fg> Yes 428 - <cyan>│</fg> <dim>○</bold> <dim>No</bold> 429 - <cyan>└</fg> 430 - ", 431 - "<cursor.backward count=999><cursor.up count=5>", 432 - "<cursor.down count=1>", 433 - "<erase.down>", 434 - "<green>◇</fg> foo 435 - <dim>│</fg> <dim>Yes</bold>", 436 - " 437 - ", 438 - "<cursor.show>", 439 - ] 440 - `; 441 - 442 - exports[`confirm (isCI = true) > right arrow moves to next choice 1`] = ` 443 - [ 444 - "<cursor.hide>", 445 - "<dim>│</fg> 446 - <cyan>◆</fg> foo 447 - <cyan>│</fg> <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 448 - <cyan>└</fg> 449 - ", 450 - "<cursor.backward count=999><cursor.up count=4>", 451 - "<cursor.down count=2>", 452 - "<erase.line><cursor.left count=1>", 453 - "<cyan>│</fg> <dim>○</bold> <dim>Yes</bold> <dim>/</bold> <green>●</fg> No", 454 - "<cursor.down count=2>", 455 - "<cursor.backward count=999><cursor.up count=4>", 456 - "<cursor.down count=1>", 457 - "<erase.down>", 458 - "<green>◇</fg> foo 459 - <dim>│</fg> <dim>No</bold>", 460 - " 461 - ", 462 - "<cursor.show>", 463 - ] 464 - `; 465 - 466 - exports[`confirm (isCI = true) > withGuide: false removes guide 1`] = ` 467 - [ 468 - "<cursor.hide>", 469 - "<cyan>◆</fg> foo 470 - <green>●</fg> Yes <dim>/</bold> <dim>○</bold> <dim>No</bold> 471 - 472 - ", 473 - "<cursor.backward count=999><cursor.up count=3>", 474 - "<erase.down>", 475 - "<green>◇</fg> foo 476 - <dim>Yes</bold>", 477 - " 478 - ", 479 - "<cursor.show>", 480 - ] 481 - `;
-263
packages/prompts/test/__snapshots__/date.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`date (isCI = false) > can cancel 1`] = ` 4 - [ 5 - "<cursor.hide>", 6 - "<dim>│</fg> 7 - <cyan>◆</fg> Pick a date 8 - <cyan>│</fg> mm<dim>/</fg><dim>dd</bold><dim>/</fg><dim>yyyy</bold> 9 - <cyan>└</fg> 10 - ", 11 - "<cursor.backward count=999><cursor.up count=4>", 12 - "<cursor.down count=1>", 13 - "<erase.down>", 14 - "<red>■</fg> Pick a date 15 - <dim>│</fg>", 16 - " 17 - ", 18 - "<cursor.show>", 19 - ] 20 - `; 21 - 22 - exports[`date (isCI = false) > defaultValue used when empty submit 1`] = ` 23 - [ 24 - "<cursor.hide>", 25 - "<dim>│</fg> 26 - <cyan>◆</fg> Pick a date 27 - <cyan>│</fg> 12<dim>/</fg>25<dim>/</fg>2025 28 - <cyan>└</fg> 29 - ", 30 - "<cursor.backward count=999><cursor.up count=4>", 31 - "<cursor.down count=1>", 32 - "<erase.down>", 33 - "<green>◇</fg> Pick a date 34 - <dim>│</fg> <dim>12/25/2025</bold>", 35 - " 36 - ", 37 - "<cursor.show>", 38 - ] 39 - `; 40 - 41 - exports[`date (isCI = false) > renders initial value 1`] = ` 42 - [ 43 - "<cursor.hide>", 44 - "<dim>│</fg> 45 - <cyan>◆</fg> Pick a date 46 - <cyan>│</fg> 01<dim>/</fg>15<dim>/</fg>2025 47 - <cyan>└</fg> 48 - ", 49 - "<cursor.backward count=999><cursor.up count=4>", 50 - "<cursor.down count=1>", 51 - "<erase.down>", 52 - "<green>◇</fg> Pick a date 53 - <dim>│</fg> <dim>01/15/2025</bold>", 54 - " 55 - ", 56 - "<cursor.show>", 57 - ] 58 - `; 59 - 60 - exports[`date (isCI = false) > renders message 1`] = ` 61 - [ 62 - "<cursor.hide>", 63 - "<dim>│</fg> 64 - <cyan>◆</fg> Pick a date 65 - <cyan>│</fg> 01<dim>/</fg>15<dim>/</fg>2025 66 - <cyan>└</fg> 67 - ", 68 - "<cursor.backward count=999><cursor.up count=4>", 69 - "<cursor.down count=1>", 70 - "<erase.down>", 71 - "<green>◇</fg> Pick a date 72 - <dim>│</fg> <dim>01/15/2025</bold>", 73 - " 74 - ", 75 - "<cursor.show>", 76 - ] 77 - `; 78 - 79 - exports[`date (isCI = false) > renders submitted value 1`] = ` 80 - [ 81 - "<cursor.hide>", 82 - "<dim>│</fg> 83 - <cyan>◆</fg> Pick a date 84 - <cyan>│</fg> 06<dim>/</fg>15<dim>/</fg>2025 85 - <cyan>└</fg> 86 - ", 87 - "<cursor.backward count=999><cursor.up count=4>", 88 - "<cursor.down count=1>", 89 - "<erase.down>", 90 - "<green>◇</fg> Pick a date 91 - <dim>│</fg> <dim>06/15/2025</bold>", 92 - " 93 - ", 94 - "<cursor.show>", 95 - ] 96 - `; 97 - 98 - exports[`date (isCI = false) > supports MDY format 1`] = ` 99 - [ 100 - "<cursor.hide>", 101 - "<dim>│</fg> 102 - <cyan>◆</fg> Pick a date 103 - <cyan>│</fg> 01<dim>/</fg>15<dim>/</fg>2025 104 - <cyan>└</fg> 105 - ", 106 - "<cursor.backward count=999><cursor.up count=4>", 107 - "<cursor.down count=1>", 108 - "<erase.down>", 109 - "<green>◇</fg> Pick a date 110 - <dim>│</fg> <dim>01/15/2025</bold>", 111 - " 112 - ", 113 - "<cursor.show>", 114 - ] 115 - `; 116 - 117 - exports[`date (isCI = false) > withGuide: false removes guide 1`] = ` 118 - [ 119 - "<cursor.hide>", 120 - "<cyan>◆</fg> Pick a date 121 - 01<dim>/</fg>15<dim>/</fg>2025 122 - 123 - ", 124 - "<cursor.backward count=999><cursor.up count=3>", 125 - "<erase.down>", 126 - "<green>◇</fg> Pick a date 127 - <dim>01/15/2025</bold>", 128 - " 129 - ", 130 - "<cursor.show>", 131 - ] 132 - `; 133 - 134 - exports[`date (isCI = true) > can cancel 1`] = ` 135 - [ 136 - "<cursor.hide>", 137 - "<dim>│</fg> 138 - <cyan>◆</fg> Pick a date 139 - <cyan>│</fg> mm<dim>/</fg><dim>dd</bold><dim>/</fg><dim>yyyy</bold> 140 - <cyan>└</fg> 141 - ", 142 - "<cursor.backward count=999><cursor.up count=4>", 143 - "<cursor.down count=1>", 144 - "<erase.down>", 145 - "<red>■</fg> Pick a date 146 - <dim>│</fg>", 147 - " 148 - ", 149 - "<cursor.show>", 150 - ] 151 - `; 152 - 153 - exports[`date (isCI = true) > defaultValue used when empty submit 1`] = ` 154 - [ 155 - "<cursor.hide>", 156 - "<dim>│</fg> 157 - <cyan>◆</fg> Pick a date 158 - <cyan>│</fg> 12<dim>/</fg>25<dim>/</fg>2025 159 - <cyan>└</fg> 160 - ", 161 - "<cursor.backward count=999><cursor.up count=4>", 162 - "<cursor.down count=1>", 163 - "<erase.down>", 164 - "<green>◇</fg> Pick a date 165 - <dim>│</fg> <dim>12/25/2025</bold>", 166 - " 167 - ", 168 - "<cursor.show>", 169 - ] 170 - `; 171 - 172 - exports[`date (isCI = true) > renders initial value 1`] = ` 173 - [ 174 - "<cursor.hide>", 175 - "<dim>│</fg> 176 - <cyan>◆</fg> Pick a date 177 - <cyan>│</fg> 01<dim>/</fg>15<dim>/</fg>2025 178 - <cyan>└</fg> 179 - ", 180 - "<cursor.backward count=999><cursor.up count=4>", 181 - "<cursor.down count=1>", 182 - "<erase.down>", 183 - "<green>◇</fg> Pick a date 184 - <dim>│</fg> <dim>01/15/2025</bold>", 185 - " 186 - ", 187 - "<cursor.show>", 188 - ] 189 - `; 190 - 191 - exports[`date (isCI = true) > renders message 1`] = ` 192 - [ 193 - "<cursor.hide>", 194 - "<dim>│</fg> 195 - <cyan>◆</fg> Pick a date 196 - <cyan>│</fg> 01<dim>/</fg>15<dim>/</fg>2025 197 - <cyan>└</fg> 198 - ", 199 - "<cursor.backward count=999><cursor.up count=4>", 200 - "<cursor.down count=1>", 201 - "<erase.down>", 202 - "<green>◇</fg> Pick a date 203 - <dim>│</fg> <dim>01/15/2025</bold>", 204 - " 205 - ", 206 - "<cursor.show>", 207 - ] 208 - `; 209 - 210 - exports[`date (isCI = true) > renders submitted value 1`] = ` 211 - [ 212 - "<cursor.hide>", 213 - "<dim>│</fg> 214 - <cyan>◆</fg> Pick a date 215 - <cyan>│</fg> 06<dim>/</fg>15<dim>/</fg>2025 216 - <cyan>└</fg> 217 - ", 218 - "<cursor.backward count=999><cursor.up count=4>", 219 - "<cursor.down count=1>", 220 - "<erase.down>", 221 - "<green>◇</fg> Pick a date 222 - <dim>│</fg> <dim>06/15/2025</bold>", 223 - " 224 - ", 225 - "<cursor.show>", 226 - ] 227 - `; 228 - 229 - exports[`date (isCI = true) > supports MDY format 1`] = ` 230 - [ 231 - "<cursor.hide>", 232 - "<dim>│</fg> 233 - <cyan>◆</fg> Pick a date 234 - <cyan>│</fg> 01<dim>/</fg>15<dim>/</fg>2025 235 - <cyan>└</fg> 236 - ", 237 - "<cursor.backward count=999><cursor.up count=4>", 238 - "<cursor.down count=1>", 239 - "<erase.down>", 240 - "<green>◇</fg> Pick a date 241 - <dim>│</fg> <dim>01/15/2025</bold>", 242 - " 243 - ", 244 - "<cursor.show>", 245 - ] 246 - `; 247 - 248 - exports[`date (isCI = true) > withGuide: false removes guide 1`] = ` 249 - [ 250 - "<cursor.hide>", 251 - "<cyan>◆</fg> Pick a date 252 - 01<dim>/</fg>15<dim>/</fg>2025 253 - 254 - ", 255 - "<cursor.backward count=999><cursor.up count=3>", 256 - "<erase.down>", 257 - "<green>◇</fg> Pick a date 258 - <dim>01/15/2025</bold>", 259 - " 260 - ", 261 - "<cursor.show>", 262 - ] 263 - `;
-1205
packages/prompts/test/__snapshots__/group-multi-select.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`groupMultiselect (isCI = false) > can be aborted by a signal 1`] = ` 4 - [ 5 - "<cursor.hide>", 6 - "<dim>│</fg> 7 - <cyan>◆</fg> Select a fruit 8 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 9 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value0</bold> 10 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 11 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 12 - <cyan>└</fg> 13 - ", 14 - " 15 - ", 16 - "<cursor.show>", 17 - ] 18 - `; 19 - 20 - exports[`groupMultiselect (isCI = false) > can deselect an option 1`] = ` 21 - [ 22 - "<cursor.hide>", 23 - "<dim>│</fg> 24 - <cyan>◆</fg> foo 25 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 26 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 27 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 28 - <cyan>└</fg> 29 - ", 30 - "<cursor.backward count=999><cursor.up count=6>", 31 - "<cursor.down count=2>", 32 - "<erase.down>", 33 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 34 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> group1value0 35 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group1value1</bold> 36 - <cyan>└</fg> 37 - ", 38 - "<cursor.backward count=999><cursor.up count=6>", 39 - "<cursor.down count=3>", 40 - "<erase.line><cursor.left count=1>", 41 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> group1value0", 42 - "<cursor.down count=3>", 43 - "<cursor.backward count=999><cursor.up count=6>", 44 - "<cursor.down count=3>", 45 - "<erase.down>", 46 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> <dim>group1value0</bold> 47 - <cyan>│</fg> <dim>└ </bold><cyan>◻</fg> group1value1 48 - <cyan>└</fg> 49 - ", 50 - "<cursor.backward count=999><cursor.up count=6>", 51 - "<cursor.down count=2>", 52 - "<erase.down>", 53 - "<cyan>│</fg> <dim></bold><green>◼</fg> <dim>group1</bold> 54 - <cyan>│</fg> <dim>│ </bold><green>◼</fg> <dim>group1value0</bold> 55 - <cyan>│</fg> <dim>└ </bold><green>◼</fg> group1value1 56 - <cyan>└</fg> 57 - ", 58 - "<cursor.backward count=999><cursor.up count=6>", 59 - "<cursor.down count=2>", 60 - "<erase.down>", 61 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 62 - <cyan>│</fg> <dim>│ </bold><green>◼</fg> <dim>group1value0</bold> 63 - <cyan>│</fg> <dim>└ </bold><cyan>◻</fg> group1value1 64 - <cyan>└</fg> 65 - ", 66 - "<cursor.backward count=999><cursor.up count=6>", 67 - "<cursor.down count=1>", 68 - "<erase.down>", 69 - "<green>◇</fg> foo 70 - <dim>│</fg> <dim>group1value0</bold>", 71 - " 72 - ", 73 - "<cursor.show>", 74 - ] 75 - `; 76 - 77 - exports[`groupMultiselect (isCI = false) > can select a group 1`] = ` 78 - [ 79 - "<cursor.hide>", 80 - "<dim>│</fg> 81 - <cyan>◆</fg> foo 82 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 83 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 84 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 85 - <cyan>└</fg> 86 - ", 87 - "<cursor.backward count=999><cursor.up count=6>", 88 - "<cursor.down count=2>", 89 - "<erase.down>", 90 - "<cyan>│</fg> <dim></bold><green>◼</fg> group1 91 - <cyan>│</fg> │ <green>◼</fg> <dim>group1value0</bold> 92 - <cyan>│</fg> └ <green>◼</fg> <dim>group1value1</bold> 93 - <cyan>└</fg> 94 - ", 95 - "<cursor.backward count=999><cursor.up count=6>", 96 - "<cursor.down count=1>", 97 - "<erase.down>", 98 - "<green>◇</fg> foo 99 - <dim>│</fg> <dim>group1value0</bold><dim>, </bold><dim>group1value1</bold>", 100 - " 101 - ", 102 - "<cursor.show>", 103 - ] 104 - `; 105 - 106 - exports[`groupMultiselect (isCI = false) > can select a group by selecting all members 1`] = ` 107 - [ 108 - "<cursor.hide>", 109 - "<dim>│</fg> 110 - <cyan>◆</fg> foo 111 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 112 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 113 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 114 - <cyan>└</fg> 115 - ", 116 - "<cursor.backward count=999><cursor.up count=6>", 117 - "<cursor.down count=2>", 118 - "<erase.down>", 119 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 120 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> group1value0 121 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group1value1</bold> 122 - <cyan>└</fg> 123 - ", 124 - "<cursor.backward count=999><cursor.up count=6>", 125 - "<cursor.down count=3>", 126 - "<erase.line><cursor.left count=1>", 127 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> group1value0", 128 - "<cursor.down count=3>", 129 - "<cursor.backward count=999><cursor.up count=6>", 130 - "<cursor.down count=3>", 131 - "<erase.down>", 132 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> <dim>group1value0</bold> 133 - <cyan>│</fg> <dim>└ </bold><cyan>◻</fg> group1value1 134 - <cyan>└</fg> 135 - ", 136 - "<cursor.backward count=999><cursor.up count=6>", 137 - "<cursor.down count=2>", 138 - "<erase.down>", 139 - "<cyan>│</fg> <dim></bold><green>◼</fg> <dim>group1</bold> 140 - <cyan>│</fg> <dim>│ </bold><green>◼</fg> <dim>group1value0</bold> 141 - <cyan>│</fg> <dim>└ </bold><green>◼</fg> group1value1 142 - <cyan>└</fg> 143 - ", 144 - "<cursor.backward count=999><cursor.up count=6>", 145 - "<cursor.down count=1>", 146 - "<erase.down>", 147 - "<green>◇</fg> foo 148 - <dim>│</fg> <dim>group1value0</bold><dim>, </bold><dim>group1value1</bold>", 149 - " 150 - ", 151 - "<cursor.show>", 152 - ] 153 - `; 154 - 155 - exports[`groupMultiselect (isCI = false) > can select multiple options 1`] = ` 156 - [ 157 - "<cursor.hide>", 158 - "<dim>│</fg> 159 - <cyan>◆</fg> foo 160 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 161 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 162 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value1</bold> 163 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value2</bold> 164 - <cyan>└</fg> 165 - ", 166 - "<cursor.backward count=999><cursor.up count=7>", 167 - "<cursor.down count=2>", 168 - "<erase.down>", 169 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 170 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> group1value0 171 - <cyan>│</fg> <dim>│ </bold><dim>◻</bold> <dim>group1value1</bold> 172 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group1value2</bold> 173 - <cyan>└</fg> 174 - ", 175 - "<cursor.backward count=999><cursor.up count=7>", 176 - "<cursor.down count=3>", 177 - "<erase.line><cursor.left count=1>", 178 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> group1value0", 179 - "<cursor.down count=4>", 180 - "<cursor.backward count=999><cursor.up count=7>", 181 - "<cursor.down count=3>", 182 - "<erase.down>", 183 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> <dim>group1value0</bold> 184 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> group1value1 185 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group1value2</bold> 186 - <cyan>└</fg> 187 - ", 188 - "<cursor.backward count=999><cursor.up count=7>", 189 - "<cursor.down count=4>", 190 - "<erase.line><cursor.left count=1>", 191 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> group1value1", 192 - "<cursor.down count=3>", 193 - "<cursor.backward count=999><cursor.up count=7>", 194 - "<cursor.down count=1>", 195 - "<erase.down>", 196 - "<green>◇</fg> foo 197 - <dim>│</fg> <dim>group1value0</bold><dim>, </bold><dim>group1value1</bold>", 198 - " 199 - ", 200 - "<cursor.show>", 201 - ] 202 - `; 203 - 204 - exports[`groupMultiselect (isCI = false) > can submit empty selection when require = false 1`] = ` 205 - [ 206 - "<cursor.hide>", 207 - "<dim>│</fg> 208 - <cyan>◆</fg> foo 209 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 210 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 211 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 212 - <cyan>└</fg> 213 - ", 214 - "<cursor.backward count=999><cursor.up count=6>", 215 - "<cursor.down count=1>", 216 - "<erase.down>", 217 - "<green>◇</fg> foo 218 - <dim>│</fg>", 219 - " 220 - ", 221 - "<cursor.show>", 222 - ] 223 - `; 224 - 225 - exports[`groupMultiselect (isCI = false) > cursorAt sets initial selection 1`] = ` 226 - [ 227 - "<cursor.hide>", 228 - "<dim>│</fg> 229 - <cyan>◆</fg> foo 230 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 231 - <cyan>│</fg> <dim>│ </bold><dim>◻</bold> <dim>group1value0</bold> 232 - <cyan>│</fg> <dim>└ </bold><cyan>◻</fg> group1value1 233 - <cyan>└</fg> 234 - ", 235 - "<cursor.backward count=999><cursor.up count=6>", 236 - "<cursor.down count=4>", 237 - "<erase.line><cursor.left count=1>", 238 - "<cyan>│</fg> <dim>└ </bold><green>◼</fg> group1value1", 239 - "<cursor.down count=2>", 240 - "<cursor.backward count=999><cursor.up count=6>", 241 - "<cursor.down count=1>", 242 - "<erase.down>", 243 - "<green>◇</fg> foo 244 - <dim>│</fg> <dim>group1value1</bold>", 245 - " 246 - ", 247 - "<cursor.show>", 248 - ] 249 - `; 250 - 251 - exports[`groupMultiselect (isCI = false) > global withGuide: false removes guide 1`] = ` 252 - [ 253 - "<cursor.hide>", 254 - "<cyan>◆</fg> foo 255 - <dim></bold><cyan>◻</fg> group1 256 - │ <cyan>◻</fg> <dim>group1value0</bold> 257 - └ <cyan>◻</fg> <dim>group1value1</bold> 258 - 259 - ", 260 - "<cursor.backward count=999><cursor.up count=5>", 261 - "<cursor.down count=1>", 262 - "<erase.down>", 263 - " <dim></bold><dim>◻</bold> <dim>group1</bold> 264 - <dim>│ </bold><cyan>◻</fg> group1value0 265 - <dim>└ </bold><dim>◻</bold> <dim>group1value1</bold> 266 - 267 - ", 268 - "<cursor.backward count=999><cursor.up count=5>", 269 - "<cursor.down count=2>", 270 - "<erase.line><cursor.left count=1>", 271 - " <dim>│ </bold><green>◼</fg> group1value0", 272 - "<cursor.down count=3>", 273 - "<cursor.backward count=999><cursor.up count=5>", 274 - "<erase.down>", 275 - "<green>◇</fg> foo 276 - <dim>group1value0</bold>", 277 - " 278 - ", 279 - "<cursor.show>", 280 - ] 281 - `; 282 - 283 - exports[`groupMultiselect (isCI = false) > groupSpacing > negative spacing is ignored 1`] = ` 284 - [ 285 - "<cursor.hide>", 286 - "<dim>│</fg> 287 - <cyan>◆</fg> foo 288 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 289 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value0</bold> 290 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 291 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 292 - <cyan>└</fg> 293 - ", 294 - "<cursor.backward count=999><cursor.up count=7>", 295 - "<cursor.down count=2>", 296 - "<erase.down>", 297 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 298 - <cyan>│</fg> <dim>└ </bold><cyan>◻</fg> group1value0 299 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 300 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 301 - <cyan>└</fg> 302 - ", 303 - "<cursor.backward count=999><cursor.up count=7>", 304 - "<cursor.down count=2>", 305 - "<erase.down>", 306 - "<cyan>│</fg> <dim></bold><green>◼</fg> <dim>group1</bold> 307 - <cyan>│</fg> <dim>└ </bold><green>◼</fg> group1value0 308 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 309 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 310 - <cyan>└</fg> 311 - ", 312 - "<cursor.backward count=999><cursor.up count=7>", 313 - "<cursor.down count=1>", 314 - "<erase.down>", 315 - "<green>◇</fg> foo 316 - <dim>│</fg> <dim>group1value0</bold>", 317 - " 318 - ", 319 - "<cursor.show>", 320 - ] 321 - `; 322 - 323 - exports[`groupMultiselect (isCI = false) > groupSpacing > renders spaced groups 1`] = ` 324 - [ 325 - "<cursor.hide>", 326 - "<dim>│</fg> 327 - <cyan>◆</fg> foo 328 - <cyan>│</fg> 329 - <cyan>│</fg> 330 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 331 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value0</bold> 332 - <cyan>│</fg> 333 - <cyan>│</fg> 334 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 335 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 336 - <cyan>└</fg> 337 - ", 338 - "<cursor.backward count=999><cursor.up count=11>", 339 - "<cursor.down count=4>", 340 - "<erase.down>", 341 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 342 - <cyan>│</fg> <dim>└ </bold><cyan>◻</fg> group1value0 343 - <cyan>│</fg> 344 - <cyan>│</fg> 345 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 346 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 347 - <cyan>└</fg> 348 - ", 349 - "<cursor.backward count=999><cursor.up count=11>", 350 - "<cursor.down count=4>", 351 - "<erase.down>", 352 - "<cyan>│</fg> <dim></bold><green>◼</fg> <dim>group1</bold> 353 - <cyan>│</fg> <dim>└ </bold><green>◼</fg> group1value0 354 - <cyan>│</fg> 355 - <cyan>│</fg> 356 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 357 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 358 - <cyan>└</fg> 359 - ", 360 - "<cursor.backward count=999><cursor.up count=11>", 361 - "<cursor.down count=1>", 362 - "<erase.down>", 363 - "<green>◇</fg> foo 364 - <dim>│</fg> <dim>group1value0</bold>", 365 - " 366 - ", 367 - "<cursor.show>", 368 - ] 369 - `; 370 - 371 - exports[`groupMultiselect (isCI = false) > initial values can be set 1`] = ` 372 - [ 373 - "<cursor.hide>", 374 - "<dim>│</fg> 375 - <cyan>◆</fg> foo 376 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 377 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 378 - <cyan>│</fg> └ <green>◼</fg> <dim>group1value1</bold> 379 - <cyan>└</fg> 380 - ", 381 - "<cursor.backward count=999><cursor.up count=6>", 382 - "<cursor.down count=1>", 383 - "<erase.down>", 384 - "<green>◇</fg> foo 385 - <dim>│</fg> <dim>group1value1</bold>", 386 - " 387 - ", 388 - "<cursor.show>", 389 - ] 390 - `; 391 - 392 - exports[`groupMultiselect (isCI = false) > renders error when nothing selected 1`] = ` 393 - [ 394 - "<cursor.hide>", 395 - "<dim>│</fg> 396 - <cyan>◆</fg> foo 397 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 398 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 399 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 400 - <cyan>└</fg> 401 - ", 402 - "<cursor.backward count=999><cursor.up count=6>", 403 - "<cursor.down count=1>", 404 - "<erase.down>", 405 - "<yellow>▲</fg> foo 406 - <yellow>│</fg> <dim></bold><cyan>◻</fg> group1 407 - <yellow>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 408 - <yellow>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 409 - <yellow>└</fg> <yellow>Please select at least one option.</fg> 410 - </><dim>Press <dim><bg:white> space </bg></fg> to select, <dim><bg:white> enter </bg></fg> to submit</bold></> 411 - ", 412 - "<cursor.backward count=999><cursor.up count=7>", 413 - "<cursor.down count=1>", 414 - "<erase.down>", 415 - "<cyan>◆</fg> foo 416 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 417 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> group1value0 418 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group1value1</bold> 419 - <cyan>└</fg> 420 - ", 421 - "<cursor.backward count=999><cursor.up count=6>", 422 - "<cursor.down count=3>", 423 - "<erase.line><cursor.left count=1>", 424 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> group1value0", 425 - "<cursor.down count=3>", 426 - "<cursor.backward count=999><cursor.up count=6>", 427 - "<cursor.down count=1>", 428 - "<erase.down>", 429 - "<green>◇</fg> foo 430 - <dim>│</fg> <dim>group1value0</bold>", 431 - " 432 - ", 433 - "<cursor.show>", 434 - ] 435 - `; 436 - 437 - exports[`groupMultiselect (isCI = false) > renders message with options 1`] = ` 438 - [ 439 - "<cursor.hide>", 440 - "<dim>│</fg> 441 - <cyan>◆</fg> foo 442 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 443 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 444 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 445 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 446 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 447 - <cyan>└</fg> 448 - ", 449 - "<cursor.backward count=999><cursor.up count=8>", 450 - "<cursor.down count=2>", 451 - "<erase.down>", 452 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 453 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> group1value0 454 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group1value1</bold> 455 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 456 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 457 - <cyan>└</fg> 458 - ", 459 - "<cursor.backward count=999><cursor.up count=8>", 460 - "<cursor.down count=3>", 461 - "<erase.line><cursor.left count=1>", 462 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> group1value0", 463 - "<cursor.down count=5>", 464 - "<cursor.backward count=999><cursor.up count=8>", 465 - "<cursor.down count=1>", 466 - "<erase.down>", 467 - "<green>◇</fg> foo 468 - <dim>│</fg> <dim>group1value0</bold>", 469 - " 470 - ", 471 - "<cursor.show>", 472 - ] 473 - `; 474 - 475 - exports[`groupMultiselect (isCI = false) > selectableGroups = false > cannot select groups 1`] = ` 476 - [ 477 - "<cursor.hide>", 478 - "<dim>│</fg> 479 - <cyan>◆</fg> foo 480 - <cyan>│</fg> <dim></bold> <dim>group1</bold> 481 - <cyan>│</fg> <dim> </bold><cyan>◻</fg> group1value0 482 - <cyan>│</fg> <dim> </bold><dim>◻</bold> <dim>group1value1</bold> 483 - <cyan>└</fg> 484 - ", 485 - "<cursor.backward count=999><cursor.up count=6>", 486 - "<cursor.down count=3>", 487 - "<erase.line><cursor.left count=1>", 488 - "<cyan>│</fg> <dim> </bold><green>◼</fg> group1value0", 489 - "<cursor.down count=3>", 490 - "<cursor.backward count=999><cursor.up count=6>", 491 - "<cursor.down count=1>", 492 - "<erase.down>", 493 - "<green>◇</fg> foo 494 - <dim>│</fg> <dim>group1value0</bold>", 495 - " 496 - ", 497 - "<cursor.show>", 498 - ] 499 - `; 500 - 501 - exports[`groupMultiselect (isCI = false) > selectableGroups = false > selecting all members of group does not select group 1`] = ` 502 - [ 503 - "<cursor.hide>", 504 - "<dim>│</fg> 505 - <cyan>◆</fg> foo 506 - <cyan>│</fg> <dim></bold> <dim>group1</bold> 507 - <cyan>│</fg> <dim> </bold><cyan>◻</fg> group1value0 508 - <cyan>│</fg> <dim> </bold><dim>◻</bold> <dim>group1value1</bold> 509 - <cyan>└</fg> 510 - ", 511 - "<cursor.backward count=999><cursor.up count=6>", 512 - "<cursor.down count=3>", 513 - "<erase.line><cursor.left count=1>", 514 - "<cyan>│</fg> <dim> </bold><green>◼</fg> group1value0", 515 - "<cursor.down count=3>", 516 - "<cursor.backward count=999><cursor.up count=6>", 517 - "<cursor.down count=3>", 518 - "<erase.down>", 519 - "<cyan>│</fg> <dim> </bold><green>◼</fg> <dim>group1value0</bold> 520 - <cyan>│</fg> <dim> </bold><cyan>◻</fg> group1value1 521 - <cyan>└</fg> 522 - ", 523 - "<cursor.backward count=999><cursor.up count=6>", 524 - "<cursor.down count=4>", 525 - "<erase.line><cursor.left count=1>", 526 - "<cyan>│</fg> <dim> </bold><green>◼</fg> group1value1", 527 - "<cursor.down count=2>", 528 - "<cursor.backward count=999><cursor.up count=6>", 529 - "<cursor.down count=1>", 530 - "<erase.down>", 531 - "<green>◇</fg> foo 532 - <dim>│</fg> <dim>group1value0</bold><dim>, </bold><dim>group1value1</bold>", 533 - " 534 - ", 535 - "<cursor.show>", 536 - ] 537 - `; 538 - 539 - exports[`groupMultiselect (isCI = false) > values can be non-primitive 1`] = ` 540 - [ 541 - "<cursor.hide>", 542 - "<dim>│</fg> 543 - <cyan>◆</fg> foo 544 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 545 - <cyan>│</fg> │ <cyan>◻</fg> <dim>value0</bold> 546 - <cyan>│</fg> └ <cyan>◻</fg> <dim>value1</bold> 547 - <cyan>└</fg> 548 - ", 549 - "<cursor.backward count=999><cursor.up count=6>", 550 - "<cursor.down count=2>", 551 - "<erase.down>", 552 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 553 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> value0 554 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>value1</bold> 555 - <cyan>└</fg> 556 - ", 557 - "<cursor.backward count=999><cursor.up count=6>", 558 - "<cursor.down count=3>", 559 - "<erase.line><cursor.left count=1>", 560 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> value0", 561 - "<cursor.down count=3>", 562 - "<cursor.backward count=999><cursor.up count=6>", 563 - "<cursor.down count=1>", 564 - "<erase.down>", 565 - "<green>◇</fg> foo 566 - <dim>│</fg> <dim>value0</bold>", 567 - " 568 - ", 569 - "<cursor.show>", 570 - ] 571 - `; 572 - 573 - exports[`groupMultiselect (isCI = false) > withGuide: false removes guide 1`] = ` 574 - [ 575 - "<cursor.hide>", 576 - "<cyan>◆</fg> foo 577 - <dim></bold><cyan>◻</fg> group1 578 - │ <cyan>◻</fg> <dim>group1value0</bold> 579 - └ <cyan>◻</fg> <dim>group1value1</bold> 580 - 581 - ", 582 - "<cursor.backward count=999><cursor.up count=5>", 583 - "<cursor.down count=1>", 584 - "<erase.down>", 585 - " <dim></bold><dim>◻</bold> <dim>group1</bold> 586 - <dim>│ </bold><cyan>◻</fg> group1value0 587 - <dim>└ </bold><dim>◻</bold> <dim>group1value1</bold> 588 - 589 - ", 590 - "<cursor.backward count=999><cursor.up count=5>", 591 - "<cursor.down count=2>", 592 - "<erase.line><cursor.left count=1>", 593 - " <dim>│ </bold><green>◼</fg> group1value0", 594 - "<cursor.down count=3>", 595 - "<cursor.backward count=999><cursor.up count=5>", 596 - "<erase.down>", 597 - "<green>◇</fg> foo 598 - <dim>group1value0</bold>", 599 - " 600 - ", 601 - "<cursor.show>", 602 - ] 603 - `; 604 - 605 - exports[`groupMultiselect (isCI = true) > can be aborted by a signal 1`] = ` 606 - [ 607 - "<cursor.hide>", 608 - "<dim>│</fg> 609 - <cyan>◆</fg> Select a fruit 610 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 611 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value0</bold> 612 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 613 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 614 - <cyan>└</fg> 615 - ", 616 - " 617 - ", 618 - "<cursor.show>", 619 - ] 620 - `; 621 - 622 - exports[`groupMultiselect (isCI = true) > can deselect an option 1`] = ` 623 - [ 624 - "<cursor.hide>", 625 - "<dim>│</fg> 626 - <cyan>◆</fg> foo 627 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 628 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 629 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 630 - <cyan>└</fg> 631 - ", 632 - "<cursor.backward count=999><cursor.up count=6>", 633 - "<cursor.down count=2>", 634 - "<erase.down>", 635 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 636 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> group1value0 637 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group1value1</bold> 638 - <cyan>└</fg> 639 - ", 640 - "<cursor.backward count=999><cursor.up count=6>", 641 - "<cursor.down count=3>", 642 - "<erase.line><cursor.left count=1>", 643 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> group1value0", 644 - "<cursor.down count=3>", 645 - "<cursor.backward count=999><cursor.up count=6>", 646 - "<cursor.down count=3>", 647 - "<erase.down>", 648 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> <dim>group1value0</bold> 649 - <cyan>│</fg> <dim>└ </bold><cyan>◻</fg> group1value1 650 - <cyan>└</fg> 651 - ", 652 - "<cursor.backward count=999><cursor.up count=6>", 653 - "<cursor.down count=2>", 654 - "<erase.down>", 655 - "<cyan>│</fg> <dim></bold><green>◼</fg> <dim>group1</bold> 656 - <cyan>│</fg> <dim>│ </bold><green>◼</fg> <dim>group1value0</bold> 657 - <cyan>│</fg> <dim>└ </bold><green>◼</fg> group1value1 658 - <cyan>└</fg> 659 - ", 660 - "<cursor.backward count=999><cursor.up count=6>", 661 - "<cursor.down count=2>", 662 - "<erase.down>", 663 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 664 - <cyan>│</fg> <dim>│ </bold><green>◼</fg> <dim>group1value0</bold> 665 - <cyan>│</fg> <dim>└ </bold><cyan>◻</fg> group1value1 666 - <cyan>└</fg> 667 - ", 668 - "<cursor.backward count=999><cursor.up count=6>", 669 - "<cursor.down count=1>", 670 - "<erase.down>", 671 - "<green>◇</fg> foo 672 - <dim>│</fg> <dim>group1value0</bold>", 673 - " 674 - ", 675 - "<cursor.show>", 676 - ] 677 - `; 678 - 679 - exports[`groupMultiselect (isCI = true) > can select a group 1`] = ` 680 - [ 681 - "<cursor.hide>", 682 - "<dim>│</fg> 683 - <cyan>◆</fg> foo 684 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 685 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 686 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 687 - <cyan>└</fg> 688 - ", 689 - "<cursor.backward count=999><cursor.up count=6>", 690 - "<cursor.down count=2>", 691 - "<erase.down>", 692 - "<cyan>│</fg> <dim></bold><green>◼</fg> group1 693 - <cyan>│</fg> │ <green>◼</fg> <dim>group1value0</bold> 694 - <cyan>│</fg> └ <green>◼</fg> <dim>group1value1</bold> 695 - <cyan>└</fg> 696 - ", 697 - "<cursor.backward count=999><cursor.up count=6>", 698 - "<cursor.down count=1>", 699 - "<erase.down>", 700 - "<green>◇</fg> foo 701 - <dim>│</fg> <dim>group1value0</bold><dim>, </bold><dim>group1value1</bold>", 702 - " 703 - ", 704 - "<cursor.show>", 705 - ] 706 - `; 707 - 708 - exports[`groupMultiselect (isCI = true) > can select a group by selecting all members 1`] = ` 709 - [ 710 - "<cursor.hide>", 711 - "<dim>│</fg> 712 - <cyan>◆</fg> foo 713 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 714 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 715 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 716 - <cyan>└</fg> 717 - ", 718 - "<cursor.backward count=999><cursor.up count=6>", 719 - "<cursor.down count=2>", 720 - "<erase.down>", 721 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 722 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> group1value0 723 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group1value1</bold> 724 - <cyan>└</fg> 725 - ", 726 - "<cursor.backward count=999><cursor.up count=6>", 727 - "<cursor.down count=3>", 728 - "<erase.line><cursor.left count=1>", 729 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> group1value0", 730 - "<cursor.down count=3>", 731 - "<cursor.backward count=999><cursor.up count=6>", 732 - "<cursor.down count=3>", 733 - "<erase.down>", 734 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> <dim>group1value0</bold> 735 - <cyan>│</fg> <dim>└ </bold><cyan>◻</fg> group1value1 736 - <cyan>└</fg> 737 - ", 738 - "<cursor.backward count=999><cursor.up count=6>", 739 - "<cursor.down count=2>", 740 - "<erase.down>", 741 - "<cyan>│</fg> <dim></bold><green>◼</fg> <dim>group1</bold> 742 - <cyan>│</fg> <dim>│ </bold><green>◼</fg> <dim>group1value0</bold> 743 - <cyan>│</fg> <dim>└ </bold><green>◼</fg> group1value1 744 - <cyan>└</fg> 745 - ", 746 - "<cursor.backward count=999><cursor.up count=6>", 747 - "<cursor.down count=1>", 748 - "<erase.down>", 749 - "<green>◇</fg> foo 750 - <dim>│</fg> <dim>group1value0</bold><dim>, </bold><dim>group1value1</bold>", 751 - " 752 - ", 753 - "<cursor.show>", 754 - ] 755 - `; 756 - 757 - exports[`groupMultiselect (isCI = true) > can select multiple options 1`] = ` 758 - [ 759 - "<cursor.hide>", 760 - "<dim>│</fg> 761 - <cyan>◆</fg> foo 762 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 763 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 764 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value1</bold> 765 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value2</bold> 766 - <cyan>└</fg> 767 - ", 768 - "<cursor.backward count=999><cursor.up count=7>", 769 - "<cursor.down count=2>", 770 - "<erase.down>", 771 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 772 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> group1value0 773 - <cyan>│</fg> <dim>│ </bold><dim>◻</bold> <dim>group1value1</bold> 774 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group1value2</bold> 775 - <cyan>└</fg> 776 - ", 777 - "<cursor.backward count=999><cursor.up count=7>", 778 - "<cursor.down count=3>", 779 - "<erase.line><cursor.left count=1>", 780 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> group1value0", 781 - "<cursor.down count=4>", 782 - "<cursor.backward count=999><cursor.up count=7>", 783 - "<cursor.down count=3>", 784 - "<erase.down>", 785 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> <dim>group1value0</bold> 786 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> group1value1 787 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group1value2</bold> 788 - <cyan>└</fg> 789 - ", 790 - "<cursor.backward count=999><cursor.up count=7>", 791 - "<cursor.down count=4>", 792 - "<erase.line><cursor.left count=1>", 793 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> group1value1", 794 - "<cursor.down count=3>", 795 - "<cursor.backward count=999><cursor.up count=7>", 796 - "<cursor.down count=1>", 797 - "<erase.down>", 798 - "<green>◇</fg> foo 799 - <dim>│</fg> <dim>group1value0</bold><dim>, </bold><dim>group1value1</bold>", 800 - " 801 - ", 802 - "<cursor.show>", 803 - ] 804 - `; 805 - 806 - exports[`groupMultiselect (isCI = true) > can submit empty selection when require = false 1`] = ` 807 - [ 808 - "<cursor.hide>", 809 - "<dim>│</fg> 810 - <cyan>◆</fg> foo 811 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 812 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 813 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 814 - <cyan>└</fg> 815 - ", 816 - "<cursor.backward count=999><cursor.up count=6>", 817 - "<cursor.down count=1>", 818 - "<erase.down>", 819 - "<green>◇</fg> foo 820 - <dim>│</fg>", 821 - " 822 - ", 823 - "<cursor.show>", 824 - ] 825 - `; 826 - 827 - exports[`groupMultiselect (isCI = true) > cursorAt sets initial selection 1`] = ` 828 - [ 829 - "<cursor.hide>", 830 - "<dim>│</fg> 831 - <cyan>◆</fg> foo 832 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 833 - <cyan>│</fg> <dim>│ </bold><dim>◻</bold> <dim>group1value0</bold> 834 - <cyan>│</fg> <dim>└ </bold><cyan>◻</fg> group1value1 835 - <cyan>└</fg> 836 - ", 837 - "<cursor.backward count=999><cursor.up count=6>", 838 - "<cursor.down count=4>", 839 - "<erase.line><cursor.left count=1>", 840 - "<cyan>│</fg> <dim>└ </bold><green>◼</fg> group1value1", 841 - "<cursor.down count=2>", 842 - "<cursor.backward count=999><cursor.up count=6>", 843 - "<cursor.down count=1>", 844 - "<erase.down>", 845 - "<green>◇</fg> foo 846 - <dim>│</fg> <dim>group1value1</bold>", 847 - " 848 - ", 849 - "<cursor.show>", 850 - ] 851 - `; 852 - 853 - exports[`groupMultiselect (isCI = true) > global withGuide: false removes guide 1`] = ` 854 - [ 855 - "<cursor.hide>", 856 - "<cyan>◆</fg> foo 857 - <dim></bold><cyan>◻</fg> group1 858 - │ <cyan>◻</fg> <dim>group1value0</bold> 859 - └ <cyan>◻</fg> <dim>group1value1</bold> 860 - 861 - ", 862 - "<cursor.backward count=999><cursor.up count=5>", 863 - "<cursor.down count=1>", 864 - "<erase.down>", 865 - " <dim></bold><dim>◻</bold> <dim>group1</bold> 866 - <dim>│ </bold><cyan>◻</fg> group1value0 867 - <dim>└ </bold><dim>◻</bold> <dim>group1value1</bold> 868 - 869 - ", 870 - "<cursor.backward count=999><cursor.up count=5>", 871 - "<cursor.down count=2>", 872 - "<erase.line><cursor.left count=1>", 873 - " <dim>│ </bold><green>◼</fg> group1value0", 874 - "<cursor.down count=3>", 875 - "<cursor.backward count=999><cursor.up count=5>", 876 - "<erase.down>", 877 - "<green>◇</fg> foo 878 - <dim>group1value0</bold>", 879 - " 880 - ", 881 - "<cursor.show>", 882 - ] 883 - `; 884 - 885 - exports[`groupMultiselect (isCI = true) > groupSpacing > negative spacing is ignored 1`] = ` 886 - [ 887 - "<cursor.hide>", 888 - "<dim>│</fg> 889 - <cyan>◆</fg> foo 890 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 891 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value0</bold> 892 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 893 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 894 - <cyan>└</fg> 895 - ", 896 - "<cursor.backward count=999><cursor.up count=7>", 897 - "<cursor.down count=2>", 898 - "<erase.down>", 899 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 900 - <cyan>│</fg> <dim>└ </bold><cyan>◻</fg> group1value0 901 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 902 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 903 - <cyan>└</fg> 904 - ", 905 - "<cursor.backward count=999><cursor.up count=7>", 906 - "<cursor.down count=2>", 907 - "<erase.down>", 908 - "<cyan>│</fg> <dim></bold><green>◼</fg> <dim>group1</bold> 909 - <cyan>│</fg> <dim>└ </bold><green>◼</fg> group1value0 910 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 911 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 912 - <cyan>└</fg> 913 - ", 914 - "<cursor.backward count=999><cursor.up count=7>", 915 - "<cursor.down count=1>", 916 - "<erase.down>", 917 - "<green>◇</fg> foo 918 - <dim>│</fg> <dim>group1value0</bold>", 919 - " 920 - ", 921 - "<cursor.show>", 922 - ] 923 - `; 924 - 925 - exports[`groupMultiselect (isCI = true) > groupSpacing > renders spaced groups 1`] = ` 926 - [ 927 - "<cursor.hide>", 928 - "<dim>│</fg> 929 - <cyan>◆</fg> foo 930 - <cyan>│</fg> 931 - <cyan>│</fg> 932 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 933 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value0</bold> 934 - <cyan>│</fg> 935 - <cyan>│</fg> 936 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 937 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 938 - <cyan>└</fg> 939 - ", 940 - "<cursor.backward count=999><cursor.up count=11>", 941 - "<cursor.down count=4>", 942 - "<erase.down>", 943 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 944 - <cyan>│</fg> <dim>└ </bold><cyan>◻</fg> group1value0 945 - <cyan>│</fg> 946 - <cyan>│</fg> 947 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 948 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 949 - <cyan>└</fg> 950 - ", 951 - "<cursor.backward count=999><cursor.up count=11>", 952 - "<cursor.down count=4>", 953 - "<erase.down>", 954 - "<cyan>│</fg> <dim></bold><green>◼</fg> <dim>group1</bold> 955 - <cyan>│</fg> <dim>└ </bold><green>◼</fg> group1value0 956 - <cyan>│</fg> 957 - <cyan>│</fg> 958 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 959 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 960 - <cyan>└</fg> 961 - ", 962 - "<cursor.backward count=999><cursor.up count=11>", 963 - "<cursor.down count=1>", 964 - "<erase.down>", 965 - "<green>◇</fg> foo 966 - <dim>│</fg> <dim>group1value0</bold>", 967 - " 968 - ", 969 - "<cursor.show>", 970 - ] 971 - `; 972 - 973 - exports[`groupMultiselect (isCI = true) > initial values can be set 1`] = ` 974 - [ 975 - "<cursor.hide>", 976 - "<dim>│</fg> 977 - <cyan>◆</fg> foo 978 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 979 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 980 - <cyan>│</fg> └ <green>◼</fg> <dim>group1value1</bold> 981 - <cyan>└</fg> 982 - ", 983 - "<cursor.backward count=999><cursor.up count=6>", 984 - "<cursor.down count=1>", 985 - "<erase.down>", 986 - "<green>◇</fg> foo 987 - <dim>│</fg> <dim>group1value1</bold>", 988 - " 989 - ", 990 - "<cursor.show>", 991 - ] 992 - `; 993 - 994 - exports[`groupMultiselect (isCI = true) > renders error when nothing selected 1`] = ` 995 - [ 996 - "<cursor.hide>", 997 - "<dim>│</fg> 998 - <cyan>◆</fg> foo 999 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 1000 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 1001 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 1002 - <cyan>└</fg> 1003 - ", 1004 - "<cursor.backward count=999><cursor.up count=6>", 1005 - "<cursor.down count=1>", 1006 - "<erase.down>", 1007 - "<yellow>▲</fg> foo 1008 - <yellow>│</fg> <dim></bold><cyan>◻</fg> group1 1009 - <yellow>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 1010 - <yellow>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 1011 - <yellow>└</fg> <yellow>Please select at least one option.</fg> 1012 - </><dim>Press <dim><bg:white> space </bg></fg> to select, <dim><bg:white> enter </bg></fg> to submit</bold></> 1013 - ", 1014 - "<cursor.backward count=999><cursor.up count=7>", 1015 - "<cursor.down count=1>", 1016 - "<erase.down>", 1017 - "<cyan>◆</fg> foo 1018 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 1019 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> group1value0 1020 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group1value1</bold> 1021 - <cyan>└</fg> 1022 - ", 1023 - "<cursor.backward count=999><cursor.up count=6>", 1024 - "<cursor.down count=3>", 1025 - "<erase.line><cursor.left count=1>", 1026 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> group1value0", 1027 - "<cursor.down count=3>", 1028 - "<cursor.backward count=999><cursor.up count=6>", 1029 - "<cursor.down count=1>", 1030 - "<erase.down>", 1031 - "<green>◇</fg> foo 1032 - <dim>│</fg> <dim>group1value0</bold>", 1033 - " 1034 - ", 1035 - "<cursor.show>", 1036 - ] 1037 - `; 1038 - 1039 - exports[`groupMultiselect (isCI = true) > renders message with options 1`] = ` 1040 - [ 1041 - "<cursor.hide>", 1042 - "<dim>│</fg> 1043 - <cyan>◆</fg> foo 1044 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 1045 - <cyan>│</fg> │ <cyan>◻</fg> <dim>group1value0</bold> 1046 - <cyan>│</fg> └ <cyan>◻</fg> <dim>group1value1</bold> 1047 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 1048 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 1049 - <cyan>└</fg> 1050 - ", 1051 - "<cursor.backward count=999><cursor.up count=8>", 1052 - "<cursor.down count=2>", 1053 - "<erase.down>", 1054 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 1055 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> group1value0 1056 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group1value1</bold> 1057 - <cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group2</bold> 1058 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>group2value0</bold> 1059 - <cyan>└</fg> 1060 - ", 1061 - "<cursor.backward count=999><cursor.up count=8>", 1062 - "<cursor.down count=3>", 1063 - "<erase.line><cursor.left count=1>", 1064 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> group1value0", 1065 - "<cursor.down count=5>", 1066 - "<cursor.backward count=999><cursor.up count=8>", 1067 - "<cursor.down count=1>", 1068 - "<erase.down>", 1069 - "<green>◇</fg> foo 1070 - <dim>│</fg> <dim>group1value0</bold>", 1071 - " 1072 - ", 1073 - "<cursor.show>", 1074 - ] 1075 - `; 1076 - 1077 - exports[`groupMultiselect (isCI = true) > selectableGroups = false > cannot select groups 1`] = ` 1078 - [ 1079 - "<cursor.hide>", 1080 - "<dim>│</fg> 1081 - <cyan>◆</fg> foo 1082 - <cyan>│</fg> <dim></bold> <dim>group1</bold> 1083 - <cyan>│</fg> <dim> </bold><cyan>◻</fg> group1value0 1084 - <cyan>│</fg> <dim> </bold><dim>◻</bold> <dim>group1value1</bold> 1085 - <cyan>└</fg> 1086 - ", 1087 - "<cursor.backward count=999><cursor.up count=6>", 1088 - "<cursor.down count=3>", 1089 - "<erase.line><cursor.left count=1>", 1090 - "<cyan>│</fg> <dim> </bold><green>◼</fg> group1value0", 1091 - "<cursor.down count=3>", 1092 - "<cursor.backward count=999><cursor.up count=6>", 1093 - "<cursor.down count=1>", 1094 - "<erase.down>", 1095 - "<green>◇</fg> foo 1096 - <dim>│</fg> <dim>group1value0</bold>", 1097 - " 1098 - ", 1099 - "<cursor.show>", 1100 - ] 1101 - `; 1102 - 1103 - exports[`groupMultiselect (isCI = true) > selectableGroups = false > selecting all members of group does not select group 1`] = ` 1104 - [ 1105 - "<cursor.hide>", 1106 - "<dim>│</fg> 1107 - <cyan>◆</fg> foo 1108 - <cyan>│</fg> <dim></bold> <dim>group1</bold> 1109 - <cyan>│</fg> <dim> </bold><cyan>◻</fg> group1value0 1110 - <cyan>│</fg> <dim> </bold><dim>◻</bold> <dim>group1value1</bold> 1111 - <cyan>└</fg> 1112 - ", 1113 - "<cursor.backward count=999><cursor.up count=6>", 1114 - "<cursor.down count=3>", 1115 - "<erase.line><cursor.left count=1>", 1116 - "<cyan>│</fg> <dim> </bold><green>◼</fg> group1value0", 1117 - "<cursor.down count=3>", 1118 - "<cursor.backward count=999><cursor.up count=6>", 1119 - "<cursor.down count=3>", 1120 - "<erase.down>", 1121 - "<cyan>│</fg> <dim> </bold><green>◼</fg> <dim>group1value0</bold> 1122 - <cyan>│</fg> <dim> </bold><cyan>◻</fg> group1value1 1123 - <cyan>└</fg> 1124 - ", 1125 - "<cursor.backward count=999><cursor.up count=6>", 1126 - "<cursor.down count=4>", 1127 - "<erase.line><cursor.left count=1>", 1128 - "<cyan>│</fg> <dim> </bold><green>◼</fg> group1value1", 1129 - "<cursor.down count=2>", 1130 - "<cursor.backward count=999><cursor.up count=6>", 1131 - "<cursor.down count=1>", 1132 - "<erase.down>", 1133 - "<green>◇</fg> foo 1134 - <dim>│</fg> <dim>group1value0</bold><dim>, </bold><dim>group1value1</bold>", 1135 - " 1136 - ", 1137 - "<cursor.show>", 1138 - ] 1139 - `; 1140 - 1141 - exports[`groupMultiselect (isCI = true) > values can be non-primitive 1`] = ` 1142 - [ 1143 - "<cursor.hide>", 1144 - "<dim>│</fg> 1145 - <cyan>◆</fg> foo 1146 - <cyan>│</fg> <dim></bold><cyan>◻</fg> group1 1147 - <cyan>│</fg> │ <cyan>◻</fg> <dim>value0</bold> 1148 - <cyan>│</fg> └ <cyan>◻</fg> <dim>value1</bold> 1149 - <cyan>└</fg> 1150 - ", 1151 - "<cursor.backward count=999><cursor.up count=6>", 1152 - "<cursor.down count=2>", 1153 - "<erase.down>", 1154 - "<cyan>│</fg> <dim></bold><dim>◻</bold> <dim>group1</bold> 1155 - <cyan>│</fg> <dim>│ </bold><cyan>◻</fg> value0 1156 - <cyan>│</fg> <dim>└ </bold><dim>◻</bold> <dim>value1</bold> 1157 - <cyan>└</fg> 1158 - ", 1159 - "<cursor.backward count=999><cursor.up count=6>", 1160 - "<cursor.down count=3>", 1161 - "<erase.line><cursor.left count=1>", 1162 - "<cyan>│</fg> <dim>│ </bold><green>◼</fg> value0", 1163 - "<cursor.down count=3>", 1164 - "<cursor.backward count=999><cursor.up count=6>", 1165 - "<cursor.down count=1>", 1166 - "<erase.down>", 1167 - "<green>◇</fg> foo 1168 - <dim>│</fg> <dim>value0</bold>", 1169 - " 1170 - ", 1171 - "<cursor.show>", 1172 - ] 1173 - `; 1174 - 1175 - exports[`groupMultiselect (isCI = true) > withGuide: false removes guide 1`] = ` 1176 - [ 1177 - "<cursor.hide>", 1178 - "<cyan>◆</fg> foo 1179 - <dim></bold><cyan>◻</fg> group1 1180 - │ <cyan>◻</fg> <dim>group1value0</bold> 1181 - └ <cyan>◻</fg> <dim>group1value1</bold> 1182 - 1183 - ", 1184 - "<cursor.backward count=999><cursor.up count=5>", 1185 - "<cursor.down count=1>", 1186 - "<erase.down>", 1187 - " <dim></bold><dim>◻</bold> <dim>group1</bold> 1188 - <dim>│ </bold><cyan>◻</fg> group1value0 1189 - <dim>└ </bold><dim>◻</bold> <dim>group1value1</bold> 1190 - 1191 - ", 1192 - "<cursor.backward count=999><cursor.up count=5>", 1193 - "<cursor.down count=2>", 1194 - "<erase.line><cursor.left count=1>", 1195 - " <dim>│ </bold><green>◼</fg> group1value0", 1196 - "<cursor.down count=3>", 1197 - "<cursor.backward count=999><cursor.up count=5>", 1198 - "<erase.down>", 1199 - "<green>◇</fg> foo 1200 - <dim>group1value0</bold>", 1201 - " 1202 - ", 1203 - "<cursor.show>", 1204 - ] 1205 - `;
-283
packages/prompts/test/__snapshots__/log.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`log (isCI = false) > error > renders error message 1`] = ` 4 - [ 5 - "<dim>│</fg> 6 - <red>■</fg> error message 7 - ", 8 - ] 9 - `; 10 - 11 - exports[`log (isCI = false) > info > renders info message 1`] = ` 12 - [ 13 - "<dim>│</fg> 14 - <blue>●</fg> info message 15 - ", 16 - ] 17 - `; 18 - 19 - exports[`log (isCI = false) > message > renders empty lines correctly 1`] = ` 20 - [ 21 - "<dim>│</fg> 22 - <dim>│</fg> foo 23 - <dim>│</fg> 24 - <dim>│</fg> bar 25 - ", 26 - ] 27 - `; 28 - 29 - exports[`log (isCI = false) > message > renders empty lines with guide disabled 1`] = ` 30 - [ 31 - " 32 - foo 33 - 34 - bar 35 - ", 36 - ] 37 - `; 38 - 39 - exports[`log (isCI = false) > message > renders empty message correctly 1`] = ` 40 - [ 41 - "<dim>│</fg> 42 - <dim>│</fg> 43 - ", 44 - ] 45 - `; 46 - 47 - exports[`log (isCI = false) > message > renders empty message with guide disabled 1`] = ` 48 - [ 49 - " 50 - 51 - ", 52 - ] 53 - `; 54 - 55 - exports[`log (isCI = false) > message > renders message 1`] = ` 56 - [ 57 - "<dim>│</fg> 58 - <dim>│</fg> message 59 - ", 60 - ] 61 - `; 62 - 63 - exports[`log (isCI = false) > message > renders message from array 1`] = ` 64 - [ 65 - "<dim>│</fg> 66 - <dim>│</fg> line 1 67 - <dim>│</fg> line 2 68 - <dim>│</fg> line 3 69 - ", 70 - ] 71 - `; 72 - 73 - exports[`log (isCI = false) > message > renders message with custom spacing 1`] = ` 74 - [ 75 - "<dim>│</fg> 76 - <dim>│</fg> 77 - <dim>│</fg> 78 - <dim>│</fg> spaced message 79 - ", 80 - ] 81 - `; 82 - 83 - exports[`log (isCI = false) > message > renders message with custom symbols and spacing 1`] = ` 84 - [ 85 - "<yellow>--</fg> 86 - <red>>></fg> custom 87 - <yellow>--</fg> symbols 88 - ", 89 - ] 90 - `; 91 - 92 - exports[`log (isCI = false) > message > renders message with guide disabled 1`] = ` 93 - [ 94 - " 95 - standalone message 96 - ", 97 - ] 98 - `; 99 - 100 - exports[`log (isCI = false) > message > renders multiline message 1`] = ` 101 - [ 102 - "<dim>│</fg> 103 - <dim>│</fg> line 1 104 - <dim>│</fg> line 2 105 - <dim>│</fg> line 3 106 - ", 107 - ] 108 - `; 109 - 110 - exports[`log (isCI = false) > message > renders multiline message with guide disabled 1`] = ` 111 - [ 112 - " 113 - line 1 114 - line 2 115 - line 3 116 - ", 117 - ] 118 - `; 119 - 120 - exports[`log (isCI = false) > step > renders step message 1`] = ` 121 - [ 122 - "<dim>│</fg> 123 - <green>◇</fg> step message 124 - ", 125 - ] 126 - `; 127 - 128 - exports[`log (isCI = false) > success > renders success message 1`] = ` 129 - [ 130 - "<dim>│</fg> 131 - <green>◆</fg> success message 132 - ", 133 - ] 134 - `; 135 - 136 - exports[`log (isCI = false) > warn > renders warn message 1`] = ` 137 - [ 138 - "<dim>│</fg> 139 - <yellow>▲</fg> warn message 140 - ", 141 - ] 142 - `; 143 - 144 - exports[`log (isCI = true) > error > renders error message 1`] = ` 145 - [ 146 - "<dim>│</fg> 147 - <red>■</fg> error message 148 - ", 149 - ] 150 - `; 151 - 152 - exports[`log (isCI = true) > info > renders info message 1`] = ` 153 - [ 154 - "<dim>│</fg> 155 - <blue>●</fg> info message 156 - ", 157 - ] 158 - `; 159 - 160 - exports[`log (isCI = true) > message > renders empty lines correctly 1`] = ` 161 - [ 162 - "<dim>│</fg> 163 - <dim>│</fg> foo 164 - <dim>│</fg> 165 - <dim>│</fg> bar 166 - ", 167 - ] 168 - `; 169 - 170 - exports[`log (isCI = true) > message > renders empty lines with guide disabled 1`] = ` 171 - [ 172 - " 173 - foo 174 - 175 - bar 176 - ", 177 - ] 178 - `; 179 - 180 - exports[`log (isCI = true) > message > renders empty message correctly 1`] = ` 181 - [ 182 - "<dim>│</fg> 183 - <dim>│</fg> 184 - ", 185 - ] 186 - `; 187 - 188 - exports[`log (isCI = true) > message > renders empty message with guide disabled 1`] = ` 189 - [ 190 - " 191 - 192 - ", 193 - ] 194 - `; 195 - 196 - exports[`log (isCI = true) > message > renders message 1`] = ` 197 - [ 198 - "<dim>│</fg> 199 - <dim>│</fg> message 200 - ", 201 - ] 202 - `; 203 - 204 - exports[`log (isCI = true) > message > renders message from array 1`] = ` 205 - [ 206 - "<dim>│</fg> 207 - <dim>│</fg> line 1 208 - <dim>│</fg> line 2 209 - <dim>│</fg> line 3 210 - ", 211 - ] 212 - `; 213 - 214 - exports[`log (isCI = true) > message > renders message with custom spacing 1`] = ` 215 - [ 216 - "<dim>│</fg> 217 - <dim>│</fg> 218 - <dim>│</fg> 219 - <dim>│</fg> spaced message 220 - ", 221 - ] 222 - `; 223 - 224 - exports[`log (isCI = true) > message > renders message with custom symbols and spacing 1`] = ` 225 - [ 226 - "<yellow>--</fg> 227 - <red>>></fg> custom 228 - <yellow>--</fg> symbols 229 - ", 230 - ] 231 - `; 232 - 233 - exports[`log (isCI = true) > message > renders message with guide disabled 1`] = ` 234 - [ 235 - " 236 - standalone message 237 - ", 238 - ] 239 - `; 240 - 241 - exports[`log (isCI = true) > message > renders multiline message 1`] = ` 242 - [ 243 - "<dim>│</fg> 244 - <dim>│</fg> line 1 245 - <dim>│</fg> line 2 246 - <dim>│</fg> line 3 247 - ", 248 - ] 249 - `; 250 - 251 - exports[`log (isCI = true) > message > renders multiline message with guide disabled 1`] = ` 252 - [ 253 - " 254 - line 1 255 - line 2 256 - line 3 257 - ", 258 - ] 259 - `; 260 - 261 - exports[`log (isCI = true) > step > renders step message 1`] = ` 262 - [ 263 - "<dim>│</fg> 264 - <green>◇</fg> step message 265 - ", 266 - ] 267 - `; 268 - 269 - exports[`log (isCI = true) > success > renders success message 1`] = ` 270 - [ 271 - "<dim>│</fg> 272 - <green>◆</fg> success message 273 - ", 274 - ] 275 - `; 276 - 277 - exports[`log (isCI = true) > warn > renders warn message 1`] = ` 278 - [ 279 - "<dim>│</fg> 280 - <yellow>▲</fg> warn message 281 - ", 282 - ] 283 - `;
-831
packages/prompts/test/__snapshots__/multi-line.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`multiline (isCI = false) > can be aborted by a signal 1`] = ` 4 - [ 5 - "<cursor.hide>", 6 - "<dim>│</fg> 7 - <cyan>◆</fg> foo 8 - <cyan>│</fg> _ 9 - <cyan>└</fg> 10 - ", 11 - " 12 - ", 13 - "<cursor.show>", 14 - ] 15 - `; 16 - 17 - exports[`multiline (isCI = false) > can cancel 1`] = ` 18 - [ 19 - "<cursor.hide>", 20 - "<dim>│</fg> 21 - <cyan>◆</fg> foo 22 - <cyan>│</fg> _ 23 - <cyan>└</fg> 24 - ", 25 - "<cursor.backward count=999><cursor.up count=4>", 26 - "<cursor.down count=1>", 27 - "<erase.down>", 28 - "<red>■</fg> foo 29 - <dim>│</fg> <dim>escape</bold>", 30 - " 31 - ", 32 - "<cursor.show>", 33 - ] 34 - `; 35 - 36 - exports[`multiline (isCI = false) > defaultValue sets the value but does not render 1`] = ` 37 - [ 38 - "<cursor.hide>", 39 - "<dim>│</fg> 40 - <cyan>◆</fg> foo 41 - <cyan>│</fg> _ 42 - <cyan>└</fg> 43 - ", 44 - "<cursor.backward count=999><cursor.up count=4>", 45 - "<cursor.down count=2>", 46 - "<erase.down>", 47 - "<cyan>│</fg> 48 - <cyan>│</fg> █ 49 - <cyan>└</fg> 50 - ", 51 - "<cursor.backward count=999><cursor.up count=5>", 52 - "<cursor.down count=1>", 53 - "<erase.down>", 54 - "<green>◇</fg> foo 55 - <dim>│</fg> <dim>bar</bold>", 56 - " 57 - ", 58 - "<cursor.show>", 59 - ] 60 - `; 61 - 62 - exports[`multiline (isCI = false) > empty string when no value and no default 1`] = ` 63 - [ 64 - "<cursor.hide>", 65 - "<dim>│</fg> 66 - <cyan>◆</fg> foo 67 - <cyan>│</fg>  <dim> (submit to use default)</bold> 68 - <cyan>└</fg> 69 - ", 70 - "<cursor.backward count=999><cursor.up count=4>", 71 - "<cursor.down count=2>", 72 - "<erase.down>", 73 - "<cyan>│</fg> 74 - <cyan>│</fg> █ 75 - <cyan>└</fg> 76 - ", 77 - "<cursor.backward count=999><cursor.up count=5>", 78 - "<cursor.down count=1>", 79 - "<erase.down>", 80 - "<green>◇</fg> foo 81 - <dim>│</fg> <dim></bold>", 82 - " 83 - ", 84 - "<cursor.show>", 85 - ] 86 - `; 87 - 88 - exports[`multiline (isCI = false) > global withGuide: false removes guide 1`] = ` 89 - [ 90 - "<cursor.hide>", 91 - "<cyan>◆</fg> foo 92 - _ 93 - 94 - ", 95 - "<cursor.backward count=999><cursor.up count=3>", 96 - "<cursor.down count=1>", 97 - "<erase.down>", 98 - " 99 - 100 - 101 - ", 102 - "<cursor.backward count=999><cursor.up count=4>", 103 - "<erase.down>", 104 - "<green>◇</fg> foo 105 - ", 106 - " 107 - ", 108 - "<cursor.show>", 109 - ] 110 - `; 111 - 112 - exports[`multiline (isCI = false) > placeholder is not used as value when pressing enter 1`] = ` 113 - [ 114 - "<cursor.hide>", 115 - "<dim>│</fg> 116 - <cyan>◆</fg> foo 117 - <cyan>│</fg>  <dim> (submit to use default)</bold> 118 - <cyan>└</fg> 119 - ", 120 - "<cursor.backward count=999><cursor.up count=4>", 121 - "<cursor.down count=2>", 122 - "<erase.down>", 123 - "<cyan>│</fg> 124 - <cyan>│</fg> █ 125 - <cyan>└</fg> 126 - ", 127 - "<cursor.backward count=999><cursor.up count=5>", 128 - "<cursor.down count=1>", 129 - "<erase.down>", 130 - "<green>◇</fg> foo 131 - <dim>│</fg> <dim>default-value</bold>", 132 - " 133 - ", 134 - "<cursor.show>", 135 - ] 136 - `; 137 - 138 - exports[`multiline (isCI = false) > renders cancelled value if one set 1`] = ` 139 - [ 140 - "<cursor.hide>", 141 - "<dim>│</fg> 142 - <cyan>◆</fg> foo 143 - <cyan>│</fg> _ 144 - <cyan>└</fg> 145 - ", 146 - "<cursor.backward count=999><cursor.up count=4>", 147 - "<cursor.down count=2>", 148 - "<erase.line><cursor.left count=1>", 149 - "<cyan>│</fg> x█", 150 - "<cursor.down count=2>", 151 - "<cursor.backward count=999><cursor.up count=4>", 152 - "<cursor.down count=2>", 153 - "<erase.line><cursor.left count=1>", 154 - "<cyan>│</fg> xy█", 155 - "<cursor.down count=2>", 156 - "<cursor.backward count=999><cursor.up count=4>", 157 - "<cursor.down count=1>", 158 - "<erase.down>", 159 - "<red>■</fg> foo 160 - <dim>│</fg> <dim>xy</bold>", 161 - " 162 - ", 163 - "<cursor.show>", 164 - ] 165 - `; 166 - 167 - exports[`multiline (isCI = false) > renders message 1`] = ` 168 - [ 169 - "<cursor.hide>", 170 - "<dim>│</fg> 171 - <cyan>◆</fg> foo 172 - <cyan>│</fg> _ 173 - <cyan>└</fg> 174 - ", 175 - "<cursor.backward count=999><cursor.up count=4>", 176 - "<cursor.down count=2>", 177 - "<erase.down>", 178 - "<cyan>│</fg> 179 - <cyan>│</fg> █ 180 - <cyan>└</fg> 181 - ", 182 - "<cursor.backward count=999><cursor.up count=5>", 183 - "<cursor.down count=1>", 184 - "<erase.down>", 185 - "<green>◇</fg> foo 186 - <dim>│</fg> <dim></bold>", 187 - " 188 - ", 189 - "<cursor.show>", 190 - ] 191 - `; 192 - 193 - exports[`multiline (isCI = false) > renders placeholder if set 1`] = ` 194 - [ 195 - "<cursor.hide>", 196 - "<dim>│</fg> 197 - <cyan>◆</fg> foo 198 - <cyan>│</fg> b<dim>ar</bold> 199 - <cyan>└</fg> 200 - ", 201 - "<cursor.backward count=999><cursor.up count=4>", 202 - "<cursor.down count=2>", 203 - "<erase.down>", 204 - "<cyan>│</fg> 205 - <cyan>│</fg> █ 206 - <cyan>└</fg> 207 - ", 208 - "<cursor.backward count=999><cursor.up count=5>", 209 - "<cursor.down count=1>", 210 - "<erase.down>", 211 - "<green>◇</fg> foo 212 - <dim>│</fg> <dim></bold>", 213 - " 214 - ", 215 - "<cursor.show>", 216 - ] 217 - `; 218 - 219 - exports[`multiline (isCI = false) > renders submit button 1`] = ` 220 - [ 221 - "<cursor.hide>", 222 - "<dim>│</fg> 223 - <cyan>◆</fg> foo 224 - <cyan>│</fg> _ 225 - <cyan>└</fg> 226 - <dim>[ submit ]</bold> 227 - ", 228 - "<cursor.backward count=999><cursor.up count=5>", 229 - "<cursor.down count=2>", 230 - "<erase.line><cursor.left count=1>", 231 - "<cyan>│</fg> x█", 232 - "<cursor.down count=3>", 233 - "<cursor.backward count=999><cursor.up count=5>", 234 - "<cursor.down count=2>", 235 - "<erase.line><cursor.left count=1>", 236 - "<cyan>│</fg> xy█", 237 - "<cursor.down count=3>", 238 - "<cursor.backward count=999><cursor.up count=5>", 239 - "<cursor.down count=4>", 240 - "<erase.line><cursor.left count=1>", 241 - " <cyan>[ submit ]</fg>", 242 - "<cursor.down count=1>", 243 - "<cursor.backward count=999><cursor.up count=5>", 244 - "<cursor.down count=1>", 245 - "<erase.down>", 246 - "<green>◇</fg> foo 247 - <dim>│</fg> <dim>xy</bold>", 248 - " 249 - ", 250 - "<cursor.show>", 251 - ] 252 - `; 253 - 254 - exports[`multiline (isCI = false) > renders submitted value 1`] = ` 255 - [ 256 - "<cursor.hide>", 257 - "<dim>│</fg> 258 - <cyan>◆</fg> foo 259 - <cyan>│</fg> _ 260 - <cyan>└</fg> 261 - ", 262 - "<cursor.backward count=999><cursor.up count=4>", 263 - "<cursor.down count=2>", 264 - "<erase.line><cursor.left count=1>", 265 - "<cyan>│</fg> x█", 266 - "<cursor.down count=2>", 267 - "<cursor.backward count=999><cursor.up count=4>", 268 - "<cursor.down count=2>", 269 - "<erase.line><cursor.left count=1>", 270 - "<cyan>│</fg> xy█", 271 - "<cursor.down count=2>", 272 - "<cursor.backward count=999><cursor.up count=4>", 273 - "<cursor.down count=2>", 274 - "<erase.down>", 275 - "<cyan>│</fg> xy 276 - <cyan>│</fg> █ 277 - <cyan>└</fg> 278 - ", 279 - "<cursor.backward count=999><cursor.up count=5>", 280 - "<cursor.down count=1>", 281 - "<erase.down>", 282 - "<green>◇</fg> foo 283 - <dim>│</fg> <dim>xy</bold>", 284 - " 285 - ", 286 - "<cursor.show>", 287 - ] 288 - `; 289 - 290 - exports[`multiline (isCI = false) > validation errors render and clear (using Error) 1`] = ` 291 - [ 292 - "<cursor.hide>", 293 - "<dim>│</fg> 294 - <cyan>◆</fg> foo 295 - <cyan>│</fg> _ 296 - <cyan>└</fg> 297 - ", 298 - "<cursor.backward count=999><cursor.up count=4>", 299 - "<cursor.down count=2>", 300 - "<erase.line><cursor.left count=1>", 301 - "<cyan>│</fg> x█", 302 - "<cursor.down count=2>", 303 - "<cursor.backward count=999><cursor.up count=4>", 304 - "<cursor.down count=2>", 305 - "<erase.down>", 306 - "<cyan>│</fg> x 307 - <cyan>│</fg> █ 308 - <cyan>└</fg> 309 - ", 310 - "<cursor.backward count=999><cursor.up count=5>", 311 - "<cursor.down count=1>", 312 - "<erase.down>", 313 - "<yellow>▲</fg> foo 314 - <yellow>│</fg> x█ 315 - <yellow>└</fg> <yellow>should be xy</fg> 316 - ", 317 - "<cursor.backward count=999><cursor.up count=4>", 318 - "<cursor.down count=1>", 319 - "<erase.down>", 320 - "<cyan>◆</fg> foo 321 - <cyan>│</fg> xy█ 322 - <cyan>└</fg> 323 - ", 324 - "<cursor.backward count=999><cursor.up count=4>", 325 - "<cursor.down count=2>", 326 - "<erase.down>", 327 - "<cyan>│</fg> xy 328 - <cyan>│</fg> █ 329 - <cyan>└</fg> 330 - ", 331 - "<cursor.backward count=999><cursor.up count=5>", 332 - "<cursor.down count=1>", 333 - "<erase.down>", 334 - "<green>◇</fg> foo 335 - <dim>│</fg> <dim>xy</bold>", 336 - " 337 - ", 338 - "<cursor.show>", 339 - ] 340 - `; 341 - 342 - exports[`multiline (isCI = false) > validation errors render and clear 1`] = ` 343 - [ 344 - "<cursor.hide>", 345 - "<dim>│</fg> 346 - <cyan>◆</fg> foo 347 - <cyan>│</fg> _ 348 - <cyan>└</fg> 349 - ", 350 - "<cursor.backward count=999><cursor.up count=4>", 351 - "<cursor.down count=2>", 352 - "<erase.line><cursor.left count=1>", 353 - "<cyan>│</fg> x█", 354 - "<cursor.down count=2>", 355 - "<cursor.backward count=999><cursor.up count=4>", 356 - "<cursor.down count=2>", 357 - "<erase.down>", 358 - "<cyan>│</fg> x 359 - <cyan>│</fg> █ 360 - <cyan>└</fg> 361 - ", 362 - "<cursor.backward count=999><cursor.up count=5>", 363 - "<cursor.down count=1>", 364 - "<erase.down>", 365 - "<yellow>▲</fg> foo 366 - <yellow>│</fg> x█ 367 - <yellow>└</fg> <yellow>should be xy</fg> 368 - ", 369 - "<cursor.backward count=999><cursor.up count=4>", 370 - "<cursor.down count=1>", 371 - "<erase.down>", 372 - "<cyan>◆</fg> foo 373 - <cyan>│</fg> xy█ 374 - <cyan>└</fg> 375 - ", 376 - "<cursor.backward count=999><cursor.up count=4>", 377 - "<cursor.down count=2>", 378 - "<erase.down>", 379 - "<cyan>│</fg> xy 380 - <cyan>│</fg> █ 381 - <cyan>└</fg> 382 - ", 383 - "<cursor.backward count=999><cursor.up count=5>", 384 - "<cursor.down count=1>", 385 - "<erase.down>", 386 - "<green>◇</fg> foo 387 - <dim>│</fg> <dim>xy</bold>", 388 - " 389 - ", 390 - "<cursor.show>", 391 - ] 392 - `; 393 - 394 - exports[`multiline (isCI = false) > withGuide: false removes guide 1`] = ` 395 - [ 396 - "<cursor.hide>", 397 - "<cyan>◆</fg> foo 398 - _ 399 - 400 - ", 401 - "<cursor.backward count=999><cursor.up count=3>", 402 - "<cursor.down count=1>", 403 - "<erase.down>", 404 - " 405 - 406 - 407 - ", 408 - "<cursor.backward count=999><cursor.up count=4>", 409 - "<erase.down>", 410 - "<green>◇</fg> foo 411 - ", 412 - " 413 - ", 414 - "<cursor.show>", 415 - ] 416 - `; 417 - 418 - exports[`multiline (isCI = true) > can be aborted by a signal 1`] = ` 419 - [ 420 - "<cursor.hide>", 421 - "<dim>│</fg> 422 - <cyan>◆</fg> foo 423 - <cyan>│</fg> _ 424 - <cyan>└</fg> 425 - ", 426 - " 427 - ", 428 - "<cursor.show>", 429 - ] 430 - `; 431 - 432 - exports[`multiline (isCI = true) > can cancel 1`] = ` 433 - [ 434 - "<cursor.hide>", 435 - "<dim>│</fg> 436 - <cyan>◆</fg> foo 437 - <cyan>│</fg> _ 438 - <cyan>└</fg> 439 - ", 440 - "<cursor.backward count=999><cursor.up count=4>", 441 - "<cursor.down count=1>", 442 - "<erase.down>", 443 - "<red>■</fg> foo 444 - <dim>│</fg> <dim>escape</bold>", 445 - " 446 - ", 447 - "<cursor.show>", 448 - ] 449 - `; 450 - 451 - exports[`multiline (isCI = true) > defaultValue sets the value but does not render 1`] = ` 452 - [ 453 - "<cursor.hide>", 454 - "<dim>│</fg> 455 - <cyan>◆</fg> foo 456 - <cyan>│</fg> _ 457 - <cyan>└</fg> 458 - ", 459 - "<cursor.backward count=999><cursor.up count=4>", 460 - "<cursor.down count=2>", 461 - "<erase.down>", 462 - "<cyan>│</fg> 463 - <cyan>│</fg> █ 464 - <cyan>└</fg> 465 - ", 466 - "<cursor.backward count=999><cursor.up count=5>", 467 - "<cursor.down count=1>", 468 - "<erase.down>", 469 - "<green>◇</fg> foo 470 - <dim>│</fg> <dim>bar</bold>", 471 - " 472 - ", 473 - "<cursor.show>", 474 - ] 475 - `; 476 - 477 - exports[`multiline (isCI = true) > empty string when no value and no default 1`] = ` 478 - [ 479 - "<cursor.hide>", 480 - "<dim>│</fg> 481 - <cyan>◆</fg> foo 482 - <cyan>│</fg>  <dim> (submit to use default)</bold> 483 - <cyan>└</fg> 484 - ", 485 - "<cursor.backward count=999><cursor.up count=4>", 486 - "<cursor.down count=2>", 487 - "<erase.down>", 488 - "<cyan>│</fg> 489 - <cyan>│</fg> █ 490 - <cyan>└</fg> 491 - ", 492 - "<cursor.backward count=999><cursor.up count=5>", 493 - "<cursor.down count=1>", 494 - "<erase.down>", 495 - "<green>◇</fg> foo 496 - <dim>│</fg> <dim></bold>", 497 - " 498 - ", 499 - "<cursor.show>", 500 - ] 501 - `; 502 - 503 - exports[`multiline (isCI = true) > global withGuide: false removes guide 1`] = ` 504 - [ 505 - "<cursor.hide>", 506 - "<cyan>◆</fg> foo 507 - _ 508 - 509 - ", 510 - "<cursor.backward count=999><cursor.up count=3>", 511 - "<cursor.down count=1>", 512 - "<erase.down>", 513 - " 514 - 515 - 516 - ", 517 - "<cursor.backward count=999><cursor.up count=4>", 518 - "<erase.down>", 519 - "<green>◇</fg> foo 520 - ", 521 - " 522 - ", 523 - "<cursor.show>", 524 - ] 525 - `; 526 - 527 - exports[`multiline (isCI = true) > placeholder is not used as value when pressing enter 1`] = ` 528 - [ 529 - "<cursor.hide>", 530 - "<dim>│</fg> 531 - <cyan>◆</fg> foo 532 - <cyan>│</fg>  <dim> (submit to use default)</bold> 533 - <cyan>└</fg> 534 - ", 535 - "<cursor.backward count=999><cursor.up count=4>", 536 - "<cursor.down count=2>", 537 - "<erase.down>", 538 - "<cyan>│</fg> 539 - <cyan>│</fg> █ 540 - <cyan>└</fg> 541 - ", 542 - "<cursor.backward count=999><cursor.up count=5>", 543 - "<cursor.down count=1>", 544 - "<erase.down>", 545 - "<green>◇</fg> foo 546 - <dim>│</fg> <dim>default-value</bold>", 547 - " 548 - ", 549 - "<cursor.show>", 550 - ] 551 - `; 552 - 553 - exports[`multiline (isCI = true) > renders cancelled value if one set 1`] = ` 554 - [ 555 - "<cursor.hide>", 556 - "<dim>│</fg> 557 - <cyan>◆</fg> foo 558 - <cyan>│</fg> _ 559 - <cyan>└</fg> 560 - ", 561 - "<cursor.backward count=999><cursor.up count=4>", 562 - "<cursor.down count=2>", 563 - "<erase.line><cursor.left count=1>", 564 - "<cyan>│</fg> x█", 565 - "<cursor.down count=2>", 566 - "<cursor.backward count=999><cursor.up count=4>", 567 - "<cursor.down count=2>", 568 - "<erase.line><cursor.left count=1>", 569 - "<cyan>│</fg> xy█", 570 - "<cursor.down count=2>", 571 - "<cursor.backward count=999><cursor.up count=4>", 572 - "<cursor.down count=1>", 573 - "<erase.down>", 574 - "<red>■</fg> foo 575 - <dim>│</fg> <dim>xy</bold>", 576 - " 577 - ", 578 - "<cursor.show>", 579 - ] 580 - `; 581 - 582 - exports[`multiline (isCI = true) > renders message 1`] = ` 583 - [ 584 - "<cursor.hide>", 585 - "<dim>│</fg> 586 - <cyan>◆</fg> foo 587 - <cyan>│</fg> _ 588 - <cyan>└</fg> 589 - ", 590 - "<cursor.backward count=999><cursor.up count=4>", 591 - "<cursor.down count=2>", 592 - "<erase.down>", 593 - "<cyan>│</fg> 594 - <cyan>│</fg> █ 595 - <cyan>└</fg> 596 - ", 597 - "<cursor.backward count=999><cursor.up count=5>", 598 - "<cursor.down count=1>", 599 - "<erase.down>", 600 - "<green>◇</fg> foo 601 - <dim>│</fg> <dim></bold>", 602 - " 603 - ", 604 - "<cursor.show>", 605 - ] 606 - `; 607 - 608 - exports[`multiline (isCI = true) > renders placeholder if set 1`] = ` 609 - [ 610 - "<cursor.hide>", 611 - "<dim>│</fg> 612 - <cyan>◆</fg> foo 613 - <cyan>│</fg> b<dim>ar</bold> 614 - <cyan>└</fg> 615 - ", 616 - "<cursor.backward count=999><cursor.up count=4>", 617 - "<cursor.down count=2>", 618 - "<erase.down>", 619 - "<cyan>│</fg> 620 - <cyan>│</fg> █ 621 - <cyan>└</fg> 622 - ", 623 - "<cursor.backward count=999><cursor.up count=5>", 624 - "<cursor.down count=1>", 625 - "<erase.down>", 626 - "<green>◇</fg> foo 627 - <dim>│</fg> <dim></bold>", 628 - " 629 - ", 630 - "<cursor.show>", 631 - ] 632 - `; 633 - 634 - exports[`multiline (isCI = true) > renders submit button 1`] = ` 635 - [ 636 - "<cursor.hide>", 637 - "<dim>│</fg> 638 - <cyan>◆</fg> foo 639 - <cyan>│</fg> _ 640 - <cyan>└</fg> 641 - <dim>[ submit ]</bold> 642 - ", 643 - "<cursor.backward count=999><cursor.up count=5>", 644 - "<cursor.down count=2>", 645 - "<erase.line><cursor.left count=1>", 646 - "<cyan>│</fg> x█", 647 - "<cursor.down count=3>", 648 - "<cursor.backward count=999><cursor.up count=5>", 649 - "<cursor.down count=2>", 650 - "<erase.line><cursor.left count=1>", 651 - "<cyan>│</fg> xy█", 652 - "<cursor.down count=3>", 653 - "<cursor.backward count=999><cursor.up count=5>", 654 - "<cursor.down count=4>", 655 - "<erase.line><cursor.left count=1>", 656 - " <cyan>[ submit ]</fg>", 657 - "<cursor.down count=1>", 658 - "<cursor.backward count=999><cursor.up count=5>", 659 - "<cursor.down count=1>", 660 - "<erase.down>", 661 - "<green>◇</fg> foo 662 - <dim>│</fg> <dim>xy</bold>", 663 - " 664 - ", 665 - "<cursor.show>", 666 - ] 667 - `; 668 - 669 - exports[`multiline (isCI = true) > renders submitted value 1`] = ` 670 - [ 671 - "<cursor.hide>", 672 - "<dim>│</fg> 673 - <cyan>◆</fg> foo 674 - <cyan>│</fg> _ 675 - <cyan>└</fg> 676 - ", 677 - "<cursor.backward count=999><cursor.up count=4>", 678 - "<cursor.down count=2>", 679 - "<erase.line><cursor.left count=1>", 680 - "<cyan>│</fg> x█", 681 - "<cursor.down count=2>", 682 - "<cursor.backward count=999><cursor.up count=4>", 683 - "<cursor.down count=2>", 684 - "<erase.line><cursor.left count=1>", 685 - "<cyan>│</fg> xy█", 686 - "<cursor.down count=2>", 687 - "<cursor.backward count=999><cursor.up count=4>", 688 - "<cursor.down count=2>", 689 - "<erase.down>", 690 - "<cyan>│</fg> xy 691 - <cyan>│</fg> █ 692 - <cyan>└</fg> 693 - ", 694 - "<cursor.backward count=999><cursor.up count=5>", 695 - "<cursor.down count=1>", 696 - "<erase.down>", 697 - "<green>◇</fg> foo 698 - <dim>│</fg> <dim>xy</bold>", 699 - " 700 - ", 701 - "<cursor.show>", 702 - ] 703 - `; 704 - 705 - exports[`multiline (isCI = true) > validation errors render and clear (using Error) 1`] = ` 706 - [ 707 - "<cursor.hide>", 708 - "<dim>│</fg> 709 - <cyan>◆</fg> foo 710 - <cyan>│</fg> _ 711 - <cyan>└</fg> 712 - ", 713 - "<cursor.backward count=999><cursor.up count=4>", 714 - "<cursor.down count=2>", 715 - "<erase.line><cursor.left count=1>", 716 - "<cyan>│</fg> x█", 717 - "<cursor.down count=2>", 718 - "<cursor.backward count=999><cursor.up count=4>", 719 - "<cursor.down count=2>", 720 - "<erase.down>", 721 - "<cyan>│</fg> x 722 - <cyan>│</fg> █ 723 - <cyan>└</fg> 724 - ", 725 - "<cursor.backward count=999><cursor.up count=5>", 726 - "<cursor.down count=1>", 727 - "<erase.down>", 728 - "<yellow>▲</fg> foo 729 - <yellow>│</fg> x█ 730 - <yellow>└</fg> <yellow>should be xy</fg> 731 - ", 732 - "<cursor.backward count=999><cursor.up count=4>", 733 - "<cursor.down count=1>", 734 - "<erase.down>", 735 - "<cyan>◆</fg> foo 736 - <cyan>│</fg> xy█ 737 - <cyan>└</fg> 738 - ", 739 - "<cursor.backward count=999><cursor.up count=4>", 740 - "<cursor.down count=2>", 741 - "<erase.down>", 742 - "<cyan>│</fg> xy 743 - <cyan>│</fg> █ 744 - <cyan>└</fg> 745 - ", 746 - "<cursor.backward count=999><cursor.up count=5>", 747 - "<cursor.down count=1>", 748 - "<erase.down>", 749 - "<green>◇</fg> foo 750 - <dim>│</fg> <dim>xy</bold>", 751 - " 752 - ", 753 - "<cursor.show>", 754 - ] 755 - `; 756 - 757 - exports[`multiline (isCI = true) > validation errors render and clear 1`] = ` 758 - [ 759 - "<cursor.hide>", 760 - "<dim>│</fg> 761 - <cyan>◆</fg> foo 762 - <cyan>│</fg> _ 763 - <cyan>└</fg> 764 - ", 765 - "<cursor.backward count=999><cursor.up count=4>", 766 - "<cursor.down count=2>", 767 - "<erase.line><cursor.left count=1>", 768 - "<cyan>│</fg> x█", 769 - "<cursor.down count=2>", 770 - "<cursor.backward count=999><cursor.up count=4>", 771 - "<cursor.down count=2>", 772 - "<erase.down>", 773 - "<cyan>│</fg> x 774 - <cyan>│</fg> █ 775 - <cyan>└</fg> 776 - ", 777 - "<cursor.backward count=999><cursor.up count=5>", 778 - "<cursor.down count=1>", 779 - "<erase.down>", 780 - "<yellow>▲</fg> foo 781 - <yellow>│</fg> x█ 782 - <yellow>└</fg> <yellow>should be xy</fg> 783 - ", 784 - "<cursor.backward count=999><cursor.up count=4>", 785 - "<cursor.down count=1>", 786 - "<erase.down>", 787 - "<cyan>◆</fg> foo 788 - <cyan>│</fg> xy█ 789 - <cyan>└</fg> 790 - ", 791 - "<cursor.backward count=999><cursor.up count=4>", 792 - "<cursor.down count=2>", 793 - "<erase.down>", 794 - "<cyan>│</fg> xy 795 - <cyan>│</fg> █ 796 - <cyan>└</fg> 797 - ", 798 - "<cursor.backward count=999><cursor.up count=5>", 799 - "<cursor.down count=1>", 800 - "<erase.down>", 801 - "<green>◇</fg> foo 802 - <dim>│</fg> <dim>xy</bold>", 803 - " 804 - ", 805 - "<cursor.show>", 806 - ] 807 - `; 808 - 809 - exports[`multiline (isCI = true) > withGuide: false removes guide 1`] = ` 810 - [ 811 - "<cursor.hide>", 812 - "<cyan>◆</fg> foo 813 - _ 814 - 815 - ", 816 - "<cursor.backward count=999><cursor.up count=3>", 817 - "<cursor.down count=1>", 818 - "<erase.down>", 819 - " 820 - 821 - 822 - ", 823 - "<cursor.backward count=999><cursor.up count=4>", 824 - "<erase.down>", 825 - "<green>◇</fg> foo 826 - ", 827 - " 828 - ", 829 - "<cursor.show>", 830 - ] 831 - `;
-1561
packages/prompts/test/__snapshots__/multi-select.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`multiselect (isCI = false) > can be aborted by a signal 1`] = ` 4 - [ 5 - "<cursor.hide>", 6 - "<dim>│</fg> 7 - <cyan>◆</fg> foo 8 - <cyan>│</fg> <cyan>◻</fg> opt0 9 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 10 - <cyan>└</fg> 11 - ", 12 - " 13 - ", 14 - "<cursor.show>", 15 - ] 16 - `; 17 - 18 - exports[`multiselect (isCI = false) > can cancel 1`] = ` 19 - [ 20 - "<cursor.hide>", 21 - "<dim>│</fg> 22 - <cyan>◆</fg> foo 23 - <cyan>│</fg> <cyan>◻</fg> opt0 24 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 25 - <cyan>└</fg> 26 - ", 27 - "<cursor.backward count=999><cursor.up count=5>", 28 - "<cursor.down count=1>", 29 - "<erase.down>", 30 - "<red>■</fg> foo 31 - <dim>│</fg>", 32 - " 33 - ", 34 - "<cursor.show>", 35 - ] 36 - `; 37 - 38 - exports[`multiselect (isCI = false) > can render option hints 1`] = ` 39 - [ 40 - "<cursor.hide>", 41 - "<dim>│</fg> 42 - <cyan>◆</fg> foo 43 - <cyan>│</fg> <cyan>◻</fg> opt0 <dim>(Hint 0)</bold> 44 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 45 - <cyan>└</fg> 46 - ", 47 - "<cursor.backward count=999><cursor.up count=5>", 48 - "<cursor.down count=2>", 49 - "<erase.line><cursor.left count=1>", 50 - "<cyan>│</fg> <green>◼</fg> opt0 <dim>(Hint 0)</bold>", 51 - "<cursor.down count=3>", 52 - "<cursor.backward count=999><cursor.up count=5>", 53 - "<cursor.down count=1>", 54 - "<erase.down>", 55 - "<green>◇</fg> foo 56 - <dim>│</fg> <dim>opt0</bold>", 57 - " 58 - ", 59 - "<cursor.show>", 60 - ] 61 - `; 62 - 63 - exports[`multiselect (isCI = false) > can set cursorAt to preselect an option 1`] = ` 64 - [ 65 - "<cursor.hide>", 66 - "<dim>│</fg> 67 - <cyan>◆</fg> foo 68 - <cyan>│</fg> <dim>◻</bold> <dim>opt0</bold> 69 - <cyan>│</fg> <cyan>◻</fg> opt1 70 - <cyan>└</fg> 71 - ", 72 - "<cursor.backward count=999><cursor.up count=5>", 73 - "<cursor.down count=3>", 74 - "<erase.line><cursor.left count=1>", 75 - "<cyan>│</fg> <green>◼</fg> opt1", 76 - "<cursor.down count=2>", 77 - "<cursor.backward count=999><cursor.up count=5>", 78 - "<cursor.down count=1>", 79 - "<erase.down>", 80 - "<green>◇</fg> foo 81 - <dim>│</fg> <dim>opt1</bold>", 82 - " 83 - ", 84 - "<cursor.show>", 85 - ] 86 - `; 87 - 88 - exports[`multiselect (isCI = false) > can set custom labels 1`] = ` 89 - [ 90 - "<cursor.hide>", 91 - "<dim>│</fg> 92 - <cyan>◆</fg> foo 93 - <cyan>│</fg> <cyan>◻</fg> Option 0 94 - <cyan>│</fg> <dim>◻</bold> <dim>Option 1</bold> 95 - <cyan>└</fg> 96 - ", 97 - "<cursor.backward count=999><cursor.up count=5>", 98 - "<cursor.down count=2>", 99 - "<erase.line><cursor.left count=1>", 100 - "<cyan>│</fg> <green>◼</fg> Option 0", 101 - "<cursor.down count=3>", 102 - "<cursor.backward count=999><cursor.up count=5>", 103 - "<cursor.down count=1>", 104 - "<erase.down>", 105 - "<green>◇</fg> foo 106 - <dim>│</fg> <dim>Option 0</bold>", 107 - " 108 - ", 109 - "<cursor.show>", 110 - ] 111 - `; 112 - 113 - exports[`multiselect (isCI = false) > can set initial values 1`] = ` 114 - [ 115 - "<cursor.hide>", 116 - "<dim>│</fg> 117 - <cyan>◆</fg> foo 118 - <cyan>│</fg> <cyan>◻</fg> opt0 119 - <cyan>│</fg> <green>◼</fg> <dim>opt1</bold> 120 - <cyan>└</fg> 121 - ", 122 - "<cursor.backward count=999><cursor.up count=5>", 123 - "<cursor.down count=1>", 124 - "<erase.down>", 125 - "<green>◇</fg> foo 126 - <dim>│</fg> <dim>opt1</bold>", 127 - " 128 - ", 129 - "<cursor.show>", 130 - ] 131 - `; 132 - 133 - exports[`multiselect (isCI = false) > can submit without selection when required = false 1`] = ` 134 - [ 135 - "<cursor.hide>", 136 - "<dim>│</fg> 137 - <cyan>◆</fg> foo 138 - <cyan>│</fg> <cyan>◻</fg> opt0 139 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 140 - <cyan>└</fg> 141 - ", 142 - "<cursor.backward count=999><cursor.up count=5>", 143 - "<cursor.down count=1>", 144 - "<erase.down>", 145 - "<green>◇</fg> foo 146 - <dim>│</fg> <dim>none</bold>", 147 - " 148 - ", 149 - "<cursor.show>", 150 - ] 151 - `; 152 - 153 - exports[`multiselect (isCI = false) > global withGuide: false removes guide 1`] = ` 154 - [ 155 - "<cursor.hide>", 156 - "<cyan>◆</fg> foo 157 - <cyan>◻</fg> opt0 158 - <dim>◻</bold> <dim>opt1</bold> 159 - 160 - ", 161 - "<cursor.backward count=999><cursor.up count=4>", 162 - "<cursor.down count=1>", 163 - "<erase.line><cursor.left count=1>", 164 - "<green>◼</fg> opt0", 165 - "<cursor.down count=3>", 166 - "<cursor.backward count=999><cursor.up count=4>", 167 - "<erase.down>", 168 - "<green>◇</fg> foo 169 - <dim>opt0</bold>", 170 - " 171 - ", 172 - "<cursor.show>", 173 - ] 174 - `; 175 - 176 - exports[`multiselect (isCI = false) > maxItems renders a sliding window 1`] = ` 177 - [ 178 - "<cursor.hide>", 179 - "<dim>│</fg> 180 - <cyan>◆</fg> foo 181 - <cyan>│</fg> <cyan>◻</fg> opt0 182 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 183 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 184 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 185 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 186 - <cyan>│</fg> <dim>...</bold> 187 - <cyan>└</fg> 188 - ", 189 - "<cursor.backward count=999><cursor.up count=9>", 190 - "<cursor.down count=2>", 191 - "<erase.down>", 192 - "<cyan>│</fg> <dim>◻</bold> <dim>opt0</bold> 193 - <cyan>│</fg> <cyan>◻</fg> opt1 194 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 195 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 196 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 197 - <cyan>│</fg> <dim>...</bold> 198 - <cyan>└</fg> 199 - ", 200 - "<cursor.backward count=999><cursor.up count=9>", 201 - "<cursor.down count=3>", 202 - "<erase.down>", 203 - "<cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 204 - <cyan>│</fg> <cyan>◻</fg> opt2 205 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 206 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 207 - <cyan>│</fg> <dim>...</bold> 208 - <cyan>└</fg> 209 - ", 210 - "<cursor.backward count=999><cursor.up count=9>", 211 - "<cursor.down count=4>", 212 - "<erase.down>", 213 - "<cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 214 - <cyan>│</fg> <cyan>◻</fg> opt3 215 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 216 - <cyan>│</fg> <dim>...</bold> 217 - <cyan>└</fg> 218 - ", 219 - "<cursor.backward count=999><cursor.up count=9>", 220 - "<cursor.down count=2>", 221 - "<erase.down>", 222 - "<cyan>│</fg> <dim>...</bold> 223 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 224 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 225 - <cyan>│</fg> <cyan>◻</fg> opt4 226 - <cyan>│</fg> <dim>◻</bold> <dim>opt5</bold> 227 - <cyan>│</fg> <dim>...</bold> 228 - <cyan>└</fg> 229 - ", 230 - "<cursor.backward count=999><cursor.up count=9>", 231 - "<cursor.down count=3>", 232 - "<erase.down>", 233 - "<cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 234 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 235 - <cyan>│</fg> <cyan>◻</fg> opt5 236 - <cyan>│</fg> <dim>◻</bold> <dim>opt6</bold> 237 - <cyan>│</fg> <dim>...</bold> 238 - <cyan>└</fg> 239 - ", 240 - "<cursor.backward count=999><cursor.up count=9>", 241 - "<cursor.down count=3>", 242 - "<erase.down>", 243 - "<cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 244 - <cyan>│</fg> <dim>◻</bold> <dim>opt5</bold> 245 - <cyan>│</fg> <cyan>◻</fg> opt6 246 - <cyan>│</fg> <dim>◻</bold> <dim>opt7</bold> 247 - <cyan>│</fg> <dim>...</bold> 248 - <cyan>└</fg> 249 - ", 250 - "<cursor.backward count=999><cursor.up count=9>", 251 - "<cursor.down count=5>", 252 - "<erase.line><cursor.left count=1>", 253 - "<cyan>│</fg> <green>◼</fg> opt6", 254 - "<cursor.down count=4>", 255 - "<cursor.backward count=999><cursor.up count=9>", 256 - "<cursor.down count=1>", 257 - "<erase.down>", 258 - "<green>◇</fg> foo 259 - <dim>│</fg> <dim>opt6</bold>", 260 - " 261 - ", 262 - "<cursor.show>", 263 - ] 264 - `; 265 - 266 - exports[`multiselect (isCI = false) > renders disabled options 1`] = ` 267 - [ 268 - "<cursor.hide>", 269 - "<dim>│</fg> 270 - <cyan>◆</fg> foo 271 - <cyan>│</fg> <dim>◻</fg> <dim>opt0</fg> 272 - <cyan>│</fg> <cyan>◻</fg> opt1 273 - <cyan>│</fg> <dim>◻</fg> <dim>opt2</fg> <dim>(Hint 2)</bold> 274 - <cyan>└</fg> 275 - ", 276 - "<cursor.backward count=999><cursor.up count=6>", 277 - "<cursor.down count=3>", 278 - "<erase.line><cursor.left count=1>", 279 - "<cyan>│</fg> <green>◼</fg> opt1", 280 - "<cursor.down count=3>", 281 - "<cursor.backward count=999><cursor.up count=6>", 282 - "<cursor.down count=1>", 283 - "<erase.down>", 284 - "<green>◇</fg> foo 285 - <dim>│</fg> <dim>opt1</bold>", 286 - " 287 - ", 288 - "<cursor.show>", 289 - ] 290 - `; 291 - 292 - exports[`multiselect (isCI = false) > renders message 1`] = ` 293 - [ 294 - "<cursor.hide>", 295 - "<dim>│</fg> 296 - <cyan>◆</fg> foo 297 - <cyan>│</fg> <cyan>◻</fg> opt0 298 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 299 - <cyan>└</fg> 300 - ", 301 - "<cursor.backward count=999><cursor.up count=5>", 302 - "<cursor.down count=2>", 303 - "<erase.line><cursor.left count=1>", 304 - "<cyan>│</fg> <green>◼</fg> opt0", 305 - "<cursor.down count=3>", 306 - "<cursor.backward count=999><cursor.up count=5>", 307 - "<cursor.down count=1>", 308 - "<erase.down>", 309 - "<green>◇</fg> foo 310 - <dim>│</fg> <dim>opt0</bold>", 311 - " 312 - ", 313 - "<cursor.show>", 314 - ] 315 - `; 316 - 317 - exports[`multiselect (isCI = false) > renders multiple cancelled values 1`] = ` 318 - [ 319 - "<cursor.hide>", 320 - "<dim>│</fg> 321 - <cyan>◆</fg> foo 322 - <cyan>│</fg> <cyan>◻</fg> opt0 323 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 324 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 325 - <cyan>└</fg> 326 - ", 327 - "<cursor.backward count=999><cursor.up count=6>", 328 - "<cursor.down count=2>", 329 - "<erase.line><cursor.left count=1>", 330 - "<cyan>│</fg> <green>◼</fg> opt0", 331 - "<cursor.down count=4>", 332 - "<cursor.backward count=999><cursor.up count=6>", 333 - "<cursor.down count=2>", 334 - "<erase.down>", 335 - "<cyan>│</fg> <green>◼</fg> <dim>opt0</bold> 336 - <cyan>│</fg> <cyan>◻</fg> opt1 337 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 338 - <cyan>└</fg> 339 - ", 340 - "<cursor.backward count=999><cursor.up count=6>", 341 - "<cursor.down count=3>", 342 - "<erase.line><cursor.left count=1>", 343 - "<cyan>│</fg> <green>◼</fg> opt1", 344 - "<cursor.down count=3>", 345 - "<cursor.backward count=999><cursor.up count=6>", 346 - "<cursor.down count=1>", 347 - "<erase.down>", 348 - "<red>■</fg> foo 349 - <dim>│</fg> <dim>opt0</bold><dim>, </bold><dim>opt1</bold> 350 - <dim>│</fg>", 351 - " 352 - ", 353 - "<cursor.show>", 354 - ] 355 - `; 356 - 357 - exports[`multiselect (isCI = false) > renders multiple selected options 1`] = ` 358 - [ 359 - "<cursor.hide>", 360 - "<dim>│</fg> 361 - <cyan>◆</fg> foo 362 - <cyan>│</fg> <cyan>◻</fg> opt0 363 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 364 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 365 - <cyan>└</fg> 366 - ", 367 - "<cursor.backward count=999><cursor.up count=6>", 368 - "<cursor.down count=2>", 369 - "<erase.line><cursor.left count=1>", 370 - "<cyan>│</fg> <green>◼</fg> opt0", 371 - "<cursor.down count=4>", 372 - "<cursor.backward count=999><cursor.up count=6>", 373 - "<cursor.down count=2>", 374 - "<erase.down>", 375 - "<cyan>│</fg> <green>◼</fg> <dim>opt0</bold> 376 - <cyan>│</fg> <cyan>◻</fg> opt1 377 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 378 - <cyan>└</fg> 379 - ", 380 - "<cursor.backward count=999><cursor.up count=6>", 381 - "<cursor.down count=3>", 382 - "<erase.line><cursor.left count=1>", 383 - "<cyan>│</fg> <green>◼</fg> opt1", 384 - "<cursor.down count=3>", 385 - "<cursor.backward count=999><cursor.up count=6>", 386 - "<cursor.down count=3>", 387 - "<erase.down>", 388 - "<cyan>│</fg> <green>◼</fg> <dim>opt1</bold> 389 - <cyan>│</fg> <cyan>◻</fg> opt2 390 - <cyan>└</fg> 391 - ", 392 - "<cursor.backward count=999><cursor.up count=6>", 393 - "<cursor.down count=1>", 394 - "<erase.down>", 395 - "<green>◇</fg> foo 396 - <dim>│</fg> <dim>opt0</bold><dim>, </bold><dim>opt1</bold>", 397 - " 398 - ", 399 - "<cursor.show>", 400 - ] 401 - `; 402 - 403 - exports[`multiselect (isCI = false) > renders validation errors 1`] = ` 404 - [ 405 - "<cursor.hide>", 406 - "<dim>│</fg> 407 - <cyan>◆</fg> foo 408 - <cyan>│</fg> <cyan>◻</fg> opt0 409 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 410 - <cyan>└</fg> 411 - ", 412 - "<cursor.backward count=999><cursor.up count=5>", 413 - "<cursor.down count=1>", 414 - "<erase.down>", 415 - "<yellow>▲</fg> foo 416 - <yellow>│</fg> <cyan>◻</fg> opt0 417 - <yellow>│</fg> <dim>◻</bold> <dim>opt1</bold> 418 - <yellow>└</fg> <yellow>Please select at least one option.</fg> 419 - </><dim>Press <dim><bg:white> space </bg></fg> to select, <dim><bg:white> enter </bg></fg> to submit</bold></> 420 - ", 421 - "<cursor.backward count=999><cursor.up count=6>", 422 - "<cursor.down count=1>", 423 - "<erase.down>", 424 - "<cyan>◆</fg> foo 425 - <cyan>│</fg> <green>◼</fg> opt0 426 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 427 - <cyan>└</fg> 428 - ", 429 - "<cursor.backward count=999><cursor.up count=5>", 430 - "<cursor.down count=1>", 431 - "<erase.down>", 432 - "<green>◇</fg> foo 433 - <dim>│</fg> <dim>opt0</bold>", 434 - " 435 - ", 436 - "<cursor.show>", 437 - ] 438 - `; 439 - 440 - exports[`multiselect (isCI = false) > shows hints for all selected options 1`] = ` 441 - [ 442 - "<cursor.hide>", 443 - "<dim>│</fg> 444 - <cyan>◆</fg> foo 445 - <cyan>│</fg> <green>◼</fg> opt0 <dim>(Hint 0)</bold> 446 - <cyan>│</fg> <green>◼</fg> <dim>opt1</bold> <dim>(Hint 1)</bold> 447 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 448 - <cyan>└</fg> 449 - ", 450 - "<cursor.backward count=999><cursor.up count=6>", 451 - "<cursor.down count=2>", 452 - "<erase.down>", 453 - "<cyan>│</fg> <green>◼</fg> <dim>opt0</bold> <dim>(Hint 0)</bold> 454 - <cyan>│</fg> <green>◼</fg> opt1 <dim>(Hint 1)</bold> 455 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 456 - <cyan>└</fg> 457 - ", 458 - "<cursor.backward count=999><cursor.up count=6>", 459 - "<cursor.down count=3>", 460 - "<erase.down>", 461 - "<cyan>│</fg> <green>◼</fg> <dim>opt1</bold> <dim>(Hint 1)</bold> 462 - <cyan>│</fg> <cyan>◻</fg> opt2 <dim>(Hint 2)</bold> 463 - <cyan>└</fg> 464 - ", 465 - "<cursor.backward count=999><cursor.up count=6>", 466 - "<cursor.down count=1>", 467 - "<erase.down>", 468 - "<green>◇</fg> foo 469 - <dim>│</fg> <dim>opt0</bold><dim>, </bold><dim>opt1</bold>", 470 - " 471 - ", 472 - "<cursor.show>", 473 - ] 474 - `; 475 - 476 - exports[`multiselect (isCI = false) > sliding window loops downwards 1`] = ` 477 - [ 478 - "<cursor.hide>", 479 - "<dim>│</fg> 480 - <cyan>◆</fg> foo 481 - <cyan>│</fg> <cyan>◻</fg> opt0 482 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 483 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 484 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 485 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 486 - <cyan>│</fg> <dim>...</bold> 487 - <cyan>└</fg> 488 - ", 489 - "<cursor.backward count=999><cursor.up count=9>", 490 - "<cursor.down count=2>", 491 - "<erase.down>", 492 - "<cyan>│</fg> <dim>◻</bold> <dim>opt0</bold> 493 - <cyan>│</fg> <cyan>◻</fg> opt1 494 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 495 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 496 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 497 - <cyan>│</fg> <dim>...</bold> 498 - <cyan>└</fg> 499 - ", 500 - "<cursor.backward count=999><cursor.up count=9>", 501 - "<cursor.down count=3>", 502 - "<erase.down>", 503 - "<cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 504 - <cyan>│</fg> <cyan>◻</fg> opt2 505 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 506 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 507 - <cyan>│</fg> <dim>...</bold> 508 - <cyan>└</fg> 509 - ", 510 - "<cursor.backward count=999><cursor.up count=9>", 511 - "<cursor.down count=4>", 512 - "<erase.down>", 513 - "<cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 514 - <cyan>│</fg> <cyan>◻</fg> opt3 515 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 516 - <cyan>│</fg> <dim>...</bold> 517 - <cyan>└</fg> 518 - ", 519 - "<cursor.backward count=999><cursor.up count=9>", 520 - "<cursor.down count=2>", 521 - "<erase.down>", 522 - "<cyan>│</fg> <dim>...</bold> 523 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 524 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 525 - <cyan>│</fg> <cyan>◻</fg> opt4 526 - <cyan>│</fg> <dim>◻</bold> <dim>opt5</bold> 527 - <cyan>│</fg> <dim>...</bold> 528 - <cyan>└</fg> 529 - ", 530 - "<cursor.backward count=999><cursor.up count=9>", 531 - "<cursor.down count=3>", 532 - "<erase.down>", 533 - "<cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 534 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 535 - <cyan>│</fg> <cyan>◻</fg> opt5 536 - <cyan>│</fg> <dim>◻</bold> <dim>opt6</bold> 537 - <cyan>│</fg> <dim>...</bold> 538 - <cyan>└</fg> 539 - ", 540 - "<cursor.backward count=999><cursor.up count=9>", 541 - "<cursor.down count=3>", 542 - "<erase.down>", 543 - "<cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 544 - <cyan>│</fg> <dim>◻</bold> <dim>opt5</bold> 545 - <cyan>│</fg> <cyan>◻</fg> opt6 546 - <cyan>│</fg> <dim>◻</bold> <dim>opt7</bold> 547 - <cyan>│</fg> <dim>...</bold> 548 - <cyan>└</fg> 549 - ", 550 - "<cursor.backward count=999><cursor.up count=9>", 551 - "<cursor.down count=3>", 552 - "<erase.down>", 553 - "<cyan>│</fg> <dim>◻</bold> <dim>opt5</bold> 554 - <cyan>│</fg> <dim>◻</bold> <dim>opt6</bold> 555 - <cyan>│</fg> <cyan>◻</fg> opt7 556 - <cyan>│</fg> <dim>◻</bold> <dim>opt8</bold> 557 - <cyan>│</fg> <dim>...</bold> 558 - <cyan>└</fg> 559 - ", 560 - "<cursor.backward count=999><cursor.up count=9>", 561 - "<cursor.down count=3>", 562 - "<erase.down>", 563 - "<cyan>│</fg> <dim>◻</bold> <dim>opt6</bold> 564 - <cyan>│</fg> <dim>◻</bold> <dim>opt7</bold> 565 - <cyan>│</fg> <cyan>◻</fg> opt8 566 - <cyan>│</fg> <dim>◻</bold> <dim>opt9</bold> 567 - <cyan>│</fg> <dim>...</bold> 568 - <cyan>└</fg> 569 - ", 570 - "<cursor.backward count=999><cursor.up count=9>", 571 - "<cursor.down count=3>", 572 - "<erase.down>", 573 - "<cyan>│</fg> <dim>◻</bold> <dim>opt7</bold> 574 - <cyan>│</fg> <dim>◻</bold> <dim>opt8</bold> 575 - <cyan>│</fg> <cyan>◻</fg> opt9 576 - <cyan>│</fg> <dim>◻</bold> <dim>opt10</bold> 577 - <cyan>│</fg> <dim>◻</bold> <dim>opt11</bold> 578 - <cyan>└</fg> 579 - ", 580 - "<cursor.backward count=999><cursor.up count=9>", 581 - "<cursor.down count=5>", 582 - "<erase.down>", 583 - "<cyan>│</fg> <dim>◻</bold> <dim>opt9</bold> 584 - <cyan>│</fg> <cyan>◻</fg> opt10 585 - <cyan>│</fg> <dim>◻</bold> <dim>opt11</bold> 586 - <cyan>└</fg> 587 - ", 588 - "<cursor.backward count=999><cursor.up count=9>", 589 - "<cursor.down count=6>", 590 - "<erase.down>", 591 - "<cyan>│</fg> <dim>◻</bold> <dim>opt10</bold> 592 - <cyan>│</fg> <cyan>◻</fg> opt11 593 - <cyan>└</fg> 594 - ", 595 - "<cursor.backward count=999><cursor.up count=9>", 596 - "<cursor.down count=2>", 597 - "<erase.down>", 598 - "<cyan>│</fg> <cyan>◻</fg> opt0 599 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 600 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 601 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 602 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 603 - <cyan>│</fg> <dim>...</bold> 604 - <cyan>└</fg> 605 - ", 606 - "<cursor.backward count=999><cursor.up count=9>", 607 - "<cursor.down count=2>", 608 - "<erase.line><cursor.left count=1>", 609 - "<cyan>│</fg> <green>◼</fg> opt0", 610 - "<cursor.down count=7>", 611 - "<cursor.backward count=999><cursor.up count=9>", 612 - "<cursor.down count=1>", 613 - "<erase.down>", 614 - "<green>◇</fg> foo 615 - <dim>│</fg> <dim>opt0</bold>", 616 - " 617 - ", 618 - "<cursor.show>", 619 - ] 620 - `; 621 - 622 - exports[`multiselect (isCI = false) > sliding window loops upwards 1`] = ` 623 - [ 624 - "<cursor.hide>", 625 - "<dim>│</fg> 626 - <cyan>◆</fg> foo 627 - <cyan>│</fg> <cyan>◻</fg> opt0 628 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 629 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 630 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 631 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 632 - <cyan>│</fg> <dim>...</bold> 633 - <cyan>└</fg> 634 - ", 635 - "<cursor.backward count=999><cursor.up count=9>", 636 - "<cursor.down count=2>", 637 - "<erase.down>", 638 - "<cyan>│</fg> <dim>...</bold> 639 - <cyan>│</fg> <dim>◻</bold> <dim>opt7</bold> 640 - <cyan>│</fg> <dim>◻</bold> <dim>opt8</bold> 641 - <cyan>│</fg> <dim>◻</bold> <dim>opt9</bold> 642 - <cyan>│</fg> <dim>◻</bold> <dim>opt10</bold> 643 - <cyan>│</fg> <cyan>◻</fg> opt11 644 - <cyan>└</fg> 645 - ", 646 - "<cursor.backward count=999><cursor.up count=9>", 647 - "<cursor.down count=7>", 648 - "<erase.line><cursor.left count=1>", 649 - "<cyan>│</fg> <green>◼</fg> opt11", 650 - "<cursor.down count=2>", 651 - "<cursor.backward count=999><cursor.up count=9>", 652 - "<cursor.down count=1>", 653 - "<erase.down>", 654 - "<green>◇</fg> foo 655 - <dim>│</fg> <dim>opt11</bold>", 656 - " 657 - ", 658 - "<cursor.show>", 659 - ] 660 - `; 661 - 662 - exports[`multiselect (isCI = false) > withGuide: false removes guide 1`] = ` 663 - [ 664 - "<cursor.hide>", 665 - "<cyan>◆</fg> foo 666 - <cyan>◻</fg> opt0 667 - <dim>◻</bold> <dim>opt1</bold> 668 - 669 - ", 670 - "<cursor.backward count=999><cursor.up count=4>", 671 - "<cursor.down count=1>", 672 - "<erase.line><cursor.left count=1>", 673 - "<green>◼</fg> opt0", 674 - "<cursor.down count=3>", 675 - "<cursor.backward count=999><cursor.up count=4>", 676 - "<erase.down>", 677 - "<green>◇</fg> foo 678 - <dim>opt0</bold>", 679 - " 680 - ", 681 - "<cursor.show>", 682 - ] 683 - `; 684 - 685 - exports[`multiselect (isCI = false) > wraps cancelled state with long options 1`] = ` 686 - [ 687 - "<cursor.hide>", 688 - "<dim>│</fg> 689 - <cyan>◆</fg> foo 690 - <cyan>│</fg> <cyan>◻</fg> Option 0 Option 0 Option 691 - <cyan>│</fg> 0 Option 0 Option 0 Option 692 - <cyan>│</fg> 0 Option 0 Option 0 Option 693 - <cyan>│</fg> 0 Option 0 694 - <cyan>│</fg> <dim>◻</bold> <dim>Option 1 Option 1 Option </bold> 695 - <cyan>│</fg> <dim>1 Option 1 Option 1 Option </bold> 696 - <cyan>│</fg> <dim>1 Option 1 Option 1 Option </bold> 697 - <cyan>│</fg> <dim>1 Option 1</bold> 698 - <cyan>└</fg> 699 - ", 700 - "<cursor.backward count=999><cursor.up count=11>", 701 - "<cursor.down count=2>", 702 - "<erase.line><cursor.left count=1>", 703 - "<cyan>│</fg> <green>◼</fg> Option 0 Option 0 Option ", 704 - "<cursor.down count=9>", 705 - "<cursor.backward count=999><cursor.up count=11>", 706 - "<cursor.down count=1>", 707 - "<erase.down>", 708 - "<red>■</fg> foo 709 - <dim>│</fg> <dim>Option 0 Option 0 Option 0 </bold> 710 - <dim>│</fg> <dim>Option 0 Option 0 Option 0 </bold> 711 - <dim>│</fg> <dim>Option 0 Option 0 Option 0 </bold> 712 - <dim>│</fg> <dim>Option 0</bold> 713 - <dim>│</fg>", 714 - " 715 - ", 716 - "<cursor.show>", 717 - ] 718 - `; 719 - 720 - exports[`multiselect (isCI = false) > wraps long messages 1`] = ` 721 - [ 722 - "<cursor.hide>", 723 - "<dim>│</fg> 724 - <cyan>◆</fg> foo foo foo foo foo foo foo 725 - <cyan>│</fg> foo foo foo foo foo foo 726 - <cyan>│</fg> foo foo foo foo foo foo foo 727 - <cyan>│</fg> <cyan>◻</fg> opt0 728 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 729 - <cyan>└</fg> 730 - ", 731 - "<cursor.backward count=999><cursor.up count=7>", 732 - "<cursor.down count=4>", 733 - "<erase.line><cursor.left count=1>", 734 - "<cyan>│</fg> <green>◼</fg> opt0", 735 - "<cursor.down count=3>", 736 - "<cursor.backward count=999><cursor.up count=7>", 737 - "<cursor.down count=1>", 738 - "<erase.down>", 739 - "<green>◇</fg> foo foo foo foo foo foo foo 740 - <green>│</fg> foo foo foo foo foo foo 741 - <green>│</fg> foo foo foo foo foo foo foo 742 - <dim>│</fg> <dim>opt0</bold>", 743 - " 744 - ", 745 - "<cursor.show>", 746 - ] 747 - `; 748 - 749 - exports[`multiselect (isCI = false) > wraps success state with long options 1`] = ` 750 - [ 751 - "<cursor.hide>", 752 - "<dim>│</fg> 753 - <cyan>◆</fg> foo 754 - <cyan>│</fg> <cyan>◻</fg> Option 0 Option 0 Option 755 - <cyan>│</fg> 0 Option 0 Option 0 Option 756 - <cyan>│</fg> 0 Option 0 Option 0 Option 757 - <cyan>│</fg> 0 Option 0 758 - <cyan>│</fg> <dim>◻</bold> <dim>Option 1 Option 1 Option </bold> 759 - <cyan>│</fg> <dim>1 Option 1 Option 1 Option </bold> 760 - <cyan>│</fg> <dim>1 Option 1 Option 1 Option </bold> 761 - <cyan>│</fg> <dim>1 Option 1</bold> 762 - <cyan>└</fg> 763 - ", 764 - "<cursor.backward count=999><cursor.up count=11>", 765 - "<cursor.down count=2>", 766 - "<erase.line><cursor.left count=1>", 767 - "<cyan>│</fg> <green>◼</fg> Option 0 Option 0 Option ", 768 - "<cursor.down count=9>", 769 - "<cursor.backward count=999><cursor.up count=11>", 770 - "<cursor.down count=1>", 771 - "<erase.down>", 772 - "<green>◇</fg> foo 773 - <dim>│</fg> <dim>Option 0 Option 0 Option 0 </bold> 774 - <dim>│</fg> <dim>Option 0 Option 0 Option 0 </bold> 775 - <dim>│</fg> <dim>Option 0 Option 0 Option 0 </bold> 776 - <dim>│</fg> <dim>Option 0</bold>", 777 - " 778 - ", 779 - "<cursor.show>", 780 - ] 781 - `; 782 - 783 - exports[`multiselect (isCI = true) > can be aborted by a signal 1`] = ` 784 - [ 785 - "<cursor.hide>", 786 - "<dim>│</fg> 787 - <cyan>◆</fg> foo 788 - <cyan>│</fg> <cyan>◻</fg> opt0 789 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 790 - <cyan>└</fg> 791 - ", 792 - " 793 - ", 794 - "<cursor.show>", 795 - ] 796 - `; 797 - 798 - exports[`multiselect (isCI = true) > can cancel 1`] = ` 799 - [ 800 - "<cursor.hide>", 801 - "<dim>│</fg> 802 - <cyan>◆</fg> foo 803 - <cyan>│</fg> <cyan>◻</fg> opt0 804 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 805 - <cyan>└</fg> 806 - ", 807 - "<cursor.backward count=999><cursor.up count=5>", 808 - "<cursor.down count=1>", 809 - "<erase.down>", 810 - "<red>■</fg> foo 811 - <dim>│</fg>", 812 - " 813 - ", 814 - "<cursor.show>", 815 - ] 816 - `; 817 - 818 - exports[`multiselect (isCI = true) > can render option hints 1`] = ` 819 - [ 820 - "<cursor.hide>", 821 - "<dim>│</fg> 822 - <cyan>◆</fg> foo 823 - <cyan>│</fg> <cyan>◻</fg> opt0 <dim>(Hint 0)</bold> 824 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 825 - <cyan>└</fg> 826 - ", 827 - "<cursor.backward count=999><cursor.up count=5>", 828 - "<cursor.down count=2>", 829 - "<erase.line><cursor.left count=1>", 830 - "<cyan>│</fg> <green>◼</fg> opt0 <dim>(Hint 0)</bold>", 831 - "<cursor.down count=3>", 832 - "<cursor.backward count=999><cursor.up count=5>", 833 - "<cursor.down count=1>", 834 - "<erase.down>", 835 - "<green>◇</fg> foo 836 - <dim>│</fg> <dim>opt0</bold>", 837 - " 838 - ", 839 - "<cursor.show>", 840 - ] 841 - `; 842 - 843 - exports[`multiselect (isCI = true) > can set cursorAt to preselect an option 1`] = ` 844 - [ 845 - "<cursor.hide>", 846 - "<dim>│</fg> 847 - <cyan>◆</fg> foo 848 - <cyan>│</fg> <dim>◻</bold> <dim>opt0</bold> 849 - <cyan>│</fg> <cyan>◻</fg> opt1 850 - <cyan>└</fg> 851 - ", 852 - "<cursor.backward count=999><cursor.up count=5>", 853 - "<cursor.down count=3>", 854 - "<erase.line><cursor.left count=1>", 855 - "<cyan>│</fg> <green>◼</fg> opt1", 856 - "<cursor.down count=2>", 857 - "<cursor.backward count=999><cursor.up count=5>", 858 - "<cursor.down count=1>", 859 - "<erase.down>", 860 - "<green>◇</fg> foo 861 - <dim>│</fg> <dim>opt1</bold>", 862 - " 863 - ", 864 - "<cursor.show>", 865 - ] 866 - `; 867 - 868 - exports[`multiselect (isCI = true) > can set custom labels 1`] = ` 869 - [ 870 - "<cursor.hide>", 871 - "<dim>│</fg> 872 - <cyan>◆</fg> foo 873 - <cyan>│</fg> <cyan>◻</fg> Option 0 874 - <cyan>│</fg> <dim>◻</bold> <dim>Option 1</bold> 875 - <cyan>└</fg> 876 - ", 877 - "<cursor.backward count=999><cursor.up count=5>", 878 - "<cursor.down count=2>", 879 - "<erase.line><cursor.left count=1>", 880 - "<cyan>│</fg> <green>◼</fg> Option 0", 881 - "<cursor.down count=3>", 882 - "<cursor.backward count=999><cursor.up count=5>", 883 - "<cursor.down count=1>", 884 - "<erase.down>", 885 - "<green>◇</fg> foo 886 - <dim>│</fg> <dim>Option 0</bold>", 887 - " 888 - ", 889 - "<cursor.show>", 890 - ] 891 - `; 892 - 893 - exports[`multiselect (isCI = true) > can set initial values 1`] = ` 894 - [ 895 - "<cursor.hide>", 896 - "<dim>│</fg> 897 - <cyan>◆</fg> foo 898 - <cyan>│</fg> <cyan>◻</fg> opt0 899 - <cyan>│</fg> <green>◼</fg> <dim>opt1</bold> 900 - <cyan>└</fg> 901 - ", 902 - "<cursor.backward count=999><cursor.up count=5>", 903 - "<cursor.down count=1>", 904 - "<erase.down>", 905 - "<green>◇</fg> foo 906 - <dim>│</fg> <dim>opt1</bold>", 907 - " 908 - ", 909 - "<cursor.show>", 910 - ] 911 - `; 912 - 913 - exports[`multiselect (isCI = true) > can submit without selection when required = false 1`] = ` 914 - [ 915 - "<cursor.hide>", 916 - "<dim>│</fg> 917 - <cyan>◆</fg> foo 918 - <cyan>│</fg> <cyan>◻</fg> opt0 919 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 920 - <cyan>└</fg> 921 - ", 922 - "<cursor.backward count=999><cursor.up count=5>", 923 - "<cursor.down count=1>", 924 - "<erase.down>", 925 - "<green>◇</fg> foo 926 - <dim>│</fg> <dim>none</bold>", 927 - " 928 - ", 929 - "<cursor.show>", 930 - ] 931 - `; 932 - 933 - exports[`multiselect (isCI = true) > global withGuide: false removes guide 1`] = ` 934 - [ 935 - "<cursor.hide>", 936 - "<cyan>◆</fg> foo 937 - <cyan>◻</fg> opt0 938 - <dim>◻</bold> <dim>opt1</bold> 939 - 940 - ", 941 - "<cursor.backward count=999><cursor.up count=4>", 942 - "<cursor.down count=1>", 943 - "<erase.line><cursor.left count=1>", 944 - "<green>◼</fg> opt0", 945 - "<cursor.down count=3>", 946 - "<cursor.backward count=999><cursor.up count=4>", 947 - "<erase.down>", 948 - "<green>◇</fg> foo 949 - <dim>opt0</bold>", 950 - " 951 - ", 952 - "<cursor.show>", 953 - ] 954 - `; 955 - 956 - exports[`multiselect (isCI = true) > maxItems renders a sliding window 1`] = ` 957 - [ 958 - "<cursor.hide>", 959 - "<dim>│</fg> 960 - <cyan>◆</fg> foo 961 - <cyan>│</fg> <cyan>◻</fg> opt0 962 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 963 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 964 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 965 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 966 - <cyan>│</fg> <dim>...</bold> 967 - <cyan>└</fg> 968 - ", 969 - "<cursor.backward count=999><cursor.up count=9>", 970 - "<cursor.down count=2>", 971 - "<erase.down>", 972 - "<cyan>│</fg> <dim>◻</bold> <dim>opt0</bold> 973 - <cyan>│</fg> <cyan>◻</fg> opt1 974 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 975 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 976 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 977 - <cyan>│</fg> <dim>...</bold> 978 - <cyan>└</fg> 979 - ", 980 - "<cursor.backward count=999><cursor.up count=9>", 981 - "<cursor.down count=3>", 982 - "<erase.down>", 983 - "<cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 984 - <cyan>│</fg> <cyan>◻</fg> opt2 985 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 986 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 987 - <cyan>│</fg> <dim>...</bold> 988 - <cyan>└</fg> 989 - ", 990 - "<cursor.backward count=999><cursor.up count=9>", 991 - "<cursor.down count=4>", 992 - "<erase.down>", 993 - "<cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 994 - <cyan>│</fg> <cyan>◻</fg> opt3 995 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 996 - <cyan>│</fg> <dim>...</bold> 997 - <cyan>└</fg> 998 - ", 999 - "<cursor.backward count=999><cursor.up count=9>", 1000 - "<cursor.down count=2>", 1001 - "<erase.down>", 1002 - "<cyan>│</fg> <dim>...</bold> 1003 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 1004 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 1005 - <cyan>│</fg> <cyan>◻</fg> opt4 1006 - <cyan>│</fg> <dim>◻</bold> <dim>opt5</bold> 1007 - <cyan>│</fg> <dim>...</bold> 1008 - <cyan>└</fg> 1009 - ", 1010 - "<cursor.backward count=999><cursor.up count=9>", 1011 - "<cursor.down count=3>", 1012 - "<erase.down>", 1013 - "<cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 1014 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 1015 - <cyan>│</fg> <cyan>◻</fg> opt5 1016 - <cyan>│</fg> <dim>◻</bold> <dim>opt6</bold> 1017 - <cyan>│</fg> <dim>...</bold> 1018 - <cyan>└</fg> 1019 - ", 1020 - "<cursor.backward count=999><cursor.up count=9>", 1021 - "<cursor.down count=3>", 1022 - "<erase.down>", 1023 - "<cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 1024 - <cyan>│</fg> <dim>◻</bold> <dim>opt5</bold> 1025 - <cyan>│</fg> <cyan>◻</fg> opt6 1026 - <cyan>│</fg> <dim>◻</bold> <dim>opt7</bold> 1027 - <cyan>│</fg> <dim>...</bold> 1028 - <cyan>└</fg> 1029 - ", 1030 - "<cursor.backward count=999><cursor.up count=9>", 1031 - "<cursor.down count=5>", 1032 - "<erase.line><cursor.left count=1>", 1033 - "<cyan>│</fg> <green>◼</fg> opt6", 1034 - "<cursor.down count=4>", 1035 - "<cursor.backward count=999><cursor.up count=9>", 1036 - "<cursor.down count=1>", 1037 - "<erase.down>", 1038 - "<green>◇</fg> foo 1039 - <dim>│</fg> <dim>opt6</bold>", 1040 - " 1041 - ", 1042 - "<cursor.show>", 1043 - ] 1044 - `; 1045 - 1046 - exports[`multiselect (isCI = true) > renders disabled options 1`] = ` 1047 - [ 1048 - "<cursor.hide>", 1049 - "<dim>│</fg> 1050 - <cyan>◆</fg> foo 1051 - <cyan>│</fg> <dim>◻</fg> <dim>opt0</fg> 1052 - <cyan>│</fg> <cyan>◻</fg> opt1 1053 - <cyan>│</fg> <dim>◻</fg> <dim>opt2</fg> <dim>(Hint 2)</bold> 1054 - <cyan>└</fg> 1055 - ", 1056 - "<cursor.backward count=999><cursor.up count=6>", 1057 - "<cursor.down count=3>", 1058 - "<erase.line><cursor.left count=1>", 1059 - "<cyan>│</fg> <green>◼</fg> opt1", 1060 - "<cursor.down count=3>", 1061 - "<cursor.backward count=999><cursor.up count=6>", 1062 - "<cursor.down count=1>", 1063 - "<erase.down>", 1064 - "<green>◇</fg> foo 1065 - <dim>│</fg> <dim>opt1</bold>", 1066 - " 1067 - ", 1068 - "<cursor.show>", 1069 - ] 1070 - `; 1071 - 1072 - exports[`multiselect (isCI = true) > renders message 1`] = ` 1073 - [ 1074 - "<cursor.hide>", 1075 - "<dim>│</fg> 1076 - <cyan>◆</fg> foo 1077 - <cyan>│</fg> <cyan>◻</fg> opt0 1078 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 1079 - <cyan>└</fg> 1080 - ", 1081 - "<cursor.backward count=999><cursor.up count=5>", 1082 - "<cursor.down count=2>", 1083 - "<erase.line><cursor.left count=1>", 1084 - "<cyan>│</fg> <green>◼</fg> opt0", 1085 - "<cursor.down count=3>", 1086 - "<cursor.backward count=999><cursor.up count=5>", 1087 - "<cursor.down count=1>", 1088 - "<erase.down>", 1089 - "<green>◇</fg> foo 1090 - <dim>│</fg> <dim>opt0</bold>", 1091 - " 1092 - ", 1093 - "<cursor.show>", 1094 - ] 1095 - `; 1096 - 1097 - exports[`multiselect (isCI = true) > renders multiple cancelled values 1`] = ` 1098 - [ 1099 - "<cursor.hide>", 1100 - "<dim>│</fg> 1101 - <cyan>◆</fg> foo 1102 - <cyan>│</fg> <cyan>◻</fg> opt0 1103 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 1104 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 1105 - <cyan>└</fg> 1106 - ", 1107 - "<cursor.backward count=999><cursor.up count=6>", 1108 - "<cursor.down count=2>", 1109 - "<erase.line><cursor.left count=1>", 1110 - "<cyan>│</fg> <green>◼</fg> opt0", 1111 - "<cursor.down count=4>", 1112 - "<cursor.backward count=999><cursor.up count=6>", 1113 - "<cursor.down count=2>", 1114 - "<erase.down>", 1115 - "<cyan>│</fg> <green>◼</fg> <dim>opt0</bold> 1116 - <cyan>│</fg> <cyan>◻</fg> opt1 1117 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 1118 - <cyan>└</fg> 1119 - ", 1120 - "<cursor.backward count=999><cursor.up count=6>", 1121 - "<cursor.down count=3>", 1122 - "<erase.line><cursor.left count=1>", 1123 - "<cyan>│</fg> <green>◼</fg> opt1", 1124 - "<cursor.down count=3>", 1125 - "<cursor.backward count=999><cursor.up count=6>", 1126 - "<cursor.down count=1>", 1127 - "<erase.down>", 1128 - "<red>■</fg> foo 1129 - <dim>│</fg> <dim>opt0</bold><dim>, </bold><dim>opt1</bold> 1130 - <dim>│</fg>", 1131 - " 1132 - ", 1133 - "<cursor.show>", 1134 - ] 1135 - `; 1136 - 1137 - exports[`multiselect (isCI = true) > renders multiple selected options 1`] = ` 1138 - [ 1139 - "<cursor.hide>", 1140 - "<dim>│</fg> 1141 - <cyan>◆</fg> foo 1142 - <cyan>│</fg> <cyan>◻</fg> opt0 1143 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 1144 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 1145 - <cyan>└</fg> 1146 - ", 1147 - "<cursor.backward count=999><cursor.up count=6>", 1148 - "<cursor.down count=2>", 1149 - "<erase.line><cursor.left count=1>", 1150 - "<cyan>│</fg> <green>◼</fg> opt0", 1151 - "<cursor.down count=4>", 1152 - "<cursor.backward count=999><cursor.up count=6>", 1153 - "<cursor.down count=2>", 1154 - "<erase.down>", 1155 - "<cyan>│</fg> <green>◼</fg> <dim>opt0</bold> 1156 - <cyan>│</fg> <cyan>◻</fg> opt1 1157 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 1158 - <cyan>└</fg> 1159 - ", 1160 - "<cursor.backward count=999><cursor.up count=6>", 1161 - "<cursor.down count=3>", 1162 - "<erase.line><cursor.left count=1>", 1163 - "<cyan>│</fg> <green>◼</fg> opt1", 1164 - "<cursor.down count=3>", 1165 - "<cursor.backward count=999><cursor.up count=6>", 1166 - "<cursor.down count=3>", 1167 - "<erase.down>", 1168 - "<cyan>│</fg> <green>◼</fg> <dim>opt1</bold> 1169 - <cyan>│</fg> <cyan>◻</fg> opt2 1170 - <cyan>└</fg> 1171 - ", 1172 - "<cursor.backward count=999><cursor.up count=6>", 1173 - "<cursor.down count=1>", 1174 - "<erase.down>", 1175 - "<green>◇</fg> foo 1176 - <dim>│</fg> <dim>opt0</bold><dim>, </bold><dim>opt1</bold>", 1177 - " 1178 - ", 1179 - "<cursor.show>", 1180 - ] 1181 - `; 1182 - 1183 - exports[`multiselect (isCI = true) > renders validation errors 1`] = ` 1184 - [ 1185 - "<cursor.hide>", 1186 - "<dim>│</fg> 1187 - <cyan>◆</fg> foo 1188 - <cyan>│</fg> <cyan>◻</fg> opt0 1189 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 1190 - <cyan>└</fg> 1191 - ", 1192 - "<cursor.backward count=999><cursor.up count=5>", 1193 - "<cursor.down count=1>", 1194 - "<erase.down>", 1195 - "<yellow>▲</fg> foo 1196 - <yellow>│</fg> <cyan>◻</fg> opt0 1197 - <yellow>│</fg> <dim>◻</bold> <dim>opt1</bold> 1198 - <yellow>└</fg> <yellow>Please select at least one option.</fg> 1199 - </><dim>Press <dim><bg:white> space </bg></fg> to select, <dim><bg:white> enter </bg></fg> to submit</bold></> 1200 - ", 1201 - "<cursor.backward count=999><cursor.up count=6>", 1202 - "<cursor.down count=1>", 1203 - "<erase.down>", 1204 - "<cyan>◆</fg> foo 1205 - <cyan>│</fg> <green>◼</fg> opt0 1206 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 1207 - <cyan>└</fg> 1208 - ", 1209 - "<cursor.backward count=999><cursor.up count=5>", 1210 - "<cursor.down count=1>", 1211 - "<erase.down>", 1212 - "<green>◇</fg> foo 1213 - <dim>│</fg> <dim>opt0</bold>", 1214 - " 1215 - ", 1216 - "<cursor.show>", 1217 - ] 1218 - `; 1219 - 1220 - exports[`multiselect (isCI = true) > shows hints for all selected options 1`] = ` 1221 - [ 1222 - "<cursor.hide>", 1223 - "<dim>│</fg> 1224 - <cyan>◆</fg> foo 1225 - <cyan>│</fg> <green>◼</fg> opt0 <dim>(Hint 0)</bold> 1226 - <cyan>│</fg> <green>◼</fg> <dim>opt1</bold> <dim>(Hint 1)</bold> 1227 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 1228 - <cyan>└</fg> 1229 - ", 1230 - "<cursor.backward count=999><cursor.up count=6>", 1231 - "<cursor.down count=2>", 1232 - "<erase.down>", 1233 - "<cyan>│</fg> <green>◼</fg> <dim>opt0</bold> <dim>(Hint 0)</bold> 1234 - <cyan>│</fg> <green>◼</fg> opt1 <dim>(Hint 1)</bold> 1235 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 1236 - <cyan>└</fg> 1237 - ", 1238 - "<cursor.backward count=999><cursor.up count=6>", 1239 - "<cursor.down count=3>", 1240 - "<erase.down>", 1241 - "<cyan>│</fg> <green>◼</fg> <dim>opt1</bold> <dim>(Hint 1)</bold> 1242 - <cyan>│</fg> <cyan>◻</fg> opt2 <dim>(Hint 2)</bold> 1243 - <cyan>└</fg> 1244 - ", 1245 - "<cursor.backward count=999><cursor.up count=6>", 1246 - "<cursor.down count=1>", 1247 - "<erase.down>", 1248 - "<green>◇</fg> foo 1249 - <dim>│</fg> <dim>opt0</bold><dim>, </bold><dim>opt1</bold>", 1250 - " 1251 - ", 1252 - "<cursor.show>", 1253 - ] 1254 - `; 1255 - 1256 - exports[`multiselect (isCI = true) > sliding window loops downwards 1`] = ` 1257 - [ 1258 - "<cursor.hide>", 1259 - "<dim>│</fg> 1260 - <cyan>◆</fg> foo 1261 - <cyan>│</fg> <cyan>◻</fg> opt0 1262 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 1263 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 1264 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 1265 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 1266 - <cyan>│</fg> <dim>...</bold> 1267 - <cyan>└</fg> 1268 - ", 1269 - "<cursor.backward count=999><cursor.up count=9>", 1270 - "<cursor.down count=2>", 1271 - "<erase.down>", 1272 - "<cyan>│</fg> <dim>◻</bold> <dim>opt0</bold> 1273 - <cyan>│</fg> <cyan>◻</fg> opt1 1274 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 1275 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 1276 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 1277 - <cyan>│</fg> <dim>...</bold> 1278 - <cyan>└</fg> 1279 - ", 1280 - "<cursor.backward count=999><cursor.up count=9>", 1281 - "<cursor.down count=3>", 1282 - "<erase.down>", 1283 - "<cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 1284 - <cyan>│</fg> <cyan>◻</fg> opt2 1285 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 1286 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 1287 - <cyan>│</fg> <dim>...</bold> 1288 - <cyan>└</fg> 1289 - ", 1290 - "<cursor.backward count=999><cursor.up count=9>", 1291 - "<cursor.down count=4>", 1292 - "<erase.down>", 1293 - "<cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 1294 - <cyan>│</fg> <cyan>◻</fg> opt3 1295 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 1296 - <cyan>│</fg> <dim>...</bold> 1297 - <cyan>└</fg> 1298 - ", 1299 - "<cursor.backward count=999><cursor.up count=9>", 1300 - "<cursor.down count=2>", 1301 - "<erase.down>", 1302 - "<cyan>│</fg> <dim>...</bold> 1303 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 1304 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 1305 - <cyan>│</fg> <cyan>◻</fg> opt4 1306 - <cyan>│</fg> <dim>◻</bold> <dim>opt5</bold> 1307 - <cyan>│</fg> <dim>...</bold> 1308 - <cyan>└</fg> 1309 - ", 1310 - "<cursor.backward count=999><cursor.up count=9>", 1311 - "<cursor.down count=3>", 1312 - "<erase.down>", 1313 - "<cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 1314 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 1315 - <cyan>│</fg> <cyan>◻</fg> opt5 1316 - <cyan>│</fg> <dim>◻</bold> <dim>opt6</bold> 1317 - <cyan>│</fg> <dim>...</bold> 1318 - <cyan>└</fg> 1319 - ", 1320 - "<cursor.backward count=999><cursor.up count=9>", 1321 - "<cursor.down count=3>", 1322 - "<erase.down>", 1323 - "<cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 1324 - <cyan>│</fg> <dim>◻</bold> <dim>opt5</bold> 1325 - <cyan>│</fg> <cyan>◻</fg> opt6 1326 - <cyan>│</fg> <dim>◻</bold> <dim>opt7</bold> 1327 - <cyan>│</fg> <dim>...</bold> 1328 - <cyan>└</fg> 1329 - ", 1330 - "<cursor.backward count=999><cursor.up count=9>", 1331 - "<cursor.down count=3>", 1332 - "<erase.down>", 1333 - "<cyan>│</fg> <dim>◻</bold> <dim>opt5</bold> 1334 - <cyan>│</fg> <dim>◻</bold> <dim>opt6</bold> 1335 - <cyan>│</fg> <cyan>◻</fg> opt7 1336 - <cyan>│</fg> <dim>◻</bold> <dim>opt8</bold> 1337 - <cyan>│</fg> <dim>...</bold> 1338 - <cyan>└</fg> 1339 - ", 1340 - "<cursor.backward count=999><cursor.up count=9>", 1341 - "<cursor.down count=3>", 1342 - "<erase.down>", 1343 - "<cyan>│</fg> <dim>◻</bold> <dim>opt6</bold> 1344 - <cyan>│</fg> <dim>◻</bold> <dim>opt7</bold> 1345 - <cyan>│</fg> <cyan>◻</fg> opt8 1346 - <cyan>│</fg> <dim>◻</bold> <dim>opt9</bold> 1347 - <cyan>│</fg> <dim>...</bold> 1348 - <cyan>└</fg> 1349 - ", 1350 - "<cursor.backward count=999><cursor.up count=9>", 1351 - "<cursor.down count=3>", 1352 - "<erase.down>", 1353 - "<cyan>│</fg> <dim>◻</bold> <dim>opt7</bold> 1354 - <cyan>│</fg> <dim>◻</bold> <dim>opt8</bold> 1355 - <cyan>│</fg> <cyan>◻</fg> opt9 1356 - <cyan>│</fg> <dim>◻</bold> <dim>opt10</bold> 1357 - <cyan>│</fg> <dim>◻</bold> <dim>opt11</bold> 1358 - <cyan>└</fg> 1359 - ", 1360 - "<cursor.backward count=999><cursor.up count=9>", 1361 - "<cursor.down count=5>", 1362 - "<erase.down>", 1363 - "<cyan>│</fg> <dim>◻</bold> <dim>opt9</bold> 1364 - <cyan>│</fg> <cyan>◻</fg> opt10 1365 - <cyan>│</fg> <dim>◻</bold> <dim>opt11</bold> 1366 - <cyan>└</fg> 1367 - ", 1368 - "<cursor.backward count=999><cursor.up count=9>", 1369 - "<cursor.down count=6>", 1370 - "<erase.down>", 1371 - "<cyan>│</fg> <dim>◻</bold> <dim>opt10</bold> 1372 - <cyan>│</fg> <cyan>◻</fg> opt11 1373 - <cyan>└</fg> 1374 - ", 1375 - "<cursor.backward count=999><cursor.up count=9>", 1376 - "<cursor.down count=2>", 1377 - "<erase.down>", 1378 - "<cyan>│</fg> <cyan>◻</fg> opt0 1379 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 1380 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 1381 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 1382 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 1383 - <cyan>│</fg> <dim>...</bold> 1384 - <cyan>└</fg> 1385 - ", 1386 - "<cursor.backward count=999><cursor.up count=9>", 1387 - "<cursor.down count=2>", 1388 - "<erase.line><cursor.left count=1>", 1389 - "<cyan>│</fg> <green>◼</fg> opt0", 1390 - "<cursor.down count=7>", 1391 - "<cursor.backward count=999><cursor.up count=9>", 1392 - "<cursor.down count=1>", 1393 - "<erase.down>", 1394 - "<green>◇</fg> foo 1395 - <dim>│</fg> <dim>opt0</bold>", 1396 - " 1397 - ", 1398 - "<cursor.show>", 1399 - ] 1400 - `; 1401 - 1402 - exports[`multiselect (isCI = true) > sliding window loops upwards 1`] = ` 1403 - [ 1404 - "<cursor.hide>", 1405 - "<dim>│</fg> 1406 - <cyan>◆</fg> foo 1407 - <cyan>│</fg> <cyan>◻</fg> opt0 1408 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 1409 - <cyan>│</fg> <dim>◻</bold> <dim>opt2</bold> 1410 - <cyan>│</fg> <dim>◻</bold> <dim>opt3</bold> 1411 - <cyan>│</fg> <dim>◻</bold> <dim>opt4</bold> 1412 - <cyan>│</fg> <dim>...</bold> 1413 - <cyan>└</fg> 1414 - ", 1415 - "<cursor.backward count=999><cursor.up count=9>", 1416 - "<cursor.down count=2>", 1417 - "<erase.down>", 1418 - "<cyan>│</fg> <dim>...</bold> 1419 - <cyan>│</fg> <dim>◻</bold> <dim>opt7</bold> 1420 - <cyan>│</fg> <dim>◻</bold> <dim>opt8</bold> 1421 - <cyan>│</fg> <dim>◻</bold> <dim>opt9</bold> 1422 - <cyan>│</fg> <dim>◻</bold> <dim>opt10</bold> 1423 - <cyan>│</fg> <cyan>◻</fg> opt11 1424 - <cyan>└</fg> 1425 - ", 1426 - "<cursor.backward count=999><cursor.up count=9>", 1427 - "<cursor.down count=7>", 1428 - "<erase.line><cursor.left count=1>", 1429 - "<cyan>│</fg> <green>◼</fg> opt11", 1430 - "<cursor.down count=2>", 1431 - "<cursor.backward count=999><cursor.up count=9>", 1432 - "<cursor.down count=1>", 1433 - "<erase.down>", 1434 - "<green>◇</fg> foo 1435 - <dim>│</fg> <dim>opt11</bold>", 1436 - " 1437 - ", 1438 - "<cursor.show>", 1439 - ] 1440 - `; 1441 - 1442 - exports[`multiselect (isCI = true) > withGuide: false removes guide 1`] = ` 1443 - [ 1444 - "<cursor.hide>", 1445 - "<cyan>◆</fg> foo 1446 - <cyan>◻</fg> opt0 1447 - <dim>◻</bold> <dim>opt1</bold> 1448 - 1449 - ", 1450 - "<cursor.backward count=999><cursor.up count=4>", 1451 - "<cursor.down count=1>", 1452 - "<erase.line><cursor.left count=1>", 1453 - "<green>◼</fg> opt0", 1454 - "<cursor.down count=3>", 1455 - "<cursor.backward count=999><cursor.up count=4>", 1456 - "<erase.down>", 1457 - "<green>◇</fg> foo 1458 - <dim>opt0</bold>", 1459 - " 1460 - ", 1461 - "<cursor.show>", 1462 - ] 1463 - `; 1464 - 1465 - exports[`multiselect (isCI = true) > wraps cancelled state with long options 1`] = ` 1466 - [ 1467 - "<cursor.hide>", 1468 - "<dim>│</fg> 1469 - <cyan>◆</fg> foo 1470 - <cyan>│</fg> <cyan>◻</fg> Option 0 Option 0 Option 1471 - <cyan>│</fg> 0 Option 0 Option 0 Option 1472 - <cyan>│</fg> 0 Option 0 Option 0 Option 1473 - <cyan>│</fg> 0 Option 0 1474 - <cyan>│</fg> <dim>◻</bold> <dim>Option 1 Option 1 Option </bold> 1475 - <cyan>│</fg> <dim>1 Option 1 Option 1 Option </bold> 1476 - <cyan>│</fg> <dim>1 Option 1 Option 1 Option </bold> 1477 - <cyan>│</fg> <dim>1 Option 1</bold> 1478 - <cyan>└</fg> 1479 - ", 1480 - "<cursor.backward count=999><cursor.up count=11>", 1481 - "<cursor.down count=2>", 1482 - "<erase.line><cursor.left count=1>", 1483 - "<cyan>│</fg> <green>◼</fg> Option 0 Option 0 Option ", 1484 - "<cursor.down count=9>", 1485 - "<cursor.backward count=999><cursor.up count=11>", 1486 - "<cursor.down count=1>", 1487 - "<erase.down>", 1488 - "<red>■</fg> foo 1489 - <dim>│</fg> <dim>Option 0 Option 0 Option 0 </bold> 1490 - <dim>│</fg> <dim>Option 0 Option 0 Option 0 </bold> 1491 - <dim>│</fg> <dim>Option 0 Option 0 Option 0 </bold> 1492 - <dim>│</fg> <dim>Option 0</bold> 1493 - <dim>│</fg>", 1494 - " 1495 - ", 1496 - "<cursor.show>", 1497 - ] 1498 - `; 1499 - 1500 - exports[`multiselect (isCI = true) > wraps long messages 1`] = ` 1501 - [ 1502 - "<cursor.hide>", 1503 - "<dim>│</fg> 1504 - <cyan>◆</fg> foo foo foo foo foo foo foo 1505 - <cyan>│</fg> foo foo foo foo foo foo 1506 - <cyan>│</fg> foo foo foo foo foo foo foo 1507 - <cyan>│</fg> <cyan>◻</fg> opt0 1508 - <cyan>│</fg> <dim>◻</bold> <dim>opt1</bold> 1509 - <cyan>└</fg> 1510 - ", 1511 - "<cursor.backward count=999><cursor.up count=7>", 1512 - "<cursor.down count=4>", 1513 - "<erase.line><cursor.left count=1>", 1514 - "<cyan>│</fg> <green>◼</fg> opt0", 1515 - "<cursor.down count=3>", 1516 - "<cursor.backward count=999><cursor.up count=7>", 1517 - "<cursor.down count=1>", 1518 - "<erase.down>", 1519 - "<green>◇</fg> foo foo foo foo foo foo foo 1520 - <green>│</fg> foo foo foo foo foo foo 1521 - <green>│</fg> foo foo foo foo foo foo foo 1522 - <dim>│</fg> <dim>opt0</bold>", 1523 - " 1524 - ", 1525 - "<cursor.show>", 1526 - ] 1527 - `; 1528 - 1529 - exports[`multiselect (isCI = true) > wraps success state with long options 1`] = ` 1530 - [ 1531 - "<cursor.hide>", 1532 - "<dim>│</fg> 1533 - <cyan>◆</fg> foo 1534 - <cyan>│</fg> <cyan>◻</fg> Option 0 Option 0 Option 1535 - <cyan>│</fg> 0 Option 0 Option 0 Option 1536 - <cyan>│</fg> 0 Option 0 Option 0 Option 1537 - <cyan>│</fg> 0 Option 0 1538 - <cyan>│</fg> <dim>◻</bold> <dim>Option 1 Option 1 Option </bold> 1539 - <cyan>│</fg> <dim>1 Option 1 Option 1 Option </bold> 1540 - <cyan>│</fg> <dim>1 Option 1 Option 1 Option </bold> 1541 - <cyan>│</fg> <dim>1 Option 1</bold> 1542 - <cyan>└</fg> 1543 - ", 1544 - "<cursor.backward count=999><cursor.up count=11>", 1545 - "<cursor.down count=2>", 1546 - "<erase.line><cursor.left count=1>", 1547 - "<cyan>│</fg> <green>◼</fg> Option 0 Option 0 Option ", 1548 - "<cursor.down count=9>", 1549 - "<cursor.backward count=999><cursor.up count=11>", 1550 - "<cursor.down count=1>", 1551 - "<erase.down>", 1552 - "<green>◇</fg> foo 1553 - <dim>│</fg> <dim>Option 0 Option 0 Option 0 </bold> 1554 - <dim>│</fg> <dim>Option 0 Option 0 Option 0 </bold> 1555 - <dim>│</fg> <dim>Option 0 Option 0 Option 0 </bold> 1556 - <dim>│</fg> <dim>Option 0</bold>", 1557 - " 1558 - ", 1559 - "<cursor.show>", 1560 - ] 1561 - `;
-385
packages/prompts/test/__snapshots__/note.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`note (isCI = false) > don't overflow 1`] = ` 4 - [ 5 - "<dim>│</fg> 6 - <green>◇</fg> </>title</> <dim>───────────────────────────────────────────────────────────────╮</fg> 7 - <dim>│</fg> <dim>│</fg> 8 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 9 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 10 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 11 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 12 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 13 - <dim>│</fg> <dim>string test string test string test string test string </bold> <dim>│</fg> 14 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 15 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 16 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 17 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 18 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 19 - <dim>│</fg> <dim>string test string test string test string test string </bold> <dim>│</fg> 20 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 21 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 22 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 23 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 24 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 25 - <dim>│</fg> <dim>string test string test string test string test string </bold> <dim>│</fg> 26 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 27 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 28 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 29 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 30 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 31 - <dim>│</fg> <dim>string test string test string test string test string</bold> <dim>│</fg> 32 - <dim>│</fg> <dim>│</fg> 33 - <dim>├───────────────────────────────────────────────────────────────────────╯</fg> 34 - ", 35 - ] 36 - `; 37 - 38 - exports[`note (isCI = false) > don't overflow with formatter 1`] = ` 39 - [ 40 - "<dim>│</fg> 41 - <green>◇</fg> </>title</> <dim>─────────────────────────────────────────────────────────────────╮</fg> 42 - <dim>│</fg> <dim>│</fg> 43 - <dim>│</fg> <red>* <cyan>test string test string test string test string test string test <red> *</fg> <dim>│</fg> 44 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 45 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 46 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 47 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 48 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 49 - <dim>│</fg> <red>* <cyan>string test string <red> *</fg> <dim>│</fg> 50 - <dim>│</fg> <red>* <cyan>test string test string test string test string test string test <red> *</fg> <dim>│</fg> 51 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 52 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 53 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 54 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 55 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 56 - <dim>│</fg> <red>* <cyan>string test string <red> *</fg> <dim>│</fg> 57 - <dim>│</fg> <red>* <cyan>test string test string test string test string test string test <red> *</fg> <dim>│</fg> 58 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 59 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 60 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 61 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 62 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 63 - <dim>│</fg> <red>* <cyan>string test string <red> *</fg> <dim>│</fg> 64 - <dim>│</fg> <red>* <cyan>test string test string test string test string test string test <red> *</fg> <dim>│</fg> 65 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 66 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 67 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 68 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 69 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 70 - <dim>│</fg> <red>* <cyan>string test string<red> *</fg> <dim>│</fg> 71 - <dim>│</fg> <dim>│</fg> 72 - <dim>├─────────────────────────────────────────────────────────────────────────╯</fg> 73 - ", 74 - ] 75 - `; 76 - 77 - exports[`note (isCI = false) > formatter which adds colors works 1`] = ` 78 - [ 79 - "<dim>│</fg> 80 - <green>◇</fg> </>title</> <dim>──╮</fg> 81 - <dim>│</fg> <dim>│</fg> 82 - <dim>│</fg> <red>line 0</fg> <dim>│</fg> 83 - <dim>│</fg> <red>line 1</fg> <dim>│</fg> 84 - <dim>│</fg> <red>line 2</fg> <dim>│</fg> 85 - <dim>│</fg> <dim>│</fg> 86 - <dim>├──────────╯</fg> 87 - ", 88 - ] 89 - `; 90 - 91 - exports[`note (isCI = false) > formatter which adds length works 1`] = ` 92 - [ 93 - "<dim>│</fg> 94 - <green>◇</fg> </>title</> <dim>──────╮</fg> 95 - <dim>│</fg> <dim>│</fg> 96 - <dim>│</fg> * line 0 * <dim>│</fg> 97 - <dim>│</fg> * line 1 * <dim>│</fg> 98 - <dim>│</fg> * line 2 * <dim>│</fg> 99 - <dim>│</fg> <dim>│</fg> 100 - <dim>├──────────────╯</fg> 101 - ", 102 - ] 103 - `; 104 - 105 - exports[`note (isCI = false) > handle wide characters 1`] = ` 106 - [ 107 - "<dim>│</fg> 108 - <green>◇</fg> </>这是标题</> <dim>─╮</fg> 109 - <dim>│</fg> <dim>│</fg> 110 - <dim>│</fg> <dim>이게</bold> <dim>│</fg> 111 - <dim>│</fg> <dim> 첫 </bold> <dim>│</fg> 112 - <dim>│</fg> <dim>번째</bold> <dim>│</fg> 113 - <dim>│</fg> <dim> </bold> <dim>│</fg> 114 - <dim>│</fg> <dim>줄이</bold> <dim>│</fg> 115 - <dim>│</fg> <dim>에요</bold> <dim>│</fg> 116 - <dim>│</fg> <dim>これ</bold> <dim>│</fg> 117 - <dim>│</fg> <dim>は次</bold> <dim>│</fg> 118 - <dim>│</fg> <dim>の行</bold> <dim>│</fg> 119 - <dim>│</fg> <dim>です</bold> <dim>│</fg> 120 - <dim>│</fg> <dim>│</fg> 121 - <dim>├────────────╯</fg> 122 - ", 123 - ] 124 - `; 125 - 126 - exports[`note (isCI = false) > handle wide characters with formatter 1`] = ` 127 - [ 128 - "<dim>│</fg> 129 - <green>◇</fg> </>这是标题</> <dim>─╮</fg> 130 - <dim>│</fg> <dim>│</fg> 131 - <dim>│</fg> <red>* <cyan><red> *</fg> <dim>│</fg> 132 - <dim>│</fg> <red>* <cyan>이<red> *</fg> <dim>│</fg> 133 - <dim>│</fg> <red>* <cyan>게<red> *</fg> <dim>│</fg> 134 - <dim>│</fg> <red>* <cyan> <red> *</fg> <dim>│</fg> 135 - <dim>│</fg> <red>* <cyan>첫<red> *</fg> <dim>│</fg> 136 - <dim>│</fg> <red>* <cyan> <red> *</fg> <dim>│</fg> 137 - <dim>│</fg> <red>* <cyan>번<red> *</fg> <dim>│</fg> 138 - <dim>│</fg> <red>* <cyan>째<red> *</fg> <dim>│</fg> 139 - <dim>│</fg> <red>* <cyan> <red> *</fg> <dim>│</fg> 140 - <dim>│</fg> <red>* <cyan>줄<red> *</fg> <dim>│</fg> 141 - <dim>│</fg> <red>* <cyan>이<red> *</fg> <dim>│</fg> 142 - <dim>│</fg> <red>* <cyan>에<red> *</fg> <dim>│</fg> 143 - <dim>│</fg> <red>* <cyan>요<red> *</fg> <dim>│</fg> 144 - <dim>│</fg> <red>* <cyan><red> *</fg> <dim>│</fg> 145 - <dim>│</fg> <red>* <cyan>こ<red> *</fg> <dim>│</fg> 146 - <dim>│</fg> <red>* <cyan>れ<red> *</fg> <dim>│</fg> 147 - <dim>│</fg> <red>* <cyan>は<red> *</fg> <dim>│</fg> 148 - <dim>│</fg> <red>* <cyan>次<red> *</fg> <dim>│</fg> 149 - <dim>│</fg> <red>* <cyan>の<red> *</fg> <dim>│</fg> 150 - <dim>│</fg> <red>* <cyan>行<red> *</fg> <dim>│</fg> 151 - <dim>│</fg> <red>* <cyan>で<red> *</fg> <dim>│</fg> 152 - <dim>│</fg> <red>* <cyan>す<red> *</fg> <dim>│</fg> 153 - <dim>│</fg> <dim>│</fg> 154 - <dim>├────────────╯</fg> 155 - ", 156 - ] 157 - `; 158 - 159 - exports[`note (isCI = false) > renders as wide as longest line 1`] = ` 160 - [ 161 - "<dim>│</fg> 162 - <green>◇</fg> </>title</> <dim>───────────────────────────╮</fg> 163 - <dim>│</fg> <dim>│</fg> 164 - <dim>│</fg> <dim>short</bold> <dim>│</fg> 165 - <dim>│</fg> <dim>somewhat questionably long line</bold> <dim>│</fg> 166 - <dim>│</fg> <dim>│</fg> 167 - <dim>├───────────────────────────────────╯</fg> 168 - ", 169 - ] 170 - `; 171 - 172 - exports[`note (isCI = false) > renders message with title 1`] = ` 173 - [ 174 - "<dim>│</fg> 175 - <green>◇</fg> </>title</> <dim>───╮</fg> 176 - <dim>│</fg> <dim>│</fg> 177 - <dim>│</fg> <dim>message</bold> <dim>│</fg> 178 - <dim>│</fg> <dim>│</fg> 179 - <dim>├───────────╯</fg> 180 - ", 181 - ] 182 - `; 183 - 184 - exports[`note (isCI = false) > without guide 1`] = ` 185 - [ 186 - "<green>◇</fg> </>title</> <dim>───╮</fg> 187 - <dim>│</fg> <dim>│</fg> 188 - <dim>│</fg> <dim>message</bold> <dim>│</fg> 189 - <dim>│</fg> <dim>│</fg> 190 - <dim>╰───────────╯</fg> 191 - ", 192 - ] 193 - `; 194 - 195 - exports[`note (isCI = true) > don't overflow 1`] = ` 196 - [ 197 - "<dim>│</fg> 198 - <green>◇</fg> </>title</> <dim>───────────────────────────────────────────────────────────────╮</fg> 199 - <dim>│</fg> <dim>│</fg> 200 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 201 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 202 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 203 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 204 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 205 - <dim>│</fg> <dim>string test string test string test string test string </bold> <dim>│</fg> 206 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 207 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 208 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 209 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 210 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 211 - <dim>│</fg> <dim>string test string test string test string test string </bold> <dim>│</fg> 212 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 213 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 214 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 215 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 216 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 217 - <dim>│</fg> <dim>string test string test string test string test string </bold> <dim>│</fg> 218 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 219 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 220 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 221 - <dim>│</fg> <dim>string test string test string test string test string test string </bold> <dim>│</fg> 222 - <dim>│</fg> <dim>test string test string test string test string test string test </bold> <dim>│</fg> 223 - <dim>│</fg> <dim>string test string test string test string test string</bold> <dim>│</fg> 224 - <dim>│</fg> <dim>│</fg> 225 - <dim>├───────────────────────────────────────────────────────────────────────╯</fg> 226 - ", 227 - ] 228 - `; 229 - 230 - exports[`note (isCI = true) > don't overflow with formatter 1`] = ` 231 - [ 232 - "<dim>│</fg> 233 - <green>◇</fg> </>title</> <dim>─────────────────────────────────────────────────────────────────╮</fg> 234 - <dim>│</fg> <dim>│</fg> 235 - <dim>│</fg> <red>* <cyan>test string test string test string test string test string test <red> *</fg> <dim>│</fg> 236 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 237 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 238 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 239 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 240 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 241 - <dim>│</fg> <red>* <cyan>string test string <red> *</fg> <dim>│</fg> 242 - <dim>│</fg> <red>* <cyan>test string test string test string test string test string test <red> *</fg> <dim>│</fg> 243 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 244 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 245 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 246 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 247 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 248 - <dim>│</fg> <red>* <cyan>string test string <red> *</fg> <dim>│</fg> 249 - <dim>│</fg> <red>* <cyan>test string test string test string test string test string test <red> *</fg> <dim>│</fg> 250 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 251 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 252 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 253 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 254 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 255 - <dim>│</fg> <red>* <cyan>string test string <red> *</fg> <dim>│</fg> 256 - <dim>│</fg> <red>* <cyan>test string test string test string test string test string test <red> *</fg> <dim>│</fg> 257 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 258 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 259 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 260 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 261 - <dim>│</fg> <red>* <cyan>string test string test string test string test string test <red> *</fg> <dim>│</fg> 262 - <dim>│</fg> <red>* <cyan>string test string<red> *</fg> <dim>│</fg> 263 - <dim>│</fg> <dim>│</fg> 264 - <dim>├─────────────────────────────────────────────────────────────────────────╯</fg> 265 - ", 266 - ] 267 - `; 268 - 269 - exports[`note (isCI = true) > formatter which adds colors works 1`] = ` 270 - [ 271 - "<dim>│</fg> 272 - <green>◇</fg> </>title</> <dim>──╮</fg> 273 - <dim>│</fg> <dim>│</fg> 274 - <dim>│</fg> <red>line 0</fg> <dim>│</fg> 275 - <dim>│</fg> <red>line 1</fg> <dim>│</fg> 276 - <dim>│</fg> <red>line 2</fg> <dim>│</fg> 277 - <dim>│</fg> <dim>│</fg> 278 - <dim>├──────────╯</fg> 279 - ", 280 - ] 281 - `; 282 - 283 - exports[`note (isCI = true) > formatter which adds length works 1`] = ` 284 - [ 285 - "<dim>│</fg> 286 - <green>◇</fg> </>title</> <dim>──────╮</fg> 287 - <dim>│</fg> <dim>│</fg> 288 - <dim>│</fg> * line 0 * <dim>│</fg> 289 - <dim>│</fg> * line 1 * <dim>│</fg> 290 - <dim>│</fg> * line 2 * <dim>│</fg> 291 - <dim>│</fg> <dim>│</fg> 292 - <dim>├──────────────╯</fg> 293 - ", 294 - ] 295 - `; 296 - 297 - exports[`note (isCI = true) > handle wide characters 1`] = ` 298 - [ 299 - "<dim>│</fg> 300 - <green>◇</fg> </>这是标题</> <dim>─╮</fg> 301 - <dim>│</fg> <dim>│</fg> 302 - <dim>│</fg> <dim>이게</bold> <dim>│</fg> 303 - <dim>│</fg> <dim> 첫 </bold> <dim>│</fg> 304 - <dim>│</fg> <dim>번째</bold> <dim>│</fg> 305 - <dim>│</fg> <dim> </bold> <dim>│</fg> 306 - <dim>│</fg> <dim>줄이</bold> <dim>│</fg> 307 - <dim>│</fg> <dim>에요</bold> <dim>│</fg> 308 - <dim>│</fg> <dim>これ</bold> <dim>│</fg> 309 - <dim>│</fg> <dim>は次</bold> <dim>│</fg> 310 - <dim>│</fg> <dim>の行</bold> <dim>│</fg> 311 - <dim>│</fg> <dim>です</bold> <dim>│</fg> 312 - <dim>│</fg> <dim>│</fg> 313 - <dim>├────────────╯</fg> 314 - ", 315 - ] 316 - `; 317 - 318 - exports[`note (isCI = true) > handle wide characters with formatter 1`] = ` 319 - [ 320 - "<dim>│</fg> 321 - <green>◇</fg> </>这是标题</> <dim>─╮</fg> 322 - <dim>│</fg> <dim>│</fg> 323 - <dim>│</fg> <red>* <cyan><red> *</fg> <dim>│</fg> 324 - <dim>│</fg> <red>* <cyan>이<red> *</fg> <dim>│</fg> 325 - <dim>│</fg> <red>* <cyan>게<red> *</fg> <dim>│</fg> 326 - <dim>│</fg> <red>* <cyan> <red> *</fg> <dim>│</fg> 327 - <dim>│</fg> <red>* <cyan>첫<red> *</fg> <dim>│</fg> 328 - <dim>│</fg> <red>* <cyan> <red> *</fg> <dim>│</fg> 329 - <dim>│</fg> <red>* <cyan>번<red> *</fg> <dim>│</fg> 330 - <dim>│</fg> <red>* <cyan>째<red> *</fg> <dim>│</fg> 331 - <dim>│</fg> <red>* <cyan> <red> *</fg> <dim>│</fg> 332 - <dim>│</fg> <red>* <cyan>줄<red> *</fg> <dim>│</fg> 333 - <dim>│</fg> <red>* <cyan>이<red> *</fg> <dim>│</fg> 334 - <dim>│</fg> <red>* <cyan>에<red> *</fg> <dim>│</fg> 335 - <dim>│</fg> <red>* <cyan>요<red> *</fg> <dim>│</fg> 336 - <dim>│</fg> <red>* <cyan><red> *</fg> <dim>│</fg> 337 - <dim>│</fg> <red>* <cyan>こ<red> *</fg> <dim>│</fg> 338 - <dim>│</fg> <red>* <cyan>れ<red> *</fg> <dim>│</fg> 339 - <dim>│</fg> <red>* <cyan>は<red> *</fg> <dim>│</fg> 340 - <dim>│</fg> <red>* <cyan>次<red> *</fg> <dim>│</fg> 341 - <dim>│</fg> <red>* <cyan>の<red> *</fg> <dim>│</fg> 342 - <dim>│</fg> <red>* <cyan>行<red> *</fg> <dim>│</fg> 343 - <dim>│</fg> <red>* <cyan>で<red> *</fg> <dim>│</fg> 344 - <dim>│</fg> <red>* <cyan>す<red> *</fg> <dim>│</fg> 345 - <dim>│</fg> <dim>│</fg> 346 - <dim>├────────────╯</fg> 347 - ", 348 - ] 349 - `; 350 - 351 - exports[`note (isCI = true) > renders as wide as longest line 1`] = ` 352 - [ 353 - "<dim>│</fg> 354 - <green>◇</fg> </>title</> <dim>───────────────────────────╮</fg> 355 - <dim>│</fg> <dim>│</fg> 356 - <dim>│</fg> <dim>short</bold> <dim>│</fg> 357 - <dim>│</fg> <dim>somewhat questionably long line</bold> <dim>│</fg> 358 - <dim>│</fg> <dim>│</fg> 359 - <dim>├───────────────────────────────────╯</fg> 360 - ", 361 - ] 362 - `; 363 - 364 - exports[`note (isCI = true) > renders message with title 1`] = ` 365 - [ 366 - "<dim>│</fg> 367 - <green>◇</fg> </>title</> <dim>───╮</fg> 368 - <dim>│</fg> <dim>│</fg> 369 - <dim>│</fg> <dim>message</bold> <dim>│</fg> 370 - <dim>│</fg> <dim>│</fg> 371 - <dim>├───────────╯</fg> 372 - ", 373 - ] 374 - `; 375 - 376 - exports[`note (isCI = true) > without guide 1`] = ` 377 - [ 378 - "<green>◇</fg> </>title</> <dim>───╮</fg> 379 - <dim>│</fg> <dim>│</fg> 380 - <dim>│</fg> <dim>message</bold> <dim>│</fg> 381 - <dim>│</fg> <dim>│</fg> 382 - <dim>╰───────────╯</fg> 383 - ", 384 - ] 385 - `;
-463
packages/prompts/test/__snapshots__/password.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`password (isCI = false) > can be aborted by a signal 1`] = ` 4 - [ 5 - "<cursor.hide>", 6 - "<dim>│</fg> 7 - <cyan>◆</fg> foo 8 - <cyan>│</fg> _ 9 - <cyan>└</fg> 10 - ", 11 - " 12 - ", 13 - "<cursor.show>", 14 - ] 15 - `; 16 - 17 - exports[`password (isCI = false) > clears input on error when clearOnError is true 1`] = ` 18 - [ 19 - "<cursor.hide>", 20 - "<dim>│</fg> 21 - <cyan>◆</fg> foo 22 - <cyan>│</fg> _ 23 - <cyan>└</fg> 24 - ", 25 - "<cursor.backward count=999><cursor.up count=4>", 26 - "<cursor.down count=2>", 27 - "<erase.line><cursor.left count=1>", 28 - "<cyan>│</fg> ▪_", 29 - "<cursor.down count=2>", 30 - "<cursor.backward count=999><cursor.up count=4>", 31 - "<cursor.down count=1>", 32 - "<erase.down>", 33 - "<yellow>▲</fg> foo 34 - <yellow>│</fg> ▪ 35 - <yellow>└</fg> <yellow>Error</fg> 36 - ", 37 - "<cursor.backward count=999><cursor.up count=4>", 38 - "<cursor.down count=1>", 39 - "<erase.down>", 40 - "<cyan>◆</fg> foo 41 - <cyan>│</fg> ▪_ 42 - <cyan>└</fg> 43 - ", 44 - "<cursor.backward count=999><cursor.up count=4>", 45 - "<cursor.down count=2>", 46 - "<erase.line><cursor.left count=1>", 47 - "<cyan>│</fg> ▪▪_", 48 - "<cursor.down count=2>", 49 - "<cursor.backward count=999><cursor.up count=4>", 50 - "<cursor.down count=1>", 51 - "<erase.down>", 52 - "<green>◇</fg> foo 53 - <dim>│</fg> <dim>▪▪</bold>", 54 - " 55 - ", 56 - "<cursor.show>", 57 - ] 58 - `; 59 - 60 - exports[`password (isCI = false) > global withGuide: false removes guide 1`] = ` 61 - [ 62 - "<cursor.hide>", 63 - "<cyan>◆</fg> foo 64 - _ 65 - 66 - ", 67 - "<cursor.backward count=999><cursor.up count=3>", 68 - "<erase.down>", 69 - "<green>◇</fg> foo 70 - ", 71 - " 72 - ", 73 - "<cursor.show>", 74 - ] 75 - `; 76 - 77 - exports[`password (isCI = false) > renders and clears validation errors 1`] = ` 78 - [ 79 - "<cursor.hide>", 80 - "<dim>│</fg> 81 - <cyan>◆</fg> foo 82 - <cyan>│</fg> _ 83 - <cyan>└</fg> 84 - ", 85 - "<cursor.backward count=999><cursor.up count=4>", 86 - "<cursor.down count=2>", 87 - "<erase.line><cursor.left count=1>", 88 - "<cyan>│</fg> ▪_", 89 - "<cursor.down count=2>", 90 - "<cursor.backward count=999><cursor.up count=4>", 91 - "<cursor.down count=1>", 92 - "<erase.down>", 93 - "<yellow>▲</fg> foo 94 - <yellow>│</fg> ▪ 95 - <yellow>└</fg> <yellow>Password must be at least 2 characters</fg> 96 - ", 97 - "<cursor.backward count=999><cursor.up count=4>", 98 - "<cursor.down count=1>", 99 - "<erase.down>", 100 - "<cyan>◆</fg> foo 101 - <cyan>│</fg> ▪▪_ 102 - <cyan>└</fg> 103 - ", 104 - "<cursor.backward count=999><cursor.up count=4>", 105 - "<cursor.down count=1>", 106 - "<erase.down>", 107 - "<green>◇</fg> foo 108 - <dim>│</fg> <dim>▪▪</bold>", 109 - " 110 - ", 111 - "<cursor.show>", 112 - ] 113 - `; 114 - 115 - exports[`password (isCI = false) > renders cancelled value 1`] = ` 116 - [ 117 - "<cursor.hide>", 118 - "<dim>│</fg> 119 - <cyan>◆</fg> foo 120 - <cyan>│</fg> _ 121 - <cyan>└</fg> 122 - ", 123 - "<cursor.backward count=999><cursor.up count=4>", 124 - "<cursor.down count=2>", 125 - "<erase.line><cursor.left count=1>", 126 - "<cyan>│</fg> ▪_", 127 - "<cursor.down count=2>", 128 - "<cursor.backward count=999><cursor.up count=4>", 129 - "<cursor.down count=1>", 130 - "<erase.down>", 131 - "<red>■</fg> foo 132 - <dim>│</fg> <dim>▪</bold> 133 - <dim>│</fg>", 134 - " 135 - ", 136 - "<cursor.show>", 137 - ] 138 - `; 139 - 140 - exports[`password (isCI = false) > renders custom mask 1`] = ` 141 - [ 142 - "<cursor.hide>", 143 - "<dim>│</fg> 144 - <cyan>◆</fg> foo 145 - <cyan>│</fg> _ 146 - <cyan>└</fg> 147 - ", 148 - "<cursor.backward count=999><cursor.up count=4>", 149 - "<cursor.down count=2>", 150 - "<erase.line><cursor.left count=1>", 151 - "<cyan>│</fg> *_", 152 - "<cursor.down count=2>", 153 - "<cursor.backward count=999><cursor.up count=4>", 154 - "<cursor.down count=2>", 155 - "<erase.line><cursor.left count=1>", 156 - "<cyan>│</fg> **_", 157 - "<cursor.down count=2>", 158 - "<cursor.backward count=999><cursor.up count=4>", 159 - "<cursor.down count=1>", 160 - "<erase.down>", 161 - "<green>◇</fg> foo 162 - <dim>│</fg> <dim>**</bold>", 163 - " 164 - ", 165 - "<cursor.show>", 166 - ] 167 - `; 168 - 169 - exports[`password (isCI = false) > renders masked value 1`] = ` 170 - [ 171 - "<cursor.hide>", 172 - "<dim>│</fg> 173 - <cyan>◆</fg> foo 174 - <cyan>│</fg> _ 175 - <cyan>└</fg> 176 - ", 177 - "<cursor.backward count=999><cursor.up count=4>", 178 - "<cursor.down count=2>", 179 - "<erase.line><cursor.left count=1>", 180 - "<cyan>│</fg> ▪_", 181 - "<cursor.down count=2>", 182 - "<cursor.backward count=999><cursor.up count=4>", 183 - "<cursor.down count=2>", 184 - "<erase.line><cursor.left count=1>", 185 - "<cyan>│</fg> ▪▪_", 186 - "<cursor.down count=2>", 187 - "<cursor.backward count=999><cursor.up count=4>", 188 - "<cursor.down count=1>", 189 - "<erase.down>", 190 - "<green>◇</fg> foo 191 - <dim>│</fg> <dim>▪▪</bold>", 192 - " 193 - ", 194 - "<cursor.show>", 195 - ] 196 - `; 197 - 198 - exports[`password (isCI = false) > renders message 1`] = ` 199 - [ 200 - "<cursor.hide>", 201 - "<dim>│</fg> 202 - <cyan>◆</fg> foo 203 - <cyan>│</fg> _ 204 - <cyan>└</fg> 205 - ", 206 - "<cursor.backward count=999><cursor.up count=4>", 207 - "<cursor.down count=1>", 208 - "<erase.down>", 209 - "<green>◇</fg> foo 210 - <dim>│</fg> ", 211 - " 212 - ", 213 - "<cursor.show>", 214 - ] 215 - `; 216 - 217 - exports[`password (isCI = false) > withGuide: false removes guide 1`] = ` 218 - [ 219 - "<cursor.hide>", 220 - "<cyan>◆</fg> foo 221 - _ 222 - 223 - ", 224 - "<cursor.backward count=999><cursor.up count=3>", 225 - "<erase.down>", 226 - "<green>◇</fg> foo 227 - ", 228 - " 229 - ", 230 - "<cursor.show>", 231 - ] 232 - `; 233 - 234 - exports[`password (isCI = true) > can be aborted by a signal 1`] = ` 235 - [ 236 - "<cursor.hide>", 237 - "<dim>│</fg> 238 - <cyan>◆</fg> foo 239 - <cyan>│</fg> _ 240 - <cyan>└</fg> 241 - ", 242 - " 243 - ", 244 - "<cursor.show>", 245 - ] 246 - `; 247 - 248 - exports[`password (isCI = true) > clears input on error when clearOnError is true 1`] = ` 249 - [ 250 - "<cursor.hide>", 251 - "<dim>│</fg> 252 - <cyan>◆</fg> foo 253 - <cyan>│</fg> _ 254 - <cyan>└</fg> 255 - ", 256 - "<cursor.backward count=999><cursor.up count=4>", 257 - "<cursor.down count=2>", 258 - "<erase.line><cursor.left count=1>", 259 - "<cyan>│</fg> ▪_", 260 - "<cursor.down count=2>", 261 - "<cursor.backward count=999><cursor.up count=4>", 262 - "<cursor.down count=1>", 263 - "<erase.down>", 264 - "<yellow>▲</fg> foo 265 - <yellow>│</fg> ▪ 266 - <yellow>└</fg> <yellow>Error</fg> 267 - ", 268 - "<cursor.backward count=999><cursor.up count=4>", 269 - "<cursor.down count=1>", 270 - "<erase.down>", 271 - "<cyan>◆</fg> foo 272 - <cyan>│</fg> ▪_ 273 - <cyan>└</fg> 274 - ", 275 - "<cursor.backward count=999><cursor.up count=4>", 276 - "<cursor.down count=2>", 277 - "<erase.line><cursor.left count=1>", 278 - "<cyan>│</fg> ▪▪_", 279 - "<cursor.down count=2>", 280 - "<cursor.backward count=999><cursor.up count=4>", 281 - "<cursor.down count=1>", 282 - "<erase.down>", 283 - "<green>◇</fg> foo 284 - <dim>│</fg> <dim>▪▪</bold>", 285 - " 286 - ", 287 - "<cursor.show>", 288 - ] 289 - `; 290 - 291 - exports[`password (isCI = true) > global withGuide: false removes guide 1`] = ` 292 - [ 293 - "<cursor.hide>", 294 - "<cyan>◆</fg> foo 295 - _ 296 - 297 - ", 298 - "<cursor.backward count=999><cursor.up count=3>", 299 - "<erase.down>", 300 - "<green>◇</fg> foo 301 - ", 302 - " 303 - ", 304 - "<cursor.show>", 305 - ] 306 - `; 307 - 308 - exports[`password (isCI = true) > renders and clears validation errors 1`] = ` 309 - [ 310 - "<cursor.hide>", 311 - "<dim>│</fg> 312 - <cyan>◆</fg> foo 313 - <cyan>│</fg> _ 314 - <cyan>└</fg> 315 - ", 316 - "<cursor.backward count=999><cursor.up count=4>", 317 - "<cursor.down count=2>", 318 - "<erase.line><cursor.left count=1>", 319 - "<cyan>│</fg> ▪_", 320 - "<cursor.down count=2>", 321 - "<cursor.backward count=999><cursor.up count=4>", 322 - "<cursor.down count=1>", 323 - "<erase.down>", 324 - "<yellow>▲</fg> foo 325 - <yellow>│</fg> ▪ 326 - <yellow>└</fg> <yellow>Password must be at least 2 characters</fg> 327 - ", 328 - "<cursor.backward count=999><cursor.up count=4>", 329 - "<cursor.down count=1>", 330 - "<erase.down>", 331 - "<cyan>◆</fg> foo 332 - <cyan>│</fg> ▪▪_ 333 - <cyan>└</fg> 334 - ", 335 - "<cursor.backward count=999><cursor.up count=4>", 336 - "<cursor.down count=1>", 337 - "<erase.down>", 338 - "<green>◇</fg> foo 339 - <dim>│</fg> <dim>▪▪</bold>", 340 - " 341 - ", 342 - "<cursor.show>", 343 - ] 344 - `; 345 - 346 - exports[`password (isCI = true) > renders cancelled value 1`] = ` 347 - [ 348 - "<cursor.hide>", 349 - "<dim>│</fg> 350 - <cyan>◆</fg> foo 351 - <cyan>│</fg> _ 352 - <cyan>└</fg> 353 - ", 354 - "<cursor.backward count=999><cursor.up count=4>", 355 - "<cursor.down count=2>", 356 - "<erase.line><cursor.left count=1>", 357 - "<cyan>│</fg> ▪_", 358 - "<cursor.down count=2>", 359 - "<cursor.backward count=999><cursor.up count=4>", 360 - "<cursor.down count=1>", 361 - "<erase.down>", 362 - "<red>■</fg> foo 363 - <dim>│</fg> <dim>▪</bold> 364 - <dim>│</fg>", 365 - " 366 - ", 367 - "<cursor.show>", 368 - ] 369 - `; 370 - 371 - exports[`password (isCI = true) > renders custom mask 1`] = ` 372 - [ 373 - "<cursor.hide>", 374 - "<dim>│</fg> 375 - <cyan>◆</fg> foo 376 - <cyan>│</fg> _ 377 - <cyan>└</fg> 378 - ", 379 - "<cursor.backward count=999><cursor.up count=4>", 380 - "<cursor.down count=2>", 381 - "<erase.line><cursor.left count=1>", 382 - "<cyan>│</fg> *_", 383 - "<cursor.down count=2>", 384 - "<cursor.backward count=999><cursor.up count=4>", 385 - "<cursor.down count=2>", 386 - "<erase.line><cursor.left count=1>", 387 - "<cyan>│</fg> **_", 388 - "<cursor.down count=2>", 389 - "<cursor.backward count=999><cursor.up count=4>", 390 - "<cursor.down count=1>", 391 - "<erase.down>", 392 - "<green>◇</fg> foo 393 - <dim>│</fg> <dim>**</bold>", 394 - " 395 - ", 396 - "<cursor.show>", 397 - ] 398 - `; 399 - 400 - exports[`password (isCI = true) > renders masked value 1`] = ` 401 - [ 402 - "<cursor.hide>", 403 - "<dim>│</fg> 404 - <cyan>◆</fg> foo 405 - <cyan>│</fg> _ 406 - <cyan>└</fg> 407 - ", 408 - "<cursor.backward count=999><cursor.up count=4>", 409 - "<cursor.down count=2>", 410 - "<erase.line><cursor.left count=1>", 411 - "<cyan>│</fg> ▪_", 412 - "<cursor.down count=2>", 413 - "<cursor.backward count=999><cursor.up count=4>", 414 - "<cursor.down count=2>", 415 - "<erase.line><cursor.left count=1>", 416 - "<cyan>│</fg> ▪▪_", 417 - "<cursor.down count=2>", 418 - "<cursor.backward count=999><cursor.up count=4>", 419 - "<cursor.down count=1>", 420 - "<erase.down>", 421 - "<green>◇</fg> foo 422 - <dim>│</fg> <dim>▪▪</bold>", 423 - " 424 - ", 425 - "<cursor.show>", 426 - ] 427 - `; 428 - 429 - exports[`password (isCI = true) > renders message 1`] = ` 430 - [ 431 - "<cursor.hide>", 432 - "<dim>│</fg> 433 - <cyan>◆</fg> foo 434 - <cyan>│</fg> _ 435 - <cyan>└</fg> 436 - ", 437 - "<cursor.backward count=999><cursor.up count=4>", 438 - "<cursor.down count=1>", 439 - "<erase.down>", 440 - "<green>◇</fg> foo 441 - <dim>│</fg> ", 442 - " 443 - ", 444 - "<cursor.show>", 445 - ] 446 - `; 447 - 448 - exports[`password (isCI = true) > withGuide: false removes guide 1`] = ` 449 - [ 450 - "<cursor.hide>", 451 - "<cyan>◆</fg> foo 452 - _ 453 - 454 - ", 455 - "<cursor.backward count=999><cursor.up count=3>", 456 - "<erase.down>", 457 - "<green>◇</fg> foo 458 - ", 459 - " 460 - ", 461 - "<cursor.show>", 462 - ] 463 - `;
-643
packages/prompts/test/__snapshots__/path.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`text (isCI = false) > can cancel 1`] = ` 4 - [ 5 - "<cursor.hide>", 6 - "<dim>│</fg> 7 - <cyan>◆</fg> foo 8 - <cyan>│</fg> 9 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 10 - <cyan>│</fg> <green>●</fg> /tmp/bar 11 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 12 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 13 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 14 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 15 - <cyan>└</fg>", 16 - "<cursor.backward count=999><cursor.up count=9>", 17 - "<cursor.down count=1>", 18 - "<erase.down>", 19 - "<red>■</fg> foo 20 - <dim>│</fg> <dim>/tmp/</bold>", 21 - " 22 - ", 23 - "<cursor.show>", 24 - ] 25 - `; 26 - 27 - exports[`text (isCI = false) > cannot submit unknown value 1`] = ` 28 - [ 29 - "<cursor.hide>", 30 - "<dim>│</fg> 31 - <cyan>◆</fg> foo 32 - <cyan>│</fg> 33 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 34 - <cyan>│</fg> <green>●</fg> /tmp/bar 35 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 36 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 37 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 38 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 39 - <cyan>└</fg>", 40 - "<cursor.backward count=999><cursor.up count=9>", 41 - "<cursor.down count=3>", 42 - "<erase.down>", 43 - "<cyan>│</fg> <dim>Search:</bold> /tmp/_█ 44 - <cyan>│</fg> <yellow>No matches found</fg> 45 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 46 - <cyan>└</fg>", 47 - "<cursor.backward count=999><cursor.up count=6>", 48 - "<cursor.down count=1>", 49 - "<erase.down>", 50 - "<yellow>▲</fg> foo 51 - <yellow>│</fg> 52 - <yellow>│</fg> <dim>Search:</bold> /tmp/_█ 53 - <yellow>│</fg> <yellow>No matches found</fg> 54 - <yellow>│</fg> <yellow>Please select a path</fg> 55 - <yellow>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 56 - <yellow>└</fg>", 57 - "<cursor.backward count=999><cursor.up count=7>", 58 - "<cursor.down count=1>", 59 - "<erase.down>", 60 - "<cyan>◆</fg> foo 61 - <cyan>│</fg> 62 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 63 - <cyan>│</fg> <green>●</fg> /tmp/bar 64 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 65 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 66 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 67 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 68 - <cyan>└</fg>", 69 - "<cursor.backward count=999><cursor.up count=9>", 70 - "<cursor.down count=3>", 71 - "<erase.down>", 72 - "<cyan>│</fg> <dim>Search:</bold> /tmp/b█ 73 - <cyan>│</fg> <green>●</fg> /tmp/bar 74 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 75 - <cyan>└</fg>", 76 - "<cursor.backward count=999><cursor.up count=6>", 77 - "<cursor.down count=1>", 78 - "<erase.down>", 79 - "<green>◇</fg> foo 80 - <dim>│</fg> <dim>/tmp/bar</bold>", 81 - " 82 - ", 83 - "<cursor.show>", 84 - ] 85 - `; 86 - 87 - exports[`text (isCI = false) > initialValue sets the value 1`] = ` 88 - [ 89 - "<cursor.hide>", 90 - "<dim>│</fg> 91 - <cyan>◆</fg> foo 92 - <cyan>│</fg> 93 - <cyan>│</fg> <dim>Search:</bold> /tmp/bar█ 94 - <cyan>│</fg> <green>●</fg> /tmp/bar 95 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 96 - <cyan>└</fg>", 97 - "<cursor.backward count=999><cursor.up count=6>", 98 - "<cursor.down count=1>", 99 - "<erase.down>", 100 - "<green>◇</fg> foo 101 - <dim>│</fg> <dim>/tmp/bar</bold>", 102 - " 103 - ", 104 - "<cursor.show>", 105 - ] 106 - `; 107 - 108 - exports[`text (isCI = false) > renders cancelled value if one set 1`] = ` 109 - [ 110 - "<cursor.hide>", 111 - "<dim>│</fg> 112 - <cyan>◆</fg> foo 113 - <cyan>│</fg> 114 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 115 - <cyan>│</fg> <green>●</fg> /tmp/bar 116 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 117 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 118 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 119 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 120 - <cyan>└</fg>", 121 - "<cursor.backward count=999><cursor.up count=9>", 122 - "<cursor.down count=3>", 123 - "<erase.down>", 124 - "<cyan>│</fg> <dim>Search:</bold> /tmp/x█ 125 - <cyan>│</fg> <yellow>No matches found</fg> 126 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 127 - <cyan>└</fg>", 128 - "<cursor.backward count=999><cursor.up count=6>", 129 - "<cursor.down count=3>", 130 - "<erase.line><cursor.left count=1>", 131 - "<cyan>│</fg> <dim>Search:</bold> /tmp/xy█", 132 - "<cursor.down count=3>", 133 - "<cursor.backward count=999><cursor.up count=6>", 134 - "<cursor.down count=1>", 135 - "<erase.down>", 136 - "<red>■</fg> foo 137 - <dim>│</fg> <dim>/tmp/xy</bold>", 138 - " 139 - ", 140 - "<cursor.show>", 141 - ] 142 - `; 143 - 144 - exports[`text (isCI = false) > renders message 1`] = ` 145 - [ 146 - "<cursor.hide>", 147 - "<dim>│</fg> 148 - <cyan>◆</fg> foo 149 - <cyan>│</fg> 150 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 151 - <cyan>│</fg> <green>●</fg> /tmp/bar 152 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 153 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 154 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 155 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 156 - <cyan>└</fg>", 157 - "<cursor.backward count=999><cursor.up count=9>", 158 - "<cursor.down count=1>", 159 - "<erase.down>", 160 - "<green>◇</fg> foo 161 - <dim>│</fg> <dim>/tmp/bar</bold>", 162 - " 163 - ", 164 - "<cursor.show>", 165 - ] 166 - `; 167 - 168 - exports[`text (isCI = false) > renders submitted value 1`] = ` 169 - [ 170 - "<cursor.hide>", 171 - "<dim>│</fg> 172 - <cyan>◆</fg> foo 173 - <cyan>│</fg> 174 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 175 - <cyan>│</fg> <green>●</fg> /tmp/bar 176 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 177 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 178 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 179 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 180 - <cyan>└</fg>", 181 - "<cursor.backward count=999><cursor.up count=9>", 182 - "<cursor.down count=3>", 183 - "<erase.down>", 184 - "<cyan>│</fg> <dim>Search:</bold> /tmp/b█ 185 - <cyan>│</fg> <green>●</fg> /tmp/bar 186 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 187 - <cyan>└</fg>", 188 - "<cursor.backward count=999><cursor.up count=6>", 189 - "<cursor.down count=3>", 190 - "<erase.line><cursor.left count=1>", 191 - "<cyan>│</fg> <dim>Search:</bold> /tmp/ba█", 192 - "<cursor.down count=3>", 193 - "<cursor.backward count=999><cursor.up count=6>", 194 - "<cursor.down count=1>", 195 - "<erase.down>", 196 - "<green>◇</fg> foo 197 - <dim>│</fg> <dim>/tmp/bar</bold>", 198 - " 199 - ", 200 - "<cursor.show>", 201 - ] 202 - `; 203 - 204 - exports[`text (isCI = false) > validation errors render and clear (using Error) 1`] = ` 205 - [ 206 - "<cursor.hide>", 207 - "<dim>│</fg> 208 - <cyan>◆</fg> foo 209 - <cyan>│</fg> 210 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 211 - <cyan>│</fg> <green>●</fg> /tmp/bar 212 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 213 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 214 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 215 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 216 - <cyan>└</fg>", 217 - "<cursor.backward count=999><cursor.up count=9>", 218 - "<cursor.down count=3>", 219 - "<erase.down>", 220 - "<cyan>│</fg> <dim>Search:</bold> /tmp/r█ 221 - <cyan>│</fg> <green>●</fg> /tmp/root.zip 222 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 223 - <cyan>└</fg>", 224 - "<cursor.backward count=999><cursor.up count=6>", 225 - "<cursor.down count=1>", 226 - "<erase.down>", 227 - "<yellow>▲</fg> foo 228 - <yellow>│</fg> 229 - <yellow>│</fg> <dim>Search:</bold> /tmp/r█ 230 - <yellow>│</fg> <yellow>should be /tmp/bar</fg> 231 - <yellow>│</fg> <green>●</fg> /tmp/root.zip 232 - <yellow>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 233 - <yellow>└</fg>", 234 - "<cursor.backward count=999><cursor.up count=7>", 235 - "<cursor.down count=1>", 236 - "<erase.down>", 237 - "<cyan>◆</fg> foo 238 - <cyan>│</fg> 239 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 240 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/bar</bold> 241 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 242 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 243 - <cyan>│</fg> <green>●</fg> /tmp/root.zip 244 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 245 - <cyan>└</fg>", 246 - "<cursor.backward count=999><cursor.up count=9>", 247 - "<cursor.down count=3>", 248 - "<erase.down>", 249 - "<cyan>│</fg> <dim>Search:</bold> /tmp/b█ 250 - <cyan>│</fg> <green>●</fg> /tmp/bar 251 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 252 - <cyan>└</fg>", 253 - "<cursor.backward count=999><cursor.up count=6>", 254 - "<cursor.down count=1>", 255 - "<erase.down>", 256 - "<green>◇</fg> foo 257 - <dim>│</fg> <dim>/tmp/bar</bold>", 258 - " 259 - ", 260 - "<cursor.show>", 261 - ] 262 - `; 263 - 264 - exports[`text (isCI = false) > validation errors render and clear 1`] = ` 265 - [ 266 - "<cursor.hide>", 267 - "<dim>│</fg> 268 - <cyan>◆</fg> foo 269 - <cyan>│</fg> 270 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 271 - <cyan>│</fg> <green>●</fg> /tmp/bar 272 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 273 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 274 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 275 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 276 - <cyan>└</fg>", 277 - "<cursor.backward count=999><cursor.up count=9>", 278 - "<cursor.down count=3>", 279 - "<erase.down>", 280 - "<cyan>│</fg> <dim>Search:</bold> /tmp/r█ 281 - <cyan>│</fg> <green>●</fg> /tmp/root.zip 282 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 283 - <cyan>└</fg>", 284 - "<cursor.backward count=999><cursor.up count=6>", 285 - "<cursor.down count=1>", 286 - "<erase.down>", 287 - "<yellow>▲</fg> foo 288 - <yellow>│</fg> 289 - <yellow>│</fg> <dim>Search:</bold> /tmp/r█ 290 - <yellow>│</fg> <yellow>should be /tmp/bar</fg> 291 - <yellow>│</fg> <green>●</fg> /tmp/root.zip 292 - <yellow>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 293 - <yellow>└</fg>", 294 - "<cursor.backward count=999><cursor.up count=7>", 295 - "<cursor.down count=1>", 296 - "<erase.down>", 297 - "<cyan>◆</fg> foo 298 - <cyan>│</fg> 299 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 300 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/bar</bold> 301 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 302 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 303 - <cyan>│</fg> <green>●</fg> /tmp/root.zip 304 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 305 - <cyan>└</fg>", 306 - "<cursor.backward count=999><cursor.up count=9>", 307 - "<cursor.down count=3>", 308 - "<erase.down>", 309 - "<cyan>│</fg> <dim>Search:</bold> /tmp/b█ 310 - <cyan>│</fg> <green>●</fg> /tmp/bar 311 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 312 - <cyan>└</fg>", 313 - "<cursor.backward count=999><cursor.up count=6>", 314 - "<cursor.down count=1>", 315 - "<erase.down>", 316 - "<green>◇</fg> foo 317 - <dim>│</fg> <dim>/tmp/bar</bold>", 318 - " 319 - ", 320 - "<cursor.show>", 321 - ] 322 - `; 323 - 324 - exports[`text (isCI = true) > can cancel 1`] = ` 325 - [ 326 - "<cursor.hide>", 327 - "<dim>│</fg> 328 - <cyan>◆</fg> foo 329 - <cyan>│</fg> 330 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 331 - <cyan>│</fg> <green>●</fg> /tmp/bar 332 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 333 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 334 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 335 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 336 - <cyan>└</fg>", 337 - "<cursor.backward count=999><cursor.up count=9>", 338 - "<cursor.down count=1>", 339 - "<erase.down>", 340 - "<red>■</fg> foo 341 - <dim>│</fg> <dim>/tmp/</bold>", 342 - " 343 - ", 344 - "<cursor.show>", 345 - ] 346 - `; 347 - 348 - exports[`text (isCI = true) > cannot submit unknown value 1`] = ` 349 - [ 350 - "<cursor.hide>", 351 - "<dim>│</fg> 352 - <cyan>◆</fg> foo 353 - <cyan>│</fg> 354 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 355 - <cyan>│</fg> <green>●</fg> /tmp/bar 356 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 357 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 358 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 359 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 360 - <cyan>└</fg>", 361 - "<cursor.backward count=999><cursor.up count=9>", 362 - "<cursor.down count=3>", 363 - "<erase.down>", 364 - "<cyan>│</fg> <dim>Search:</bold> /tmp/_█ 365 - <cyan>│</fg> <yellow>No matches found</fg> 366 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 367 - <cyan>└</fg>", 368 - "<cursor.backward count=999><cursor.up count=6>", 369 - "<cursor.down count=1>", 370 - "<erase.down>", 371 - "<yellow>▲</fg> foo 372 - <yellow>│</fg> 373 - <yellow>│</fg> <dim>Search:</bold> /tmp/_█ 374 - <yellow>│</fg> <yellow>No matches found</fg> 375 - <yellow>│</fg> <yellow>Please select a path</fg> 376 - <yellow>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 377 - <yellow>└</fg>", 378 - "<cursor.backward count=999><cursor.up count=7>", 379 - "<cursor.down count=1>", 380 - "<erase.down>", 381 - "<cyan>◆</fg> foo 382 - <cyan>│</fg> 383 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 384 - <cyan>│</fg> <green>●</fg> /tmp/bar 385 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 386 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 387 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 388 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 389 - <cyan>└</fg>", 390 - "<cursor.backward count=999><cursor.up count=9>", 391 - "<cursor.down count=3>", 392 - "<erase.down>", 393 - "<cyan>│</fg> <dim>Search:</bold> /tmp/b█ 394 - <cyan>│</fg> <green>●</fg> /tmp/bar 395 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 396 - <cyan>└</fg>", 397 - "<cursor.backward count=999><cursor.up count=6>", 398 - "<cursor.down count=1>", 399 - "<erase.down>", 400 - "<green>◇</fg> foo 401 - <dim>│</fg> <dim>/tmp/bar</bold>", 402 - " 403 - ", 404 - "<cursor.show>", 405 - ] 406 - `; 407 - 408 - exports[`text (isCI = true) > initialValue sets the value 1`] = ` 409 - [ 410 - "<cursor.hide>", 411 - "<dim>│</fg> 412 - <cyan>◆</fg> foo 413 - <cyan>│</fg> 414 - <cyan>│</fg> <dim>Search:</bold> /tmp/bar█ 415 - <cyan>│</fg> <green>●</fg> /tmp/bar 416 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 417 - <cyan>└</fg>", 418 - "<cursor.backward count=999><cursor.up count=6>", 419 - "<cursor.down count=1>", 420 - "<erase.down>", 421 - "<green>◇</fg> foo 422 - <dim>│</fg> <dim>/tmp/bar</bold>", 423 - " 424 - ", 425 - "<cursor.show>", 426 - ] 427 - `; 428 - 429 - exports[`text (isCI = true) > renders cancelled value if one set 1`] = ` 430 - [ 431 - "<cursor.hide>", 432 - "<dim>│</fg> 433 - <cyan>◆</fg> foo 434 - <cyan>│</fg> 435 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 436 - <cyan>│</fg> <green>●</fg> /tmp/bar 437 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 438 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 439 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 440 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 441 - <cyan>└</fg>", 442 - "<cursor.backward count=999><cursor.up count=9>", 443 - "<cursor.down count=3>", 444 - "<erase.down>", 445 - "<cyan>│</fg> <dim>Search:</bold> /tmp/x█ 446 - <cyan>│</fg> <yellow>No matches found</fg> 447 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 448 - <cyan>└</fg>", 449 - "<cursor.backward count=999><cursor.up count=6>", 450 - "<cursor.down count=3>", 451 - "<erase.line><cursor.left count=1>", 452 - "<cyan>│</fg> <dim>Search:</bold> /tmp/xy█", 453 - "<cursor.down count=3>", 454 - "<cursor.backward count=999><cursor.up count=6>", 455 - "<cursor.down count=1>", 456 - "<erase.down>", 457 - "<red>■</fg> foo 458 - <dim>│</fg> <dim>/tmp/xy</bold>", 459 - " 460 - ", 461 - "<cursor.show>", 462 - ] 463 - `; 464 - 465 - exports[`text (isCI = true) > renders message 1`] = ` 466 - [ 467 - "<cursor.hide>", 468 - "<dim>│</fg> 469 - <cyan>◆</fg> foo 470 - <cyan>│</fg> 471 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 472 - <cyan>│</fg> <green>●</fg> /tmp/bar 473 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 474 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 475 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 476 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 477 - <cyan>└</fg>", 478 - "<cursor.backward count=999><cursor.up count=9>", 479 - "<cursor.down count=1>", 480 - "<erase.down>", 481 - "<green>◇</fg> foo 482 - <dim>│</fg> <dim>/tmp/bar</bold>", 483 - " 484 - ", 485 - "<cursor.show>", 486 - ] 487 - `; 488 - 489 - exports[`text (isCI = true) > renders submitted value 1`] = ` 490 - [ 491 - "<cursor.hide>", 492 - "<dim>│</fg> 493 - <cyan>◆</fg> foo 494 - <cyan>│</fg> 495 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 496 - <cyan>│</fg> <green>●</fg> /tmp/bar 497 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 498 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 499 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 500 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 501 - <cyan>└</fg>", 502 - "<cursor.backward count=999><cursor.up count=9>", 503 - "<cursor.down count=3>", 504 - "<erase.down>", 505 - "<cyan>│</fg> <dim>Search:</bold> /tmp/b█ 506 - <cyan>│</fg> <green>●</fg> /tmp/bar 507 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 508 - <cyan>└</fg>", 509 - "<cursor.backward count=999><cursor.up count=6>", 510 - "<cursor.down count=3>", 511 - "<erase.line><cursor.left count=1>", 512 - "<cyan>│</fg> <dim>Search:</bold> /tmp/ba█", 513 - "<cursor.down count=3>", 514 - "<cursor.backward count=999><cursor.up count=6>", 515 - "<cursor.down count=1>", 516 - "<erase.down>", 517 - "<green>◇</fg> foo 518 - <dim>│</fg> <dim>/tmp/bar</bold>", 519 - " 520 - ", 521 - "<cursor.show>", 522 - ] 523 - `; 524 - 525 - exports[`text (isCI = true) > validation errors render and clear (using Error) 1`] = ` 526 - [ 527 - "<cursor.hide>", 528 - "<dim>│</fg> 529 - <cyan>◆</fg> foo 530 - <cyan>│</fg> 531 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 532 - <cyan>│</fg> <green>●</fg> /tmp/bar 533 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 534 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 535 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 536 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 537 - <cyan>└</fg>", 538 - "<cursor.backward count=999><cursor.up count=9>", 539 - "<cursor.down count=3>", 540 - "<erase.down>", 541 - "<cyan>│</fg> <dim>Search:</bold> /tmp/r█ 542 - <cyan>│</fg> <green>●</fg> /tmp/root.zip 543 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 544 - <cyan>└</fg>", 545 - "<cursor.backward count=999><cursor.up count=6>", 546 - "<cursor.down count=1>", 547 - "<erase.down>", 548 - "<yellow>▲</fg> foo 549 - <yellow>│</fg> 550 - <yellow>│</fg> <dim>Search:</bold> /tmp/r█ 551 - <yellow>│</fg> <yellow>should be /tmp/bar</fg> 552 - <yellow>│</fg> <green>●</fg> /tmp/root.zip 553 - <yellow>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 554 - <yellow>└</fg>", 555 - "<cursor.backward count=999><cursor.up count=7>", 556 - "<cursor.down count=1>", 557 - "<erase.down>", 558 - "<cyan>◆</fg> foo 559 - <cyan>│</fg> 560 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 561 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/bar</bold> 562 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 563 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 564 - <cyan>│</fg> <green>●</fg> /tmp/root.zip 565 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 566 - <cyan>└</fg>", 567 - "<cursor.backward count=999><cursor.up count=9>", 568 - "<cursor.down count=3>", 569 - "<erase.down>", 570 - "<cyan>│</fg> <dim>Search:</bold> /tmp/b█ 571 - <cyan>│</fg> <green>●</fg> /tmp/bar 572 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 573 - <cyan>└</fg>", 574 - "<cursor.backward count=999><cursor.up count=6>", 575 - "<cursor.down count=1>", 576 - "<erase.down>", 577 - "<green>◇</fg> foo 578 - <dim>│</fg> <dim>/tmp/bar</bold>", 579 - " 580 - ", 581 - "<cursor.show>", 582 - ] 583 - `; 584 - 585 - exports[`text (isCI = true) > validation errors render and clear 1`] = ` 586 - [ 587 - "<cursor.hide>", 588 - "<dim>│</fg> 589 - <cyan>◆</fg> foo 590 - <cyan>│</fg> 591 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 592 - <cyan>│</fg> <green>●</fg> /tmp/bar 593 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 594 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 595 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/root.zip</bold> 596 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 597 - <cyan>└</fg>", 598 - "<cursor.backward count=999><cursor.up count=9>", 599 - "<cursor.down count=3>", 600 - "<erase.down>", 601 - "<cyan>│</fg> <dim>Search:</bold> /tmp/r█ 602 - <cyan>│</fg> <green>●</fg> /tmp/root.zip 603 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 604 - <cyan>└</fg>", 605 - "<cursor.backward count=999><cursor.up count=6>", 606 - "<cursor.down count=1>", 607 - "<erase.down>", 608 - "<yellow>▲</fg> foo 609 - <yellow>│</fg> 610 - <yellow>│</fg> <dim>Search:</bold> /tmp/r█ 611 - <yellow>│</fg> <yellow>should be /tmp/bar</fg> 612 - <yellow>│</fg> <green>●</fg> /tmp/root.zip 613 - <yellow>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 614 - <yellow>└</fg>", 615 - "<cursor.backward count=999><cursor.up count=7>", 616 - "<cursor.down count=1>", 617 - "<erase.down>", 618 - "<cyan>◆</fg> foo 619 - <cyan>│</fg> 620 - <cyan>│</fg> <dim>Search:</bold> /tmp/█ 621 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/bar</bold> 622 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/foo</bold> 623 - <cyan>│</fg> <dim>○</bold> <dim>/tmp/hello</bold> 624 - <cyan>│</fg> <green>●</fg> /tmp/root.zip 625 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 626 - <cyan>└</fg>", 627 - "<cursor.backward count=999><cursor.up count=9>", 628 - "<cursor.down count=3>", 629 - "<erase.down>", 630 - "<cyan>│</fg> <dim>Search:</bold> /tmp/b█ 631 - <cyan>│</fg> <green>●</fg> /tmp/bar 632 - <cyan>│</fg> <dim>↑/↓</bold> to select • <dim>Enter:</bold> confirm • <dim>Type:</bold> to search 633 - <cyan>└</fg>", 634 - "<cursor.backward count=999><cursor.up count=6>", 635 - "<cursor.down count=1>", 636 - "<erase.down>", 637 - "<green>◇</fg> foo 638 - <dim>│</fg> <dim>/tmp/bar</bold>", 639 - " 640 - ", 641 - "<cursor.show>", 642 - ] 643 - `;
-586
packages/prompts/test/__snapshots__/progress-bar.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`prompts - progress (isCI = false) > message > sets message for next frame 1`] = ` 4 - [ 5 - "<cursor.hide>", 6 - "<dim>│</fg> 7 - ", 8 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ", 9 - "<cursor.left count=1>", 10 - "<erase.down>", 11 - "<magenta>◐</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> foo", 12 - ] 13 - `; 14 - 15 - exports[`prompts - progress (isCI = false) > process exit handling > prioritizes cancel option over global setting 1`] = ` 16 - [ 17 - "<cursor.hide>", 18 - "<dim>│</fg> 19 - ", 20 - "<red>■</fg> Progress cancel message 21 - ", 22 - "<cursor.show>", 23 - ] 24 - `; 25 - 26 - exports[`prompts - progress (isCI = false) > process exit handling > prioritizes error option over global setting 1`] = ` 27 - [ 28 - "<cursor.hide>", 29 - "<dim>│</fg> 30 - ", 31 - "<red>▲</fg> Progress error message 32 - ", 33 - "<cursor.show>", 34 - ] 35 - `; 36 - 37 - exports[`prompts - progress (isCI = false) > process exit handling > uses custom cancel message when provided directly 1`] = ` 38 - [ 39 - "<cursor.hide>", 40 - "<dim>│</fg> 41 - ", 42 - "<red>■</fg> Custom cancel message 43 - ", 44 - "<cursor.show>", 45 - ] 46 - `; 47 - 48 - exports[`prompts - progress (isCI = false) > process exit handling > uses custom error message when provided directly 1`] = ` 49 - [ 50 - "<cursor.hide>", 51 - "<dim>│</fg> 52 - ", 53 - "<red>▲</fg> Custom error message 54 - ", 55 - "<cursor.show>", 56 - ] 57 - `; 58 - 59 - exports[`prompts - progress (isCI = false) > process exit handling > uses default cancel message 1`] = ` 60 - [ 61 - "<cursor.hide>", 62 - "<dim>│</fg> 63 - ", 64 - "<red>■</fg> Canceled 65 - ", 66 - "<cursor.show>", 67 - ] 68 - `; 69 - 70 - exports[`prompts - progress (isCI = false) > process exit handling > uses global custom cancel message from settings 1`] = ` 71 - [ 72 - "<cursor.hide>", 73 - "<dim>│</fg> 74 - ", 75 - "<red>■</fg> Global cancel message 76 - ", 77 - "<cursor.show>", 78 - ] 79 - `; 80 - 81 - exports[`prompts - progress (isCI = false) > process exit handling > uses global custom error message from settings 1`] = ` 82 - [ 83 - "<cursor.hide>", 84 - "<dim>│</fg> 85 - ", 86 - "<red>▲</fg> Global error message 87 - ", 88 - "<cursor.show>", 89 - ] 90 - `; 91 - 92 - exports[`prompts - progress (isCI = false) > start > renders frames at interval 1`] = ` 93 - [ 94 - "<cursor.hide>", 95 - "<dim>│</fg> 96 - ", 97 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ", 98 - "<cursor.left count=1>", 99 - "<erase.down>", 100 - "<magenta>◐</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ", 101 - "<cursor.left count=1>", 102 - "<erase.down>", 103 - "<magenta>◓</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ", 104 - "<cursor.left count=1>", 105 - "<erase.down>", 106 - "<magenta>◑</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ", 107 - ] 108 - `; 109 - 110 - exports[`prompts - progress (isCI = false) > start > renders message 1`] = ` 111 - [ 112 - "<cursor.hide>", 113 - "<dim>│</fg> 114 - ", 115 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> foo", 116 - ] 117 - `; 118 - 119 - exports[`prompts - progress (isCI = false) > start > renders timer when indicator is "timer" 1`] = ` 120 - [ 121 - "<cursor.hide>", 122 - "<dim>│</fg> 123 - ", 124 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> [0s]", 125 - ] 126 - `; 127 - 128 - exports[`prompts - progress (isCI = false) > stop > renders cancel symbol when calling cancel() 1`] = ` 129 - [ 130 - "<cursor.hide>", 131 - "<dim>│</fg> 132 - ", 133 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ", 134 - "<cursor.left count=1>", 135 - "<erase.down>", 136 - "<red>■</fg> 137 - ", 138 - "<cursor.show>", 139 - ] 140 - `; 141 - 142 - exports[`prompts - progress (isCI = false) > stop > renders error symbol when calling error() 1`] = ` 143 - [ 144 - "<cursor.hide>", 145 - "<dim>│</fg> 146 - ", 147 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ", 148 - "<cursor.left count=1>", 149 - "<erase.down>", 150 - "<red>▲</fg> 151 - ", 152 - "<cursor.show>", 153 - ] 154 - `; 155 - 156 - exports[`prompts - progress (isCI = false) > stop > renders message 1`] = ` 157 - [ 158 - "<cursor.hide>", 159 - "<dim>│</fg> 160 - ", 161 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ", 162 - "<cursor.left count=1>", 163 - "<erase.down>", 164 - "<green>◇</fg> foo 165 - ", 166 - "<cursor.show>", 167 - ] 168 - `; 169 - 170 - exports[`prompts - progress (isCI = false) > stop > renders message when cancelling 1`] = ` 171 - [ 172 - "<cursor.hide>", 173 - "<dim>│</fg> 174 - ", 175 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ", 176 - "<cursor.left count=1>", 177 - "<erase.down>", 178 - "<red>■</fg> cancelled :-( 179 - ", 180 - "<cursor.show>", 181 - ] 182 - `; 183 - 184 - exports[`prompts - progress (isCI = false) > stop > renders message when erroring 1`] = ` 185 - [ 186 - "<cursor.hide>", 187 - "<dim>│</fg> 188 - ", 189 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ", 190 - "<cursor.left count=1>", 191 - "<erase.down>", 192 - "<red>▲</fg> FATAL ERROR! 193 - ", 194 - "<cursor.show>", 195 - ] 196 - `; 197 - 198 - exports[`prompts - progress (isCI = false) > stop > renders message without removing dots 1`] = ` 199 - [ 200 - "<cursor.hide>", 201 - "<dim>│</fg> 202 - ", 203 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ", 204 - "<cursor.left count=1>", 205 - "<erase.down>", 206 - "<green>◇</fg> foo. 207 - ", 208 - "<cursor.show>", 209 - ] 210 - `; 211 - 212 - exports[`prompts - progress (isCI = false) > stop > renders submit symbol and stops progress 1`] = ` 213 - [ 214 - "<cursor.hide>", 215 - "<dim>│</fg> 216 - ", 217 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ", 218 - "<cursor.left count=1>", 219 - "<erase.down>", 220 - "<green>◇</fg> 221 - ", 222 - "<cursor.show>", 223 - ] 224 - `; 225 - 226 - exports[`prompts - progress (isCI = false) > style > renders block progressbar 1`] = ` 227 - [ 228 - "<cursor.hide>", 229 - "<dim>│</fg> 230 - ", 231 - "<magenta>◒</fg> <magenta></fg><dim>██████████</bold> ", 232 - "<cursor.left count=1>", 233 - "<erase.down>", 234 - "<magenta>◐</fg> <magenta></fg><dim>██████████</bold> ", 235 - "<cursor.left count=1>", 236 - "<erase.down>", 237 - "<magenta>◓</fg> <magenta>█████</fg><dim>█████</bold> ", 238 - "<cursor.left count=1>", 239 - "<erase.down>", 240 - "<magenta>◑</fg> <magenta>█████</fg><dim>█████</bold> ", 241 - "<cursor.left count=1>", 242 - "<erase.down>", 243 - "<green>◇</fg> 244 - ", 245 - "<cursor.show>", 246 - ] 247 - `; 248 - 249 - exports[`prompts - progress (isCI = false) > style > renders heavy progressbar 1`] = ` 250 - [ 251 - "<cursor.hide>", 252 - "<dim>│</fg> 253 - ", 254 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━</bold> ", 255 - "<cursor.left count=1>", 256 - "<erase.down>", 257 - "<magenta>◐</fg> <magenta></fg><dim>━━━━━━━━━━</bold> ", 258 - "<cursor.left count=1>", 259 - "<erase.down>", 260 - "<magenta>◓</fg> <magenta>━━━━━</fg><dim>━━━━━</bold> ", 261 - "<cursor.left count=1>", 262 - "<erase.down>", 263 - "<magenta>◑</fg> <magenta>━━━━━</fg><dim>━━━━━</bold> ", 264 - "<cursor.left count=1>", 265 - "<erase.down>", 266 - "<green>◇</fg> 267 - ", 268 - "<cursor.show>", 269 - ] 270 - `; 271 - 272 - exports[`prompts - progress (isCI = false) > style > renders light progressbar 1`] = ` 273 - [ 274 - "<cursor.hide>", 275 - "<dim>│</fg> 276 - ", 277 - "<magenta>◒</fg> <magenta></fg><dim>──────────</bold> ", 278 - "<cursor.left count=1>", 279 - "<erase.down>", 280 - "<magenta>◐</fg> <magenta></fg><dim>──────────</bold> ", 281 - "<cursor.left count=1>", 282 - "<erase.down>", 283 - "<magenta>◓</fg> <magenta>─────</fg><dim>─────</bold> ", 284 - "<cursor.left count=1>", 285 - "<erase.down>", 286 - "<magenta>◑</fg> <magenta>─────</fg><dim>─────</bold> ", 287 - "<cursor.left count=1>", 288 - "<erase.down>", 289 - "<green>◇</fg> 290 - ", 291 - "<cursor.show>", 292 - ] 293 - `; 294 - 295 - exports[`prompts - progress (isCI = true) > message > sets message for next frame 1`] = ` 296 - [ 297 - "<cursor.hide>", 298 - "<dim>│</fg> 299 - ", 300 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ...", 301 - " 302 - ", 303 - "<cursor.left count=1>", 304 - "<erase.down>", 305 - "<magenta>◐</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> foo...", 306 - ] 307 - `; 308 - 309 - exports[`prompts - progress (isCI = true) > process exit handling > prioritizes cancel option over global setting 1`] = ` 310 - [ 311 - "<cursor.hide>", 312 - "<dim>│</fg> 313 - ", 314 - "<red>■</fg> Progress cancel message 315 - ", 316 - "<cursor.show>", 317 - ] 318 - `; 319 - 320 - exports[`prompts - progress (isCI = true) > process exit handling > prioritizes error option over global setting 1`] = ` 321 - [ 322 - "<cursor.hide>", 323 - "<dim>│</fg> 324 - ", 325 - "<red>▲</fg> Progress error message 326 - ", 327 - "<cursor.show>", 328 - ] 329 - `; 330 - 331 - exports[`prompts - progress (isCI = true) > process exit handling > uses custom cancel message when provided directly 1`] = ` 332 - [ 333 - "<cursor.hide>", 334 - "<dim>│</fg> 335 - ", 336 - "<red>■</fg> Custom cancel message 337 - ", 338 - "<cursor.show>", 339 - ] 340 - `; 341 - 342 - exports[`prompts - progress (isCI = true) > process exit handling > uses custom error message when provided directly 1`] = ` 343 - [ 344 - "<cursor.hide>", 345 - "<dim>│</fg> 346 - ", 347 - "<red>▲</fg> Custom error message 348 - ", 349 - "<cursor.show>", 350 - ] 351 - `; 352 - 353 - exports[`prompts - progress (isCI = true) > process exit handling > uses default cancel message 1`] = ` 354 - [ 355 - "<cursor.hide>", 356 - "<dim>│</fg> 357 - ", 358 - "<red>■</fg> Canceled 359 - ", 360 - "<cursor.show>", 361 - ] 362 - `; 363 - 364 - exports[`prompts - progress (isCI = true) > process exit handling > uses global custom cancel message from settings 1`] = ` 365 - [ 366 - "<cursor.hide>", 367 - "<dim>│</fg> 368 - ", 369 - "<red>■</fg> Global cancel message 370 - ", 371 - "<cursor.show>", 372 - ] 373 - `; 374 - 375 - exports[`prompts - progress (isCI = true) > process exit handling > uses global custom error message from settings 1`] = ` 376 - [ 377 - "<cursor.hide>", 378 - "<dim>│</fg> 379 - ", 380 - "<red>▲</fg> Global error message 381 - ", 382 - "<cursor.show>", 383 - ] 384 - `; 385 - 386 - exports[`prompts - progress (isCI = true) > start > renders frames at interval 1`] = ` 387 - [ 388 - "<cursor.hide>", 389 - "<dim>│</fg> 390 - ", 391 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ...", 392 - ] 393 - `; 394 - 395 - exports[`prompts - progress (isCI = true) > start > renders message 1`] = ` 396 - [ 397 - "<cursor.hide>", 398 - "<dim>│</fg> 399 - ", 400 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> foo...", 401 - ] 402 - `; 403 - 404 - exports[`prompts - progress (isCI = true) > start > renders timer when indicator is "timer" 1`] = ` 405 - [ 406 - "<cursor.hide>", 407 - "<dim>│</fg> 408 - ", 409 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ...", 410 - ] 411 - `; 412 - 413 - exports[`prompts - progress (isCI = true) > stop > renders cancel symbol when calling cancel() 1`] = ` 414 - [ 415 - "<cursor.hide>", 416 - "<dim>│</fg> 417 - ", 418 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ...", 419 - " 420 - ", 421 - "<cursor.left count=1>", 422 - "<erase.down>", 423 - "<red>■</fg> 424 - ", 425 - "<cursor.show>", 426 - ] 427 - `; 428 - 429 - exports[`prompts - progress (isCI = true) > stop > renders error symbol when calling error() 1`] = ` 430 - [ 431 - "<cursor.hide>", 432 - "<dim>│</fg> 433 - ", 434 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ...", 435 - " 436 - ", 437 - "<cursor.left count=1>", 438 - "<erase.down>", 439 - "<red>▲</fg> 440 - ", 441 - "<cursor.show>", 442 - ] 443 - `; 444 - 445 - exports[`prompts - progress (isCI = true) > stop > renders message 1`] = ` 446 - [ 447 - "<cursor.hide>", 448 - "<dim>│</fg> 449 - ", 450 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ...", 451 - " 452 - ", 453 - "<cursor.left count=1>", 454 - "<erase.down>", 455 - "<green>◇</fg> foo 456 - ", 457 - "<cursor.show>", 458 - ] 459 - `; 460 - 461 - exports[`prompts - progress (isCI = true) > stop > renders message when cancelling 1`] = ` 462 - [ 463 - "<cursor.hide>", 464 - "<dim>│</fg> 465 - ", 466 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ...", 467 - " 468 - ", 469 - "<cursor.left count=1>", 470 - "<erase.down>", 471 - "<red>■</fg> cancelled :-( 472 - ", 473 - "<cursor.show>", 474 - ] 475 - `; 476 - 477 - exports[`prompts - progress (isCI = true) > stop > renders message when erroring 1`] = ` 478 - [ 479 - "<cursor.hide>", 480 - "<dim>│</fg> 481 - ", 482 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ...", 483 - " 484 - ", 485 - "<cursor.left count=1>", 486 - "<erase.down>", 487 - "<red>▲</fg> FATAL ERROR! 488 - ", 489 - "<cursor.show>", 490 - ] 491 - `; 492 - 493 - exports[`prompts - progress (isCI = true) > stop > renders message without removing dots 1`] = ` 494 - [ 495 - "<cursor.hide>", 496 - "<dim>│</fg> 497 - ", 498 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ...", 499 - " 500 - ", 501 - "<cursor.left count=1>", 502 - "<erase.down>", 503 - "<green>◇</fg> foo. 504 - ", 505 - "<cursor.show>", 506 - ] 507 - `; 508 - 509 - exports[`prompts - progress (isCI = true) > stop > renders submit symbol and stops progress 1`] = ` 510 - [ 511 - "<cursor.hide>", 512 - "<dim>│</fg> 513 - ", 514 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</bold> ...", 515 - " 516 - ", 517 - "<cursor.left count=1>", 518 - "<erase.down>", 519 - "<green>◇</fg> 520 - ", 521 - "<cursor.show>", 522 - ] 523 - `; 524 - 525 - exports[`prompts - progress (isCI = true) > style > renders block progressbar 1`] = ` 526 - [ 527 - "<cursor.hide>", 528 - "<dim>│</fg> 529 - ", 530 - "<magenta>◒</fg> <magenta></fg><dim>██████████</bold> ...", 531 - " 532 - ", 533 - "<cursor.left count=1>", 534 - "<erase.down>", 535 - "<magenta>◐</fg> <magenta>█████</fg><dim>█████</bold> ...", 536 - " 537 - ", 538 - "<cursor.left count=1>", 539 - "<erase.down>", 540 - "<green>◇</fg> 541 - ", 542 - "<cursor.show>", 543 - ] 544 - `; 545 - 546 - exports[`prompts - progress (isCI = true) > style > renders heavy progressbar 1`] = ` 547 - [ 548 - "<cursor.hide>", 549 - "<dim>│</fg> 550 - ", 551 - "<magenta>◒</fg> <magenta></fg><dim>━━━━━━━━━━</bold> ...", 552 - " 553 - ", 554 - "<cursor.left count=1>", 555 - "<erase.down>", 556 - "<magenta>◐</fg> <magenta>━━━━━</fg><dim>━━━━━</bold> ...", 557 - " 558 - ", 559 - "<cursor.left count=1>", 560 - "<erase.down>", 561 - "<green>◇</fg> 562 - ", 563 - "<cursor.show>", 564 - ] 565 - `; 566 - 567 - exports[`prompts - progress (isCI = true) > style > renders light progressbar 1`] = ` 568 - [ 569 - "<cursor.hide>", 570 - "<dim>│</fg> 571 - ", 572 - "<magenta>◒</fg> <magenta></fg><dim>──────────</bold> ...", 573 - " 574 - ", 575 - "<cursor.left count=1>", 576 - "<erase.down>", 577 - "<magenta>◐</fg> <magenta>─────</fg><dim>─────</bold> ...", 578 - " 579 - ", 580 - "<cursor.left count=1>", 581 - "<erase.down>", 582 - "<green>◇</fg> 583 - ", 584 - "<cursor.show>", 585 - ] 586 - `;
-613
packages/prompts/test/__snapshots__/select-key.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`text (isCI = false) > can cancel by pressing escape 1`] = ` 4 - [ 5 - "<cursor.hide>", 6 - "<dim>│</fg> 7 - <cyan>◆</fg> foo 8 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> Option A 9 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 10 - <cyan>└</fg> 11 - ", 12 - "<cursor.backward count=999><cursor.up count=5>", 13 - "<cursor.down count=1>", 14 - "<erase.down>", 15 - "<red>■</fg> foo 16 - <dim>│</fg> <dim>Option A</bold> 17 - <dim>│</fg>", 18 - " 19 - ", 20 - "<cursor.show>", 21 - ] 22 - `; 23 - 24 - exports[`text (isCI = false) > caseSensitive: true makes input case-sensitive 1`] = ` 25 - [ 26 - "<cursor.hide>", 27 - "<dim>│</fg> 28 - <cyan>◆</fg> foo 29 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> Option a 30 - <cyan>│</fg> <dim><bg:white> A </bg></fg> Option A 31 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 32 - <cyan>└</fg> 33 - ", 34 - "<cursor.show>", 35 - "<cursor.backward count=999><cursor.up count=6>", 36 - "<cursor.down count=1>", 37 - "<erase.down>", 38 - "<green>◇</fg> foo 39 - <dim>│</fg> <dim>Option A</bold>", 40 - " 41 - ", 42 - ] 43 - `; 44 - 45 - exports[`text (isCI = false) > caseSensitive: true makes options case-sensitive 1`] = ` 46 - [ 47 - "<cursor.hide>", 48 - "<dim>│</fg> 49 - <cyan>◆</fg> foo 50 - <cyan>│</fg> <bg:cyan><dim> A </fg></bg> Option A 51 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 52 - <cyan>└</fg> 53 - ", 54 - "<cursor.backward count=999><cursor.up count=5>", 55 - "<cursor.down count=1>", 56 - "<erase.down>", 57 - "<red>■</fg> foo 58 - <dim>│</fg> <dim>Option A</bold> 59 - <dim>│</fg>", 60 - " 61 - ", 62 - "<cursor.show>", 63 - ] 64 - `; 65 - 66 - exports[`text (isCI = false) > global withGuide: false removes guide 1`] = ` 67 - [ 68 - "<cursor.hide>", 69 - "<cyan>◆</fg> foo 70 - <bg:cyan><dim> a </fg></bg> Option A 71 - <dim><bg:white> b </bg></fg> Option B 72 - 73 - ", 74 - "<cursor.show>", 75 - "<cursor.backward count=999><cursor.up count=4>", 76 - "<erase.down>", 77 - "<green>◇</fg> foo 78 - <dim>Option A</bold>", 79 - " 80 - ", 81 - ] 82 - `; 83 - 84 - exports[`text (isCI = false) > input is case-insensitive by default 1`] = ` 85 - [ 86 - "<cursor.hide>", 87 - "<dim>│</fg> 88 - <cyan>◆</fg> foo 89 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> Option A 90 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 91 - <cyan>└</fg> 92 - ", 93 - "<cursor.show>", 94 - "<cursor.backward count=999><cursor.up count=5>", 95 - "<cursor.down count=1>", 96 - "<erase.down>", 97 - "<green>◇</fg> foo 98 - <dim>│</fg> <dim>Option A</bold>", 99 - " 100 - ", 101 - ] 102 - `; 103 - 104 - exports[`text (isCI = false) > long cancelled labels are wrapped correctly 1`] = ` 105 - [ 106 - "<cursor.hide>", 107 - "<dim>│</fg> 108 - <cyan>◆</fg> Select an option: 109 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> This is a somewhat long 110 - <cyan>│</fg> label This is a somewhat 111 - <cyan>│</fg> long label This is a 112 - <cyan>│</fg> somewhat long label This is 113 - <cyan>│</fg> a somewhat long label This 114 - <cyan>│</fg> is a somewhat long label 115 - <cyan>│</fg> This is a somewhat long 116 - <cyan>│</fg> label This is a somewhat 117 - <cyan>│</fg> long label This is a 118 - <cyan>│</fg> somewhat long label This is 119 - <cyan>│</fg> a somewhat long label This 120 - <cyan>│</fg> is a somewhat long label 121 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Short label 122 - <cyan>└</fg> 123 - ", 124 - "<cursor.backward count=999><cursor.up count=16>", 125 - "<cursor.down count=1>", 126 - "<erase.down>", 127 - "<red>■</fg> Select an option: 128 - <dim>│</fg> <dim>This is a somewhat long </bold> 129 - <dim>│</fg> <dim>label This is a somewhat </bold> 130 - <dim>│</fg> <dim>long label This is a </bold> 131 - <dim>│</fg> <dim>somewhat long label This is</bold> 132 - <dim>│</fg> <dim> a somewhat long label This</bold> 133 - <dim>│</fg> <dim> is a somewhat long label </bold> 134 - <dim>│</fg> <dim>This is a somewhat long </bold> 135 - <dim>│</fg> <dim>label This is a somewhat </bold> 136 - <dim>│</fg> <dim>long label This is a </bold> 137 - <dim>│</fg> <dim>somewhat long label This is</bold> 138 - <dim>│</fg> <dim> a somewhat long label This</bold> 139 - <dim>│</fg> <dim> is a somewhat long label</bold> 140 - <dim>│</fg>", 141 - " 142 - ", 143 - "<cursor.show>", 144 - ] 145 - `; 146 - 147 - exports[`text (isCI = false) > long option labels are wrapped correctly 1`] = ` 148 - [ 149 - "<cursor.hide>", 150 - "<dim>│</fg> 151 - <cyan>◆</fg> Select an option: 152 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> This is a somewhat long 153 - <cyan>│</fg> label This is a somewhat 154 - <cyan>│</fg> long label This is a 155 - <cyan>│</fg> somewhat long label This is 156 - <cyan>│</fg> a somewhat long label This 157 - <cyan>│</fg> is a somewhat long label 158 - <cyan>│</fg> This is a somewhat long 159 - <cyan>│</fg> label This is a somewhat 160 - <cyan>│</fg> long label This is a 161 - <cyan>│</fg> somewhat long label This is 162 - <cyan>│</fg> a somewhat long label This 163 - <cyan>│</fg> is a somewhat long label 164 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Short label 165 - <cyan>└</fg> 166 - ", 167 - "<cursor.show>", 168 - "<cursor.backward count=999><cursor.up count=16>", 169 - "<cursor.down count=1>", 170 - "<erase.down>", 171 - "<green>◇</fg> Select an option: 172 - <dim>│</fg> <dim>This is a somewhat long </bold> 173 - <dim>│</fg> <dim>label This is a somewhat </bold> 174 - <dim>│</fg> <dim>long label This is a </bold> 175 - <dim>│</fg> <dim>somewhat long label This is</bold> 176 - <dim>│</fg> <dim> a somewhat long label This</bold> 177 - <dim>│</fg> <dim> is a somewhat long label </bold> 178 - <dim>│</fg> <dim>This is a somewhat long </bold> 179 - <dim>│</fg> <dim>label This is a somewhat </bold> 180 - <dim>│</fg> <dim>long label This is a </bold> 181 - <dim>│</fg> <dim>somewhat long label This is</bold> 182 - <dim>│</fg> <dim> a somewhat long label This</bold> 183 - <dim>│</fg> <dim> is a somewhat long label</bold>", 184 - " 185 - ", 186 - ] 187 - `; 188 - 189 - exports[`text (isCI = false) > long submitted labels are wrapped correctly 1`] = ` 190 - [ 191 - "<cursor.hide>", 192 - "<dim>│</fg> 193 - <cyan>◆</fg> Select an option: 194 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> This is a somewhat long 195 - <cyan>│</fg> label This is a somewhat 196 - <cyan>│</fg> long label This is a 197 - <cyan>│</fg> somewhat long label This is 198 - <cyan>│</fg> a somewhat long label This 199 - <cyan>│</fg> is a somewhat long label 200 - <cyan>│</fg> This is a somewhat long 201 - <cyan>│</fg> label This is a somewhat 202 - <cyan>│</fg> long label This is a 203 - <cyan>│</fg> somewhat long label This is 204 - <cyan>│</fg> a somewhat long label This 205 - <cyan>│</fg> is a somewhat long label 206 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Short label 207 - <cyan>└</fg> 208 - ", 209 - "<cursor.show>", 210 - "<cursor.backward count=999><cursor.up count=16>", 211 - "<cursor.down count=1>", 212 - "<erase.down>", 213 - "<green>◇</fg> Select an option: 214 - <dim>│</fg> <dim>This is a somewhat long </bold> 215 - <dim>│</fg> <dim>label This is a somewhat </bold> 216 - <dim>│</fg> <dim>long label This is a </bold> 217 - <dim>│</fg> <dim>somewhat long label This is</bold> 218 - <dim>│</fg> <dim> a somewhat long label This</bold> 219 - <dim>│</fg> <dim> is a somewhat long label </bold> 220 - <dim>│</fg> <dim>This is a somewhat long </bold> 221 - <dim>│</fg> <dim>label This is a somewhat </bold> 222 - <dim>│</fg> <dim>long label This is a </bold> 223 - <dim>│</fg> <dim>somewhat long label This is</bold> 224 - <dim>│</fg> <dim> a somewhat long label This</bold> 225 - <dim>│</fg> <dim> is a somewhat long label</bold>", 226 - " 227 - ", 228 - ] 229 - `; 230 - 231 - exports[`text (isCI = false) > options are case-insensitive by default 1`] = ` 232 - [ 233 - "<cursor.hide>", 234 - "<dim>│</fg> 235 - <cyan>◆</fg> foo 236 - <cyan>│</fg> <bg:cyan><dim> A </fg></bg> Option A 237 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 238 - <cyan>└</fg> 239 - ", 240 - "<cursor.show>", 241 - "<cursor.backward count=999><cursor.up count=5>", 242 - "<cursor.down count=1>", 243 - "<erase.down>", 244 - "<green>◇</fg> foo 245 - <dim>│</fg> <dim>Option A</bold>", 246 - " 247 - ", 248 - ] 249 - `; 250 - 251 - exports[`text (isCI = false) > renders message with options 1`] = ` 252 - [ 253 - "<cursor.hide>", 254 - "<dim>│</fg> 255 - <cyan>◆</fg> foo 256 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> Option A 257 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 258 - <cyan>└</fg> 259 - ", 260 - "<cursor.backward count=999><cursor.up count=5>", 261 - "<cursor.down count=1>", 262 - "<erase.down>", 263 - "<green>◇</fg> foo 264 - <dim>│</fg> <dim>Option A</bold>", 265 - " 266 - ", 267 - "<cursor.show>", 268 - ] 269 - `; 270 - 271 - exports[`text (isCI = false) > selects option by keypress 1`] = ` 272 - [ 273 - "<cursor.hide>", 274 - "<dim>│</fg> 275 - <cyan>◆</fg> foo 276 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> Option A 277 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 278 - <cyan>└</fg> 279 - ", 280 - "<cursor.show>", 281 - "<cursor.backward count=999><cursor.up count=5>", 282 - "<cursor.down count=1>", 283 - "<erase.down>", 284 - "<green>◇</fg> foo 285 - <dim>│</fg> <dim>Option B</bold>", 286 - " 287 - ", 288 - ] 289 - `; 290 - 291 - exports[`text (isCI = false) > withGuide: false removes guide 1`] = ` 292 - [ 293 - "<cursor.hide>", 294 - "<cyan>◆</fg> foo 295 - <bg:cyan><dim> a </fg></bg> Option A 296 - <dim><bg:white> b </bg></fg> Option B 297 - 298 - ", 299 - "<cursor.show>", 300 - "<cursor.backward count=999><cursor.up count=4>", 301 - "<erase.down>", 302 - "<green>◇</fg> foo 303 - <dim>Option A</bold>", 304 - " 305 - ", 306 - ] 307 - `; 308 - 309 - exports[`text (isCI = true) > can cancel by pressing escape 1`] = ` 310 - [ 311 - "<cursor.hide>", 312 - "<dim>│</fg> 313 - <cyan>◆</fg> foo 314 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> Option A 315 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 316 - <cyan>└</fg> 317 - ", 318 - "<cursor.backward count=999><cursor.up count=5>", 319 - "<cursor.down count=1>", 320 - "<erase.down>", 321 - "<red>■</fg> foo 322 - <dim>│</fg> <dim>Option A</bold> 323 - <dim>│</fg>", 324 - " 325 - ", 326 - "<cursor.show>", 327 - ] 328 - `; 329 - 330 - exports[`text (isCI = true) > caseSensitive: true makes input case-sensitive 1`] = ` 331 - [ 332 - "<cursor.hide>", 333 - "<dim>│</fg> 334 - <cyan>◆</fg> foo 335 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> Option a 336 - <cyan>│</fg> <dim><bg:white> A </bg></fg> Option A 337 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 338 - <cyan>└</fg> 339 - ", 340 - "<cursor.show>", 341 - "<cursor.backward count=999><cursor.up count=6>", 342 - "<cursor.down count=1>", 343 - "<erase.down>", 344 - "<green>◇</fg> foo 345 - <dim>│</fg> <dim>Option A</bold>", 346 - " 347 - ", 348 - ] 349 - `; 350 - 351 - exports[`text (isCI = true) > caseSensitive: true makes options case-sensitive 1`] = ` 352 - [ 353 - "<cursor.hide>", 354 - "<dim>│</fg> 355 - <cyan>◆</fg> foo 356 - <cyan>│</fg> <bg:cyan><dim> A </fg></bg> Option A 357 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 358 - <cyan>└</fg> 359 - ", 360 - "<cursor.backward count=999><cursor.up count=5>", 361 - "<cursor.down count=1>", 362 - "<erase.down>", 363 - "<red>■</fg> foo 364 - <dim>│</fg> <dim>Option A</bold> 365 - <dim>│</fg>", 366 - " 367 - ", 368 - "<cursor.show>", 369 - ] 370 - `; 371 - 372 - exports[`text (isCI = true) > global withGuide: false removes guide 1`] = ` 373 - [ 374 - "<cursor.hide>", 375 - "<cyan>◆</fg> foo 376 - <bg:cyan><dim> a </fg></bg> Option A 377 - <dim><bg:white> b </bg></fg> Option B 378 - 379 - ", 380 - "<cursor.show>", 381 - "<cursor.backward count=999><cursor.up count=4>", 382 - "<erase.down>", 383 - "<green>◇</fg> foo 384 - <dim>Option A</bold>", 385 - " 386 - ", 387 - ] 388 - `; 389 - 390 - exports[`text (isCI = true) > input is case-insensitive by default 1`] = ` 391 - [ 392 - "<cursor.hide>", 393 - "<dim>│</fg> 394 - <cyan>◆</fg> foo 395 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> Option A 396 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 397 - <cyan>└</fg> 398 - ", 399 - "<cursor.show>", 400 - "<cursor.backward count=999><cursor.up count=5>", 401 - "<cursor.down count=1>", 402 - "<erase.down>", 403 - "<green>◇</fg> foo 404 - <dim>│</fg> <dim>Option A</bold>", 405 - " 406 - ", 407 - ] 408 - `; 409 - 410 - exports[`text (isCI = true) > long cancelled labels are wrapped correctly 1`] = ` 411 - [ 412 - "<cursor.hide>", 413 - "<dim>│</fg> 414 - <cyan>◆</fg> Select an option: 415 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> This is a somewhat long 416 - <cyan>│</fg> label This is a somewhat 417 - <cyan>│</fg> long label This is a 418 - <cyan>│</fg> somewhat long label This is 419 - <cyan>│</fg> a somewhat long label This 420 - <cyan>│</fg> is a somewhat long label 421 - <cyan>│</fg> This is a somewhat long 422 - <cyan>│</fg> label This is a somewhat 423 - <cyan>│</fg> long label This is a 424 - <cyan>│</fg> somewhat long label This is 425 - <cyan>│</fg> a somewhat long label This 426 - <cyan>│</fg> is a somewhat long label 427 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Short label 428 - <cyan>└</fg> 429 - ", 430 - "<cursor.backward count=999><cursor.up count=16>", 431 - "<cursor.down count=1>", 432 - "<erase.down>", 433 - "<red>■</fg> Select an option: 434 - <dim>│</fg> <dim>This is a somewhat long </bold> 435 - <dim>│</fg> <dim>label This is a somewhat </bold> 436 - <dim>│</fg> <dim>long label This is a </bold> 437 - <dim>│</fg> <dim>somewhat long label This is</bold> 438 - <dim>│</fg> <dim> a somewhat long label This</bold> 439 - <dim>│</fg> <dim> is a somewhat long label </bold> 440 - <dim>│</fg> <dim>This is a somewhat long </bold> 441 - <dim>│</fg> <dim>label This is a somewhat </bold> 442 - <dim>│</fg> <dim>long label This is a </bold> 443 - <dim>│</fg> <dim>somewhat long label This is</bold> 444 - <dim>│</fg> <dim> a somewhat long label This</bold> 445 - <dim>│</fg> <dim> is a somewhat long label</bold> 446 - <dim>│</fg>", 447 - " 448 - ", 449 - "<cursor.show>", 450 - ] 451 - `; 452 - 453 - exports[`text (isCI = true) > long option labels are wrapped correctly 1`] = ` 454 - [ 455 - "<cursor.hide>", 456 - "<dim>│</fg> 457 - <cyan>◆</fg> Select an option: 458 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> This is a somewhat long 459 - <cyan>│</fg> label This is a somewhat 460 - <cyan>│</fg> long label This is a 461 - <cyan>│</fg> somewhat long label This is 462 - <cyan>│</fg> a somewhat long label This 463 - <cyan>│</fg> is a somewhat long label 464 - <cyan>│</fg> This is a somewhat long 465 - <cyan>│</fg> label This is a somewhat 466 - <cyan>│</fg> long label This is a 467 - <cyan>│</fg> somewhat long label This is 468 - <cyan>│</fg> a somewhat long label This 469 - <cyan>│</fg> is a somewhat long label 470 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Short label 471 - <cyan>└</fg> 472 - ", 473 - "<cursor.show>", 474 - "<cursor.backward count=999><cursor.up count=16>", 475 - "<cursor.down count=1>", 476 - "<erase.down>", 477 - "<green>◇</fg> Select an option: 478 - <dim>│</fg> <dim>This is a somewhat long </bold> 479 - <dim>│</fg> <dim>label This is a somewhat </bold> 480 - <dim>│</fg> <dim>long label This is a </bold> 481 - <dim>│</fg> <dim>somewhat long label This is</bold> 482 - <dim>│</fg> <dim> a somewhat long label This</bold> 483 - <dim>│</fg> <dim> is a somewhat long label </bold> 484 - <dim>│</fg> <dim>This is a somewhat long </bold> 485 - <dim>│</fg> <dim>label This is a somewhat </bold> 486 - <dim>│</fg> <dim>long label This is a </bold> 487 - <dim>│</fg> <dim>somewhat long label This is</bold> 488 - <dim>│</fg> <dim> a somewhat long label This</bold> 489 - <dim>│</fg> <dim> is a somewhat long label</bold>", 490 - " 491 - ", 492 - ] 493 - `; 494 - 495 - exports[`text (isCI = true) > long submitted labels are wrapped correctly 1`] = ` 496 - [ 497 - "<cursor.hide>", 498 - "<dim>│</fg> 499 - <cyan>◆</fg> Select an option: 500 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> This is a somewhat long 501 - <cyan>│</fg> label This is a somewhat 502 - <cyan>│</fg> long label This is a 503 - <cyan>│</fg> somewhat long label This is 504 - <cyan>│</fg> a somewhat long label This 505 - <cyan>│</fg> is a somewhat long label 506 - <cyan>│</fg> This is a somewhat long 507 - <cyan>│</fg> label This is a somewhat 508 - <cyan>│</fg> long label This is a 509 - <cyan>│</fg> somewhat long label This is 510 - <cyan>│</fg> a somewhat long label This 511 - <cyan>│</fg> is a somewhat long label 512 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Short label 513 - <cyan>└</fg> 514 - ", 515 - "<cursor.show>", 516 - "<cursor.backward count=999><cursor.up count=16>", 517 - "<cursor.down count=1>", 518 - "<erase.down>", 519 - "<green>◇</fg> Select an option: 520 - <dim>│</fg> <dim>This is a somewhat long </bold> 521 - <dim>│</fg> <dim>label This is a somewhat </bold> 522 - <dim>│</fg> <dim>long label This is a </bold> 523 - <dim>│</fg> <dim>somewhat long label This is</bold> 524 - <dim>│</fg> <dim> a somewhat long label This</bold> 525 - <dim>│</fg> <dim> is a somewhat long label </bold> 526 - <dim>│</fg> <dim>This is a somewhat long </bold> 527 - <dim>│</fg> <dim>label This is a somewhat </bold> 528 - <dim>│</fg> <dim>long label This is a </bold> 529 - <dim>│</fg> <dim>somewhat long label This is</bold> 530 - <dim>│</fg> <dim> a somewhat long label This</bold> 531 - <dim>│</fg> <dim> is a somewhat long label</bold>", 532 - " 533 - ", 534 - ] 535 - `; 536 - 537 - exports[`text (isCI = true) > options are case-insensitive by default 1`] = ` 538 - [ 539 - "<cursor.hide>", 540 - "<dim>│</fg> 541 - <cyan>◆</fg> foo 542 - <cyan>│</fg> <bg:cyan><dim> A </fg></bg> Option A 543 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 544 - <cyan>└</fg> 545 - ", 546 - "<cursor.show>", 547 - "<cursor.backward count=999><cursor.up count=5>", 548 - "<cursor.down count=1>", 549 - "<erase.down>", 550 - "<green>◇</fg> foo 551 - <dim>│</fg> <dim>Option A</bold>", 552 - " 553 - ", 554 - ] 555 - `; 556 - 557 - exports[`text (isCI = true) > renders message with options 1`] = ` 558 - [ 559 - "<cursor.hide>", 560 - "<dim>│</fg> 561 - <cyan>◆</fg> foo 562 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> Option A 563 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 564 - <cyan>└</fg> 565 - ", 566 - "<cursor.backward count=999><cursor.up count=5>", 567 - "<cursor.down count=1>", 568 - "<erase.down>", 569 - "<green>◇</fg> foo 570 - <dim>│</fg> <dim>Option A</bold>", 571 - " 572 - ", 573 - "<cursor.show>", 574 - ] 575 - `; 576 - 577 - exports[`text (isCI = true) > selects option by keypress 1`] = ` 578 - [ 579 - "<cursor.hide>", 580 - "<dim>│</fg> 581 - <cyan>◆</fg> foo 582 - <cyan>│</fg> <bg:cyan><dim> a </fg></bg> Option A 583 - <cyan>│</fg> <dim><bg:white> b </bg></fg> Option B 584 - <cyan>└</fg> 585 - ", 586 - "<cursor.show>", 587 - "<cursor.backward count=999><cursor.up count=5>", 588 - "<cursor.down count=1>", 589 - "<erase.down>", 590 - "<green>◇</fg> foo 591 - <dim>│</fg> <dim>Option B</bold>", 592 - " 593 - ", 594 - ] 595 - `; 596 - 597 - exports[`text (isCI = true) > withGuide: false removes guide 1`] = ` 598 - [ 599 - "<cursor.hide>", 600 - "<cyan>◆</fg> foo 601 - <bg:cyan><dim> a </fg></bg> Option A 602 - <dim><bg:white> b </bg></fg> Option B 603 - 604 - ", 605 - "<cursor.show>", 606 - "<cursor.backward count=999><cursor.up count=4>", 607 - "<erase.down>", 608 - "<green>◇</fg> foo 609 - <dim>Option A</bold>", 610 - " 611 - ", 612 - ] 613 - `;
-961
packages/prompts/test/__snapshots__/select.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`select (isCI = false) > can be aborted by a signal 1`] = ` 4 - [ 5 - "<cursor.hide>", 6 - "<dim>│</fg> 7 - <cyan>◆</fg> foo 8 - <cyan>│</fg> <green>●</fg> opt0 9 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 10 - <cyan>└</fg> 11 - ", 12 - " 13 - ", 14 - "<cursor.show>", 15 - ] 16 - `; 17 - 18 - exports[`select (isCI = false) > can cancel 1`] = ` 19 - [ 20 - "<cursor.hide>", 21 - "<dim>│</fg> 22 - <cyan>◆</fg> foo 23 - <cyan>│</fg> <green>●</fg> opt0 24 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 25 - <cyan>└</fg> 26 - ", 27 - "<cursor.backward count=999><cursor.up count=5>", 28 - "<cursor.down count=1>", 29 - "<erase.down>", 30 - "<red>■</fg> foo 31 - <dim>│</fg> <dim>opt0</bold> 32 - <dim>│</fg>", 33 - " 34 - ", 35 - "<cursor.show>", 36 - ] 37 - `; 38 - 39 - exports[`select (isCI = false) > correctly limits options when message wraps to multiple lines 1`] = ` 40 - [ 41 - "<cursor.hide>", 42 - "<dim>│</fg> 43 - <cyan>◆</fg> This is a very 44 - <cyan>│</fg> long message that 45 - <cyan>│</fg> will wrap to 46 - <cyan>│</fg> multiple lines 47 - <cyan>│</fg> <green>●</fg> Option 0 48 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 49 - <cyan>│</fg> <dim>○</bold> <dim>Option 2</bold> 50 - <cyan>│</fg> <dim>...</bold> 51 - <cyan>└</fg> 52 - ", 53 - "<cursor.backward count=999><cursor.up count=10>", 54 - "<cursor.down count=5>", 55 - "<erase.down>", 56 - "<cyan>│</fg> <dim>○</bold> <dim>Option 0</bold> 57 - <cyan>│</fg> <green>●</fg> Option 1 58 - <cyan>│</fg> <dim>○</bold> <dim>Option 2</bold> 59 - <cyan>│</fg> <dim>...</bold> 60 - <cyan>└</fg> 61 - ", 62 - "<cursor.backward count=999><cursor.up count=10>", 63 - "<cursor.down count=6>", 64 - "<erase.down>", 65 - "<cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 66 - <cyan>│</fg> <green>●</fg> Option 2 67 - <cyan>│</fg> <dim>...</bold> 68 - <cyan>└</fg> 69 - ", 70 - "<cursor.backward count=999><cursor.up count=10>", 71 - "<cursor.down count=5>", 72 - "<erase.down>", 73 - "<cyan>│</fg> <dim>...</bold> 74 - <cyan>│</fg> <green>●</fg> Option 3 75 - <cyan>│</fg> <dim>○</bold> <dim>Option 4</bold> 76 - <cyan>│</fg> <dim>...</bold> 77 - <cyan>└</fg> 78 - ", 79 - "<cursor.backward count=999><cursor.up count=10>", 80 - "<cursor.down count=6>", 81 - "<erase.down>", 82 - "<cyan>│</fg> <green>●</fg> Option 4 83 - <cyan>│</fg> <dim>○</bold> <dim>Option 5</bold> 84 - <cyan>│</fg> <dim>...</bold> 85 - <cyan>└</fg> 86 - ", 87 - "<cursor.backward count=999><cursor.up count=10>", 88 - "<cursor.down count=1>", 89 - "<erase.down>", 90 - "<green>◇</fg> This is a very 91 - <green>│</fg> long message that 92 - <green>│</fg> will wrap to 93 - <green>│</fg> multiple lines 94 - <dim>│</fg> <dim>Option 4</bold>", 95 - " 96 - ", 97 - "<cursor.show>", 98 - ] 99 - `; 100 - 101 - exports[`select (isCI = false) > correctly limits options with explicit multiline message 1`] = ` 102 - [ 103 - "<cursor.hide>", 104 - "<dim>│</fg> 105 - <cyan>◆</fg> Choose an option: 106 - <cyan>│</fg> Line 2 of the message 107 - <cyan>│</fg> Line 3 of the message 108 - <cyan>│</fg> <green>●</fg> Option 0 109 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 110 - <cyan>│</fg> <dim>○</bold> <dim>Option 2</bold> 111 - <cyan>│</fg> <dim>○</bold> <dim>Option 3</bold> 112 - <cyan>│</fg> <dim>...</bold> 113 - <cyan>└</fg> 114 - ", 115 - "<cursor.backward count=999><cursor.up count=10>", 116 - "<cursor.down count=4>", 117 - "<erase.down>", 118 - "<cyan>│</fg> <dim>○</bold> <dim>Option 0</bold> 119 - <cyan>│</fg> <green>●</fg> Option 1 120 - <cyan>│</fg> <dim>○</bold> <dim>Option 2</bold> 121 - <cyan>│</fg> <dim>○</bold> <dim>Option 3</bold> 122 - <cyan>│</fg> <dim>...</bold> 123 - <cyan>└</fg> 124 - ", 125 - "<cursor.backward count=999><cursor.up count=10>", 126 - "<cursor.down count=5>", 127 - "<erase.down>", 128 - "<cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 129 - <cyan>│</fg> <green>●</fg> Option 2 130 - <cyan>│</fg> <dim>○</bold> <dim>Option 3</bold> 131 - <cyan>│</fg> <dim>...</bold> 132 - <cyan>└</fg> 133 - ", 134 - "<cursor.backward count=999><cursor.up count=10>", 135 - "<cursor.down count=4>", 136 - "<erase.down>", 137 - "<cyan>│</fg> <dim>...</bold> 138 - <cyan>│</fg> <dim>○</bold> <dim>Option 2</bold> 139 - <cyan>│</fg> <green>●</fg> Option 3 140 - <cyan>│</fg> <dim>○</bold> <dim>Option 4</bold> 141 - <cyan>│</fg> <dim>...</bold> 142 - <cyan>└</fg> 143 - ", 144 - "<cursor.backward count=999><cursor.up count=10>", 145 - "<cursor.down count=1>", 146 - "<erase.down>", 147 - "<green>◇</fg> Choose an option: 148 - <green>│</fg> Line 2 of the message 149 - <green>│</fg> Line 3 of the message 150 - <dim>│</fg> <dim>Option 3</bold>", 151 - " 152 - ", 153 - "<cursor.show>", 154 - ] 155 - `; 156 - 157 - exports[`select (isCI = false) > down arrow selects next option 1`] = ` 158 - [ 159 - "<cursor.hide>", 160 - "<dim>│</fg> 161 - <cyan>◆</fg> foo 162 - <cyan>│</fg> <green>●</fg> opt0 163 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 164 - <cyan>└</fg> 165 - ", 166 - "<cursor.backward count=999><cursor.up count=5>", 167 - "<cursor.down count=2>", 168 - "<erase.down>", 169 - "<cyan>│</fg> <dim>○</bold> <dim>opt0</bold> 170 - <cyan>│</fg> <green>●</fg> opt1 171 - <cyan>└</fg> 172 - ", 173 - "<cursor.backward count=999><cursor.up count=5>", 174 - "<cursor.down count=1>", 175 - "<erase.down>", 176 - "<green>◇</fg> foo 177 - <dim>│</fg> <dim>opt1</bold>", 178 - " 179 - ", 180 - "<cursor.show>", 181 - ] 182 - `; 183 - 184 - exports[`select (isCI = false) > global withGuide: false removes guide 1`] = ` 185 - [ 186 - "<cursor.hide>", 187 - "<cyan>◆</fg> foo 188 - <green>●</fg> opt0 189 - <dim>○</bold> <dim>opt1</bold> 190 - 191 - ", 192 - "<cursor.backward count=999><cursor.up count=4>", 193 - "<erase.down>", 194 - "<green>◇</fg> foo 195 - <dim>opt0</bold>", 196 - " 197 - ", 198 - "<cursor.show>", 199 - ] 200 - `; 201 - 202 - exports[`select (isCI = false) > handles mixed size re-renders 1`] = ` 203 - [ 204 - "<cursor.hide>", 205 - "<dim>│</fg> 206 - <cyan>◆</fg> Whatever 207 - <cyan>│</fg> <green>●</fg> Long Option 208 - <cyan>│</fg> Long Option 209 - <cyan>│</fg> Long Option 210 - <cyan>│</fg> Long Option 211 - <cyan>│</fg> Long Option 212 - <cyan>│</fg> Long Option 213 - <cyan>│</fg> Long Option 214 - <cyan>│</fg> Long Option 215 - <cyan>│</fg> <dim>...</bold> 216 - <cyan>└</fg> 217 - ", 218 - "<cursor.backward count=999><cursor.up count=12>", 219 - "<erase.down>", 220 - "<dim>│</fg> 221 - <cyan>◆</fg> Whatever 222 - <cyan>│</fg> <dim>...</bold> 223 - <cyan>│</fg> <dim>○</bold> <dim>Option 0</bold> 224 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 225 - <cyan>│</fg> <dim>○</bold> <dim>Option 2</bold> 226 - <cyan>│</fg> <green>●</fg> Option 3 227 - <cyan>└</fg> 228 - ", 229 - "<cursor.backward count=999><cursor.up count=8>", 230 - "<cursor.down count=1>", 231 - "<erase.down>", 232 - "<green>◇</fg> Whatever 233 - <dim>│</fg> <dim>Option 3</bold>", 234 - " 235 - ", 236 - "<cursor.show>", 237 - ] 238 - `; 239 - 240 - exports[`select (isCI = false) > renders disabled options 1`] = ` 241 - [ 242 - "<cursor.hide>", 243 - "<dim>│</fg> 244 - <cyan>◆</fg> foo 245 - <cyan>│</fg> <dim>○</fg> <dim>Option 0</fg> 246 - <cyan>│</fg> <green>●</fg> Option 1 247 - <cyan>│</fg> <dim>○</fg> <dim>Option 2</fg> <dim>(Hint 2)</bold> 248 - <cyan>└</fg> 249 - ", 250 - "<cursor.backward count=999><cursor.up count=6>", 251 - "<cursor.down count=1>", 252 - "<erase.down>", 253 - "<green>◇</fg> foo 254 - <dim>│</fg> <dim>Option 1</bold>", 255 - " 256 - ", 257 - "<cursor.show>", 258 - ] 259 - `; 260 - 261 - exports[`select (isCI = false) > renders multi-line option labels 1`] = ` 262 - [ 263 - "<cursor.hide>", 264 - "<dim>│</fg> 265 - <cyan>◆</fg> foo 266 - <cyan>│</fg> <green>●</fg> Option 0 267 - <cyan>│</fg> with multiple lines 268 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 269 - <cyan>└</fg> 270 - ", 271 - "<cursor.backward count=999><cursor.up count=6>", 272 - "<cursor.down count=2>", 273 - "<erase.down>", 274 - "<cyan>│</fg> <dim>○</bold> <dim>Option 0</bold> 275 - <cyan>│</fg> <dim>with multiple lines</bold> 276 - <cyan>│</fg> <green>●</fg> Option 1 277 - <cyan>└</fg> 278 - ", 279 - "<cursor.backward count=999><cursor.up count=6>", 280 - "<cursor.down count=1>", 281 - "<erase.down>", 282 - "<green>◇</fg> foo 283 - <dim>│</fg> <dim>Option 1</bold>", 284 - " 285 - ", 286 - "<cursor.show>", 287 - ] 288 - `; 289 - 290 - exports[`select (isCI = false) > renders option hints 1`] = ` 291 - [ 292 - "<cursor.hide>", 293 - "<dim>│</fg> 294 - <cyan>◆</fg> foo 295 - <cyan>│</fg> <green>●</fg> opt0 <dim>(Hint 0)</bold> 296 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 297 - <cyan>└</fg> 298 - ", 299 - "<cursor.backward count=999><cursor.up count=5>", 300 - "<cursor.down count=1>", 301 - "<erase.down>", 302 - "<green>◇</fg> foo 303 - <dim>│</fg> <dim>opt0</bold>", 304 - " 305 - ", 306 - "<cursor.show>", 307 - ] 308 - `; 309 - 310 - exports[`select (isCI = false) > renders option labels 1`] = ` 311 - [ 312 - "<cursor.hide>", 313 - "<dim>│</fg> 314 - <cyan>◆</fg> foo 315 - <cyan>│</fg> <green>●</fg> Option 0 316 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 317 - <cyan>└</fg> 318 - ", 319 - "<cursor.backward count=999><cursor.up count=5>", 320 - "<cursor.down count=1>", 321 - "<erase.down>", 322 - "<green>◇</fg> foo 323 - <dim>│</fg> <dim>Option 0</bold>", 324 - " 325 - ", 326 - "<cursor.show>", 327 - ] 328 - `; 329 - 330 - exports[`select (isCI = false) > renders options and message 1`] = ` 331 - [ 332 - "<cursor.hide>", 333 - "<dim>│</fg> 334 - <cyan>◆</fg> foo 335 - <cyan>│</fg> <green>●</fg> opt0 336 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 337 - <cyan>└</fg> 338 - ", 339 - "<cursor.backward count=999><cursor.up count=5>", 340 - "<cursor.down count=1>", 341 - "<erase.down>", 342 - "<green>◇</fg> foo 343 - <dim>│</fg> <dim>opt0</bold>", 344 - " 345 - ", 346 - "<cursor.show>", 347 - ] 348 - `; 349 - 350 - exports[`select (isCI = false) > up arrow selects previous option 1`] = ` 351 - [ 352 - "<cursor.hide>", 353 - "<dim>│</fg> 354 - <cyan>◆</fg> foo 355 - <cyan>│</fg> <green>●</fg> opt0 356 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 357 - <cyan>└</fg> 358 - ", 359 - "<cursor.backward count=999><cursor.up count=5>", 360 - "<cursor.down count=2>", 361 - "<erase.down>", 362 - "<cyan>│</fg> <dim>○</bold> <dim>opt0</bold> 363 - <cyan>│</fg> <green>●</fg> opt1 364 - <cyan>└</fg> 365 - ", 366 - "<cursor.backward count=999><cursor.up count=5>", 367 - "<cursor.down count=2>", 368 - "<erase.down>", 369 - "<cyan>│</fg> <green>●</fg> opt0 370 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 371 - <cyan>└</fg> 372 - ", 373 - "<cursor.backward count=999><cursor.up count=5>", 374 - "<cursor.down count=1>", 375 - "<erase.down>", 376 - "<green>◇</fg> foo 377 - <dim>│</fg> <dim>opt0</bold>", 378 - " 379 - ", 380 - "<cursor.show>", 381 - ] 382 - `; 383 - 384 - exports[`select (isCI = false) > withGuide: false removes guide 1`] = ` 385 - [ 386 - "<cursor.hide>", 387 - "<cyan>◆</fg> foo 388 - <green>●</fg> opt0 389 - <dim>○</bold> <dim>opt1</bold> 390 - 391 - ", 392 - "<cursor.backward count=999><cursor.up count=4>", 393 - "<erase.down>", 394 - "<green>◇</fg> foo 395 - <dim>opt0</bold>", 396 - " 397 - ", 398 - "<cursor.show>", 399 - ] 400 - `; 401 - 402 - exports[`select (isCI = false) > wraps long cancelled message 1`] = ` 403 - [ 404 - "<cursor.hide>", 405 - "<dim>│</fg> 406 - <cyan>◆</fg> foo 407 - <cyan>│</fg> <green>●</fg> foo foo foo foo foo foo 408 - <cyan>│</fg> foo foo foo foo foo foo foo 409 - <cyan>│</fg> foo foo foo foo foo foo 410 - <cyan>│</fg> foo foo foo foo foo foo foo 411 - <cyan>│</fg> foo foo foo foo 412 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 413 - <cyan>└</fg> 414 - ", 415 - "<cursor.backward count=999><cursor.up count=9>", 416 - "<cursor.down count=1>", 417 - "<erase.down>", 418 - "<red>■</fg> foo 419 - <dim>│</fg> <dim>foo foo foo foo foo foo foo</bold> 420 - <dim>│</fg> <dim> foo foo foo foo foo foo </bold> 421 - <dim>│</fg> <dim>foo foo foo foo foo foo foo</bold> 422 - <dim>│</fg> <dim> foo foo foo foo foo foo </bold> 423 - <dim>│</fg> <dim>foo foo foo foo</bold> 424 - <dim>│</fg>", 425 - " 426 - ", 427 - "<cursor.show>", 428 - ] 429 - `; 430 - 431 - exports[`select (isCI = false) > wraps long messages 1`] = ` 432 - [ 433 - "<cursor.hide>", 434 - "<dim>│</fg> 435 - <cyan>◆</fg> foo foo foo foo foo foo foo 436 - <cyan>│</fg> foo foo foo foo foo foo 437 - <cyan>│</fg> foo foo foo foo foo foo foo 438 - <cyan>│</fg> <green>●</fg> opt0 439 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 440 - <cyan>└</fg> 441 - ", 442 - "<cursor.backward count=999><cursor.up count=7>", 443 - "<cursor.down count=1>", 444 - "<erase.down>", 445 - "<green>◇</fg> foo foo foo foo foo foo foo 446 - <green>│</fg> foo foo foo foo foo foo 447 - <green>│</fg> foo foo foo foo foo foo foo 448 - <dim>│</fg> <dim>opt0</bold>", 449 - " 450 - ", 451 - "<cursor.show>", 452 - ] 453 - `; 454 - 455 - exports[`select (isCI = false) > wraps long results 1`] = ` 456 - [ 457 - "<cursor.hide>", 458 - "<dim>│</fg> 459 - <cyan>◆</fg> foo 460 - <cyan>│</fg> <green>●</fg> foo foo foo foo foo foo 461 - <cyan>│</fg> foo foo foo foo foo foo foo 462 - <cyan>│</fg> foo foo foo foo foo foo 463 - <cyan>│</fg> foo foo foo foo foo foo foo 464 - <cyan>│</fg> foo foo foo foo 465 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 466 - <cyan>└</fg> 467 - ", 468 - "<cursor.backward count=999><cursor.up count=9>", 469 - "<cursor.down count=1>", 470 - "<erase.down>", 471 - "<green>◇</fg> foo 472 - <dim>│</fg> <dim>foo foo foo foo foo foo foo</bold> 473 - <dim>│</fg> <dim> foo foo foo foo foo foo </bold> 474 - <dim>│</fg> <dim>foo foo foo foo foo foo foo</bold> 475 - <dim>│</fg> <dim> foo foo foo foo foo foo </bold> 476 - <dim>│</fg> <dim>foo foo foo foo</bold>", 477 - " 478 - ", 479 - "<cursor.show>", 480 - ] 481 - `; 482 - 483 - exports[`select (isCI = true) > can be aborted by a signal 1`] = ` 484 - [ 485 - "<cursor.hide>", 486 - "<dim>│</fg> 487 - <cyan>◆</fg> foo 488 - <cyan>│</fg> <green>●</fg> opt0 489 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 490 - <cyan>└</fg> 491 - ", 492 - " 493 - ", 494 - "<cursor.show>", 495 - ] 496 - `; 497 - 498 - exports[`select (isCI = true) > can cancel 1`] = ` 499 - [ 500 - "<cursor.hide>", 501 - "<dim>│</fg> 502 - <cyan>◆</fg> foo 503 - <cyan>│</fg> <green>●</fg> opt0 504 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 505 - <cyan>└</fg> 506 - ", 507 - "<cursor.backward count=999><cursor.up count=5>", 508 - "<cursor.down count=1>", 509 - "<erase.down>", 510 - "<red>■</fg> foo 511 - <dim>│</fg> <dim>opt0</bold> 512 - <dim>│</fg>", 513 - " 514 - ", 515 - "<cursor.show>", 516 - ] 517 - `; 518 - 519 - exports[`select (isCI = true) > correctly limits options when message wraps to multiple lines 1`] = ` 520 - [ 521 - "<cursor.hide>", 522 - "<dim>│</fg> 523 - <cyan>◆</fg> This is a very 524 - <cyan>│</fg> long message that 525 - <cyan>│</fg> will wrap to 526 - <cyan>│</fg> multiple lines 527 - <cyan>│</fg> <green>●</fg> Option 0 528 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 529 - <cyan>│</fg> <dim>○</bold> <dim>Option 2</bold> 530 - <cyan>│</fg> <dim>...</bold> 531 - <cyan>└</fg> 532 - ", 533 - "<cursor.backward count=999><cursor.up count=10>", 534 - "<cursor.down count=5>", 535 - "<erase.down>", 536 - "<cyan>│</fg> <dim>○</bold> <dim>Option 0</bold> 537 - <cyan>│</fg> <green>●</fg> Option 1 538 - <cyan>│</fg> <dim>○</bold> <dim>Option 2</bold> 539 - <cyan>│</fg> <dim>...</bold> 540 - <cyan>└</fg> 541 - ", 542 - "<cursor.backward count=999><cursor.up count=10>", 543 - "<cursor.down count=6>", 544 - "<erase.down>", 545 - "<cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 546 - <cyan>│</fg> <green>●</fg> Option 2 547 - <cyan>│</fg> <dim>...</bold> 548 - <cyan>└</fg> 549 - ", 550 - "<cursor.backward count=999><cursor.up count=10>", 551 - "<cursor.down count=5>", 552 - "<erase.down>", 553 - "<cyan>│</fg> <dim>...</bold> 554 - <cyan>│</fg> <green>●</fg> Option 3 555 - <cyan>│</fg> <dim>○</bold> <dim>Option 4</bold> 556 - <cyan>│</fg> <dim>...</bold> 557 - <cyan>└</fg> 558 - ", 559 - "<cursor.backward count=999><cursor.up count=10>", 560 - "<cursor.down count=6>", 561 - "<erase.down>", 562 - "<cyan>│</fg> <green>●</fg> Option 4 563 - <cyan>│</fg> <dim>○</bold> <dim>Option 5</bold> 564 - <cyan>│</fg> <dim>...</bold> 565 - <cyan>└</fg> 566 - ", 567 - "<cursor.backward count=999><cursor.up count=10>", 568 - "<cursor.down count=1>", 569 - "<erase.down>", 570 - "<green>◇</fg> This is a very 571 - <green>│</fg> long message that 572 - <green>│</fg> will wrap to 573 - <green>│</fg> multiple lines 574 - <dim>│</fg> <dim>Option 4</bold>", 575 - " 576 - ", 577 - "<cursor.show>", 578 - ] 579 - `; 580 - 581 - exports[`select (isCI = true) > correctly limits options with explicit multiline message 1`] = ` 582 - [ 583 - "<cursor.hide>", 584 - "<dim>│</fg> 585 - <cyan>◆</fg> Choose an option: 586 - <cyan>│</fg> Line 2 of the message 587 - <cyan>│</fg> Line 3 of the message 588 - <cyan>│</fg> <green>●</fg> Option 0 589 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 590 - <cyan>│</fg> <dim>○</bold> <dim>Option 2</bold> 591 - <cyan>│</fg> <dim>○</bold> <dim>Option 3</bold> 592 - <cyan>│</fg> <dim>...</bold> 593 - <cyan>└</fg> 594 - ", 595 - "<cursor.backward count=999><cursor.up count=10>", 596 - "<cursor.down count=4>", 597 - "<erase.down>", 598 - "<cyan>│</fg> <dim>○</bold> <dim>Option 0</bold> 599 - <cyan>│</fg> <green>●</fg> Option 1 600 - <cyan>│</fg> <dim>○</bold> <dim>Option 2</bold> 601 - <cyan>│</fg> <dim>○</bold> <dim>Option 3</bold> 602 - <cyan>│</fg> <dim>...</bold> 603 - <cyan>└</fg> 604 - ", 605 - "<cursor.backward count=999><cursor.up count=10>", 606 - "<cursor.down count=5>", 607 - "<erase.down>", 608 - "<cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 609 - <cyan>│</fg> <green>●</fg> Option 2 610 - <cyan>│</fg> <dim>○</bold> <dim>Option 3</bold> 611 - <cyan>│</fg> <dim>...</bold> 612 - <cyan>└</fg> 613 - ", 614 - "<cursor.backward count=999><cursor.up count=10>", 615 - "<cursor.down count=4>", 616 - "<erase.down>", 617 - "<cyan>│</fg> <dim>...</bold> 618 - <cyan>│</fg> <dim>○</bold> <dim>Option 2</bold> 619 - <cyan>│</fg> <green>●</fg> Option 3 620 - <cyan>│</fg> <dim>○</bold> <dim>Option 4</bold> 621 - <cyan>│</fg> <dim>...</bold> 622 - <cyan>└</fg> 623 - ", 624 - "<cursor.backward count=999><cursor.up count=10>", 625 - "<cursor.down count=1>", 626 - "<erase.down>", 627 - "<green>◇</fg> Choose an option: 628 - <green>│</fg> Line 2 of the message 629 - <green>│</fg> Line 3 of the message 630 - <dim>│</fg> <dim>Option 3</bold>", 631 - " 632 - ", 633 - "<cursor.show>", 634 - ] 635 - `; 636 - 637 - exports[`select (isCI = true) > down arrow selects next option 1`] = ` 638 - [ 639 - "<cursor.hide>", 640 - "<dim>│</fg> 641 - <cyan>◆</fg> foo 642 - <cyan>│</fg> <green>●</fg> opt0 643 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 644 - <cyan>└</fg> 645 - ", 646 - "<cursor.backward count=999><cursor.up count=5>", 647 - "<cursor.down count=2>", 648 - "<erase.down>", 649 - "<cyan>│</fg> <dim>○</bold> <dim>opt0</bold> 650 - <cyan>│</fg> <green>●</fg> opt1 651 - <cyan>└</fg> 652 - ", 653 - "<cursor.backward count=999><cursor.up count=5>", 654 - "<cursor.down count=1>", 655 - "<erase.down>", 656 - "<green>◇</fg> foo 657 - <dim>│</fg> <dim>opt1</bold>", 658 - " 659 - ", 660 - "<cursor.show>", 661 - ] 662 - `; 663 - 664 - exports[`select (isCI = true) > global withGuide: false removes guide 1`] = ` 665 - [ 666 - "<cursor.hide>", 667 - "<cyan>◆</fg> foo 668 - <green>●</fg> opt0 669 - <dim>○</bold> <dim>opt1</bold> 670 - 671 - ", 672 - "<cursor.backward count=999><cursor.up count=4>", 673 - "<erase.down>", 674 - "<green>◇</fg> foo 675 - <dim>opt0</bold>", 676 - " 677 - ", 678 - "<cursor.show>", 679 - ] 680 - `; 681 - 682 - exports[`select (isCI = true) > handles mixed size re-renders 1`] = ` 683 - [ 684 - "<cursor.hide>", 685 - "<dim>│</fg> 686 - <cyan>◆</fg> Whatever 687 - <cyan>│</fg> <green>●</fg> Long Option 688 - <cyan>│</fg> Long Option 689 - <cyan>│</fg> Long Option 690 - <cyan>│</fg> Long Option 691 - <cyan>│</fg> Long Option 692 - <cyan>│</fg> Long Option 693 - <cyan>│</fg> Long Option 694 - <cyan>│</fg> Long Option 695 - <cyan>│</fg> <dim>...</bold> 696 - <cyan>└</fg> 697 - ", 698 - "<cursor.backward count=999><cursor.up count=12>", 699 - "<erase.down>", 700 - "<dim>│</fg> 701 - <cyan>◆</fg> Whatever 702 - <cyan>│</fg> <dim>...</bold> 703 - <cyan>│</fg> <dim>○</bold> <dim>Option 0</bold> 704 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 705 - <cyan>│</fg> <dim>○</bold> <dim>Option 2</bold> 706 - <cyan>│</fg> <green>●</fg> Option 3 707 - <cyan>└</fg> 708 - ", 709 - "<cursor.backward count=999><cursor.up count=8>", 710 - "<cursor.down count=1>", 711 - "<erase.down>", 712 - "<green>◇</fg> Whatever 713 - <dim>│</fg> <dim>Option 3</bold>", 714 - " 715 - ", 716 - "<cursor.show>", 717 - ] 718 - `; 719 - 720 - exports[`select (isCI = true) > renders disabled options 1`] = ` 721 - [ 722 - "<cursor.hide>", 723 - "<dim>│</fg> 724 - <cyan>◆</fg> foo 725 - <cyan>│</fg> <dim>○</fg> <dim>Option 0</fg> 726 - <cyan>│</fg> <green>●</fg> Option 1 727 - <cyan>│</fg> <dim>○</fg> <dim>Option 2</fg> <dim>(Hint 2)</bold> 728 - <cyan>└</fg> 729 - ", 730 - "<cursor.backward count=999><cursor.up count=6>", 731 - "<cursor.down count=1>", 732 - "<erase.down>", 733 - "<green>◇</fg> foo 734 - <dim>│</fg> <dim>Option 1</bold>", 735 - " 736 - ", 737 - "<cursor.show>", 738 - ] 739 - `; 740 - 741 - exports[`select (isCI = true) > renders multi-line option labels 1`] = ` 742 - [ 743 - "<cursor.hide>", 744 - "<dim>│</fg> 745 - <cyan>◆</fg> foo 746 - <cyan>│</fg> <green>●</fg> Option 0 747 - <cyan>│</fg> with multiple lines 748 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 749 - <cyan>└</fg> 750 - ", 751 - "<cursor.backward count=999><cursor.up count=6>", 752 - "<cursor.down count=2>", 753 - "<erase.down>", 754 - "<cyan>│</fg> <dim>○</bold> <dim>Option 0</bold> 755 - <cyan>│</fg> <dim>with multiple lines</bold> 756 - <cyan>│</fg> <green>●</fg> Option 1 757 - <cyan>└</fg> 758 - ", 759 - "<cursor.backward count=999><cursor.up count=6>", 760 - "<cursor.down count=1>", 761 - "<erase.down>", 762 - "<green>◇</fg> foo 763 - <dim>│</fg> <dim>Option 1</bold>", 764 - " 765 - ", 766 - "<cursor.show>", 767 - ] 768 - `; 769 - 770 - exports[`select (isCI = true) > renders option hints 1`] = ` 771 - [ 772 - "<cursor.hide>", 773 - "<dim>│</fg> 774 - <cyan>◆</fg> foo 775 - <cyan>│</fg> <green>●</fg> opt0 <dim>(Hint 0)</bold> 776 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 777 - <cyan>└</fg> 778 - ", 779 - "<cursor.backward count=999><cursor.up count=5>", 780 - "<cursor.down count=1>", 781 - "<erase.down>", 782 - "<green>◇</fg> foo 783 - <dim>│</fg> <dim>opt0</bold>", 784 - " 785 - ", 786 - "<cursor.show>", 787 - ] 788 - `; 789 - 790 - exports[`select (isCI = true) > renders option labels 1`] = ` 791 - [ 792 - "<cursor.hide>", 793 - "<dim>│</fg> 794 - <cyan>◆</fg> foo 795 - <cyan>│</fg> <green>●</fg> Option 0 796 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 797 - <cyan>└</fg> 798 - ", 799 - "<cursor.backward count=999><cursor.up count=5>", 800 - "<cursor.down count=1>", 801 - "<erase.down>", 802 - "<green>◇</fg> foo 803 - <dim>│</fg> <dim>Option 0</bold>", 804 - " 805 - ", 806 - "<cursor.show>", 807 - ] 808 - `; 809 - 810 - exports[`select (isCI = true) > renders options and message 1`] = ` 811 - [ 812 - "<cursor.hide>", 813 - "<dim>│</fg> 814 - <cyan>◆</fg> foo 815 - <cyan>│</fg> <green>●</fg> opt0 816 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 817 - <cyan>└</fg> 818 - ", 819 - "<cursor.backward count=999><cursor.up count=5>", 820 - "<cursor.down count=1>", 821 - "<erase.down>", 822 - "<green>◇</fg> foo 823 - <dim>│</fg> <dim>opt0</bold>", 824 - " 825 - ", 826 - "<cursor.show>", 827 - ] 828 - `; 829 - 830 - exports[`select (isCI = true) > up arrow selects previous option 1`] = ` 831 - [ 832 - "<cursor.hide>", 833 - "<dim>│</fg> 834 - <cyan>◆</fg> foo 835 - <cyan>│</fg> <green>●</fg> opt0 836 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 837 - <cyan>└</fg> 838 - ", 839 - "<cursor.backward count=999><cursor.up count=5>", 840 - "<cursor.down count=2>", 841 - "<erase.down>", 842 - "<cyan>│</fg> <dim>○</bold> <dim>opt0</bold> 843 - <cyan>│</fg> <green>●</fg> opt1 844 - <cyan>└</fg> 845 - ", 846 - "<cursor.backward count=999><cursor.up count=5>", 847 - "<cursor.down count=2>", 848 - "<erase.down>", 849 - "<cyan>│</fg> <green>●</fg> opt0 850 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 851 - <cyan>└</fg> 852 - ", 853 - "<cursor.backward count=999><cursor.up count=5>", 854 - "<cursor.down count=1>", 855 - "<erase.down>", 856 - "<green>◇</fg> foo 857 - <dim>│</fg> <dim>opt0</bold>", 858 - " 859 - ", 860 - "<cursor.show>", 861 - ] 862 - `; 863 - 864 - exports[`select (isCI = true) > withGuide: false removes guide 1`] = ` 865 - [ 866 - "<cursor.hide>", 867 - "<cyan>◆</fg> foo 868 - <green>●</fg> opt0 869 - <dim>○</bold> <dim>opt1</bold> 870 - 871 - ", 872 - "<cursor.backward count=999><cursor.up count=4>", 873 - "<erase.down>", 874 - "<green>◇</fg> foo 875 - <dim>opt0</bold>", 876 - " 877 - ", 878 - "<cursor.show>", 879 - ] 880 - `; 881 - 882 - exports[`select (isCI = true) > wraps long cancelled message 1`] = ` 883 - [ 884 - "<cursor.hide>", 885 - "<dim>│</fg> 886 - <cyan>◆</fg> foo 887 - <cyan>│</fg> <green>●</fg> foo foo foo foo foo foo 888 - <cyan>│</fg> foo foo foo foo foo foo foo 889 - <cyan>│</fg> foo foo foo foo foo foo 890 - <cyan>│</fg> foo foo foo foo foo foo foo 891 - <cyan>│</fg> foo foo foo foo 892 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 893 - <cyan>└</fg> 894 - ", 895 - "<cursor.backward count=999><cursor.up count=9>", 896 - "<cursor.down count=1>", 897 - "<erase.down>", 898 - "<red>■</fg> foo 899 - <dim>│</fg> <dim>foo foo foo foo foo foo foo</bold> 900 - <dim>│</fg> <dim> foo foo foo foo foo foo </bold> 901 - <dim>│</fg> <dim>foo foo foo foo foo foo foo</bold> 902 - <dim>│</fg> <dim> foo foo foo foo foo foo </bold> 903 - <dim>│</fg> <dim>foo foo foo foo</bold> 904 - <dim>│</fg>", 905 - " 906 - ", 907 - "<cursor.show>", 908 - ] 909 - `; 910 - 911 - exports[`select (isCI = true) > wraps long messages 1`] = ` 912 - [ 913 - "<cursor.hide>", 914 - "<dim>│</fg> 915 - <cyan>◆</fg> foo foo foo foo foo foo foo 916 - <cyan>│</fg> foo foo foo foo foo foo 917 - <cyan>│</fg> foo foo foo foo foo foo foo 918 - <cyan>│</fg> <green>●</fg> opt0 919 - <cyan>│</fg> <dim>○</bold> <dim>opt1</bold> 920 - <cyan>└</fg> 921 - ", 922 - "<cursor.backward count=999><cursor.up count=7>", 923 - "<cursor.down count=1>", 924 - "<erase.down>", 925 - "<green>◇</fg> foo foo foo foo foo foo foo 926 - <green>│</fg> foo foo foo foo foo foo 927 - <green>│</fg> foo foo foo foo foo foo foo 928 - <dim>│</fg> <dim>opt0</bold>", 929 - " 930 - ", 931 - "<cursor.show>", 932 - ] 933 - `; 934 - 935 - exports[`select (isCI = true) > wraps long results 1`] = ` 936 - [ 937 - "<cursor.hide>", 938 - "<dim>│</fg> 939 - <cyan>◆</fg> foo 940 - <cyan>│</fg> <green>●</fg> foo foo foo foo foo foo 941 - <cyan>│</fg> foo foo foo foo foo foo foo 942 - <cyan>│</fg> foo foo foo foo foo foo 943 - <cyan>│</fg> foo foo foo foo foo foo foo 944 - <cyan>│</fg> foo foo foo foo 945 - <cyan>│</fg> <dim>○</bold> <dim>Option 1</bold> 946 - <cyan>└</fg> 947 - ", 948 - "<cursor.backward count=999><cursor.up count=9>", 949 - "<cursor.down count=1>", 950 - "<erase.down>", 951 - "<green>◇</fg> foo 952 - <dim>│</fg> <dim>foo foo foo foo foo foo foo</bold> 953 - <dim>│</fg> <dim> foo foo foo foo foo foo </bold> 954 - <dim>│</fg> <dim>foo foo foo foo foo foo foo</bold> 955 - <dim>│</fg> <dim> foo foo foo foo foo foo </bold> 956 - <dim>│</fg> <dim>foo foo foo foo</bold>", 957 - " 958 - ", 959 - "<cursor.show>", 960 - ] 961 - `;
-1008
packages/prompts/test/__snapshots__/spinner.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`spinner (isCI = false) > can be aborted by a signal 1`] = ` 4 - [ 5 - "<cursor.hide>", 6 - "<dim>│</fg> 7 - ", 8 - "<red>■</fg> Canceled 9 - ", 10 - "<cursor.show>", 11 - ] 12 - `; 13 - 14 - exports[`spinner (isCI = false) > clear > stops and clears the spinner from the output 1`] = ` 15 - [ 16 - "<cursor.hide>", 17 - "<dim>│</fg> 18 - ", 19 - "<magenta>◒</fg> Loading", 20 - "<cursor.left count=1>", 21 - "<erase.down>", 22 - "<cursor.show>", 23 - ] 24 - `; 25 - 26 - exports[`spinner (isCI = false) > global withGuide: false removes guide 1`] = ` 27 - [ 28 - "<cursor.hide>", 29 - "<magenta>◒</fg> foo", 30 - "<cursor.left count=1>", 31 - "<erase.down>", 32 - "<green>◇</fg> 33 - ", 34 - "<cursor.show>", 35 - ] 36 - `; 37 - 38 - exports[`spinner (isCI = false) > indicator customization > custom delay 1`] = ` 39 - [ 40 - "<cursor.hide>", 41 - "<dim>│</fg> 42 - ", 43 - "<magenta>◒</fg> ", 44 - "<cursor.left count=1>", 45 - "<erase.down>", 46 - "<magenta>◐</fg> ", 47 - "<cursor.left count=1>", 48 - "<erase.down>", 49 - "<magenta>◓</fg> ", 50 - "<cursor.left count=1>", 51 - "<erase.down>", 52 - "<magenta>◑</fg> ", 53 - "<cursor.left count=1>", 54 - "<erase.down>", 55 - "<green>◇</fg> 56 - ", 57 - "<cursor.show>", 58 - ] 59 - `; 60 - 61 - exports[`spinner (isCI = false) > indicator customization > custom frame style 1`] = ` 62 - [ 63 - "<cursor.hide>", 64 - "<dim>│</fg> 65 - ", 66 - "<red>◒</fg> ", 67 - "<cursor.left count=1>", 68 - "<erase.down>", 69 - "<red>◐</fg> ", 70 - "<cursor.left count=1>", 71 - "<erase.down>", 72 - "<red>◓</fg> ", 73 - "<cursor.left count=1>", 74 - "<erase.down>", 75 - "<red>◑</fg> ", 76 - "<cursor.left count=1>", 77 - "<erase.down>", 78 - "<green>◇</fg> 79 - ", 80 - "<cursor.show>", 81 - ] 82 - `; 83 - 84 - exports[`spinner (isCI = false) > indicator customization > custom frames 1`] = ` 85 - [ 86 - "<cursor.hide>", 87 - "<dim>│</fg> 88 - ", 89 - "<magenta>🐴</fg> ", 90 - "<cursor.left count=1>", 91 - "<erase.down>", 92 - "<magenta>🦋</fg> ", 93 - "<cursor.left count=1>", 94 - "<erase.down>", 95 - "<magenta>🐙</fg> ", 96 - "<cursor.left count=1>", 97 - "<erase.down>", 98 - "<magenta>🐶</fg> ", 99 - "<cursor.left count=1>", 100 - "<erase.down>", 101 - "<green>◇</fg> 102 - ", 103 - "<cursor.show>", 104 - ] 105 - `; 106 - 107 - exports[`spinner (isCI = false) > indicator customization > custom frames with lots of frame have consistent ellipsis display 1`] = ` 108 - [ 109 - "<cursor.hide>", 110 - "<dim>│</fg> 111 - ", 112 - "<magenta>0</fg> ", 113 - "<cursor.left count=1>", 114 - "<erase.down>", 115 - "<magenta>1</fg> ", 116 - "<cursor.left count=1>", 117 - "<erase.down>", 118 - "<magenta>2</fg> ", 119 - "<cursor.left count=1>", 120 - "<erase.down>", 121 - "<magenta>3</fg> ", 122 - "<cursor.left count=1>", 123 - "<erase.down>", 124 - "<magenta>4</fg> ", 125 - "<cursor.left count=1>", 126 - "<erase.down>", 127 - "<magenta>5</fg> ", 128 - "<cursor.left count=1>", 129 - "<erase.down>", 130 - "<magenta>6</fg> ", 131 - "<cursor.left count=1>", 132 - "<erase.down>", 133 - "<magenta>7</fg> ", 134 - "<cursor.left count=1>", 135 - "<erase.down>", 136 - "<magenta>8</fg> .", 137 - "<cursor.left count=1>", 138 - "<erase.down>", 139 - "<magenta>9</fg> .", 140 - "<cursor.left count=1>", 141 - "<erase.down>", 142 - "<magenta>0</fg> .", 143 - "<cursor.left count=1>", 144 - "<erase.down>", 145 - "<magenta>1</fg> .", 146 - "<cursor.left count=1>", 147 - "<erase.down>", 148 - "<magenta>2</fg> .", 149 - "<cursor.left count=1>", 150 - "<erase.down>", 151 - "<magenta>3</fg> .", 152 - "<cursor.left count=1>", 153 - "<erase.down>", 154 - "<magenta>4</fg> .", 155 - "<cursor.left count=1>", 156 - "<erase.down>", 157 - "<magenta>5</fg> .", 158 - "<cursor.left count=1>", 159 - "<erase.down>", 160 - "<magenta>6</fg> ..", 161 - "<cursor.left count=1>", 162 - "<erase.down>", 163 - "<magenta>7</fg> ..", 164 - "<cursor.left count=1>", 165 - "<erase.down>", 166 - "<magenta>8</fg> ..", 167 - "<cursor.left count=1>", 168 - "<erase.down>", 169 - "<magenta>9</fg> ..", 170 - "<cursor.left count=1>", 171 - "<erase.down>", 172 - "<magenta>0</fg> ..", 173 - "<cursor.left count=1>", 174 - "<erase.down>", 175 - "<magenta>1</fg> ..", 176 - "<cursor.left count=1>", 177 - "<erase.down>", 178 - "<magenta>2</fg> ..", 179 - "<cursor.left count=1>", 180 - "<erase.down>", 181 - "<magenta>3</fg> ..", 182 - "<cursor.left count=1>", 183 - "<erase.down>", 184 - "<magenta>4</fg> ...", 185 - "<cursor.left count=1>", 186 - "<erase.down>", 187 - "<magenta>5</fg> ...", 188 - "<cursor.left count=1>", 189 - "<erase.down>", 190 - "<magenta>6</fg> ...", 191 - "<cursor.left count=1>", 192 - "<erase.down>", 193 - "<magenta>7</fg> ...", 194 - "<cursor.left count=1>", 195 - "<erase.down>", 196 - "<magenta>8</fg> ...", 197 - "<cursor.left count=1>", 198 - "<erase.down>", 199 - "<magenta>9</fg> ...", 200 - "<cursor.left count=1>", 201 - "<erase.down>", 202 - "<magenta>0</fg> ...", 203 - "<cursor.left count=1>", 204 - "<erase.down>", 205 - "<magenta>1</fg> ...", 206 - "<cursor.left count=1>", 207 - "<erase.down>", 208 - "<magenta>2</fg> ...", 209 - "<cursor.left count=1>", 210 - "<erase.down>", 211 - "<magenta>3</fg> ", 212 - "<cursor.left count=1>", 213 - "<erase.down>", 214 - "<magenta>4</fg> ", 215 - "<cursor.left count=1>", 216 - "<erase.down>", 217 - "<magenta>5</fg> ", 218 - "<cursor.left count=1>", 219 - "<erase.down>", 220 - "<magenta>6</fg> ", 221 - "<cursor.left count=1>", 222 - "<erase.down>", 223 - "<magenta>7</fg> ", 224 - "<cursor.left count=1>", 225 - "<erase.down>", 226 - "<magenta>8</fg> ", 227 - "<cursor.left count=1>", 228 - "<erase.down>", 229 - "<magenta>9</fg> ", 230 - "<cursor.left count=1>", 231 - "<erase.down>", 232 - "<magenta>0</fg> ", 233 - "<cursor.left count=1>", 234 - "<erase.down>", 235 - "<magenta>1</fg> .", 236 - "<cursor.left count=1>", 237 - "<erase.down>", 238 - "<magenta>2</fg> .", 239 - "<cursor.left count=1>", 240 - "<erase.down>", 241 - "<magenta>3</fg> .", 242 - "<cursor.left count=1>", 243 - "<erase.down>", 244 - "<magenta>4</fg> .", 245 - "<cursor.left count=1>", 246 - "<erase.down>", 247 - "<magenta>5</fg> .", 248 - "<cursor.left count=1>", 249 - "<erase.down>", 250 - "<magenta>6</fg> .", 251 - "<cursor.left count=1>", 252 - "<erase.down>", 253 - "<magenta>7</fg> .", 254 - "<cursor.left count=1>", 255 - "<erase.down>", 256 - "<magenta>8</fg> .", 257 - "<cursor.left count=1>", 258 - "<erase.down>", 259 - "<magenta>9</fg> ..", 260 - "<cursor.left count=1>", 261 - "<erase.down>", 262 - "<magenta>0</fg> ..", 263 - "<cursor.left count=1>", 264 - "<erase.down>", 265 - "<magenta>1</fg> ..", 266 - "<cursor.left count=1>", 267 - "<erase.down>", 268 - "<magenta>2</fg> ..", 269 - "<cursor.left count=1>", 270 - "<erase.down>", 271 - "<magenta>3</fg> ..", 272 - "<cursor.left count=1>", 273 - "<erase.down>", 274 - "<magenta>4</fg> ..", 275 - "<cursor.left count=1>", 276 - "<erase.down>", 277 - "<magenta>5</fg> ..", 278 - "<cursor.left count=1>", 279 - "<erase.down>", 280 - "<magenta>6</fg> ..", 281 - "<cursor.left count=1>", 282 - "<erase.down>", 283 - "<magenta>7</fg> ...", 284 - "<cursor.left count=1>", 285 - "<erase.down>", 286 - "<magenta>8</fg> ...", 287 - "<cursor.left count=1>", 288 - "<erase.down>", 289 - "<magenta>9</fg> ...", 290 - "<cursor.left count=1>", 291 - "<erase.down>", 292 - "<magenta>0</fg> ...", 293 - "<cursor.left count=1>", 294 - "<erase.down>", 295 - "<magenta>1</fg> ...", 296 - "<cursor.left count=1>", 297 - "<erase.down>", 298 - "<magenta>2</fg> ...", 299 - "<cursor.left count=1>", 300 - "<erase.down>", 301 - "<magenta>3</fg> ...", 302 - "<cursor.left count=1>", 303 - "<erase.down>", 304 - "<green>◇</fg> 305 - ", 306 - "<cursor.show>", 307 - ] 308 - `; 309 - 310 - exports[`spinner (isCI = false) > message > sets message for next frame 1`] = ` 311 - [ 312 - "<cursor.hide>", 313 - "<dim>│</fg> 314 - ", 315 - "<magenta>◒</fg> ", 316 - "<cursor.left count=1>", 317 - "<erase.down>", 318 - "<magenta>◐</fg> foo", 319 - "<cursor.left count=1>", 320 - "<erase.down>", 321 - "<green>◇</fg> 322 - ", 323 - "<cursor.show>", 324 - ] 325 - `; 326 - 327 - exports[`spinner (isCI = false) > process exit handling > prioritizes cancel option over global setting 1`] = ` 328 - [ 329 - "<cursor.hide>", 330 - "<dim>│</fg> 331 - ", 332 - "<red>■</fg> Spinner cancel message 333 - ", 334 - "<cursor.show>", 335 - ] 336 - `; 337 - 338 - exports[`spinner (isCI = false) > process exit handling > prioritizes error option over global setting 1`] = ` 339 - [ 340 - "<cursor.hide>", 341 - "<dim>│</fg> 342 - ", 343 - "<red>▲</fg> Spinner error message 344 - ", 345 - "<cursor.show>", 346 - ] 347 - `; 348 - 349 - exports[`spinner (isCI = false) > process exit handling > uses custom cancel message when provided directly 1`] = ` 350 - [ 351 - "<cursor.hide>", 352 - "<dim>│</fg> 353 - ", 354 - "<red>■</fg> Custom cancel message 355 - ", 356 - "<cursor.show>", 357 - ] 358 - `; 359 - 360 - exports[`spinner (isCI = false) > process exit handling > uses custom error message when provided directly 1`] = ` 361 - [ 362 - "<cursor.hide>", 363 - "<dim>│</fg> 364 - ", 365 - "<red>▲</fg> Custom error message 366 - ", 367 - "<cursor.show>", 368 - ] 369 - `; 370 - 371 - exports[`spinner (isCI = false) > process exit handling > uses default cancel message 1`] = ` 372 - [ 373 - "<cursor.hide>", 374 - "<dim>│</fg> 375 - ", 376 - "<red>■</fg> Canceled 377 - ", 378 - "<cursor.show>", 379 - ] 380 - `; 381 - 382 - exports[`spinner (isCI = false) > process exit handling > uses global custom cancel message from settings 1`] = ` 383 - [ 384 - "<cursor.hide>", 385 - "<dim>│</fg> 386 - ", 387 - "<red>■</fg> Global cancel message 388 - ", 389 - "<cursor.show>", 390 - ] 391 - `; 392 - 393 - exports[`spinner (isCI = false) > process exit handling > uses global custom error message from settings 1`] = ` 394 - [ 395 - "<cursor.hide>", 396 - "<dim>│</fg> 397 - ", 398 - "<red>▲</fg> Global error message 399 - ", 400 - "<cursor.show>", 401 - ] 402 - `; 403 - 404 - exports[`spinner (isCI = false) > start > handles multi-line messages 1`] = ` 405 - [ 406 - "<cursor.hide>", 407 - "<dim>│</fg> 408 - ", 409 - "<magenta>◒</fg> foo 410 - bar 411 - baz", 412 - "<cursor.up count=2>", 413 - "<cursor.left count=1>", 414 - "<erase.down>", 415 - "<green>◇</fg> 416 - ", 417 - "<cursor.show>", 418 - ] 419 - `; 420 - 421 - exports[`spinner (isCI = false) > start > handles wrapping 1`] = ` 422 - [ 423 - "<cursor.hide>", 424 - "<dim>│</fg> 425 - ", 426 - "<magenta>◒</fg> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 427 - xxxxxxxxxxxxx", 428 - "<cursor.up count=1>", 429 - "<cursor.left count=1>", 430 - "<erase.down>", 431 - "<green>◇</fg> stopped 432 - ", 433 - "<cursor.show>", 434 - ] 435 - `; 436 - 437 - exports[`spinner (isCI = false) > start > renders frames at interval 1`] = ` 438 - [ 439 - "<cursor.hide>", 440 - "<dim>│</fg> 441 - ", 442 - "<magenta>◒</fg> ", 443 - "<cursor.left count=1>", 444 - "<erase.down>", 445 - "<magenta>◐</fg> ", 446 - "<cursor.left count=1>", 447 - "<erase.down>", 448 - "<magenta>◓</fg> ", 449 - "<cursor.left count=1>", 450 - "<erase.down>", 451 - "<magenta>◑</fg> ", 452 - "<cursor.left count=1>", 453 - "<erase.down>", 454 - "<green>◇</fg> 455 - ", 456 - "<cursor.show>", 457 - ] 458 - `; 459 - 460 - exports[`spinner (isCI = false) > start > renders message 1`] = ` 461 - [ 462 - "<cursor.hide>", 463 - "<dim>│</fg> 464 - ", 465 - "<magenta>◒</fg> foo", 466 - "<cursor.left count=1>", 467 - "<erase.down>", 468 - "<green>◇</fg> 469 - ", 470 - "<cursor.show>", 471 - ] 472 - `; 473 - 474 - exports[`spinner (isCI = false) > start > renders timer when indicator is "timer" 1`] = ` 475 - [ 476 - "<cursor.hide>", 477 - "<dim>│</fg> 478 - ", 479 - "<magenta>◒</fg> [0s]", 480 - "<cursor.left count=1>", 481 - "<erase.down>", 482 - "<green>◇</fg> [0s] 483 - ", 484 - "<cursor.show>", 485 - ] 486 - `; 487 - 488 - exports[`spinner (isCI = false) > stop > renders cancel symbol when calling cancel() 1`] = ` 489 - [ 490 - "<cursor.hide>", 491 - "<dim>│</fg> 492 - ", 493 - "<magenta>◒</fg> ", 494 - "<cursor.left count=1>", 495 - "<erase.down>", 496 - "<red>■</fg> 497 - ", 498 - "<cursor.show>", 499 - ] 500 - `; 501 - 502 - exports[`spinner (isCI = false) > stop > renders error symbol when calling error() 1`] = ` 503 - [ 504 - "<cursor.hide>", 505 - "<dim>│</fg> 506 - ", 507 - "<magenta>◒</fg> ", 508 - "<cursor.left count=1>", 509 - "<erase.down>", 510 - "<red>▲</fg> 511 - ", 512 - "<cursor.show>", 513 - ] 514 - `; 515 - 516 - exports[`spinner (isCI = false) > stop > renders message 1`] = ` 517 - [ 518 - "<cursor.hide>", 519 - "<dim>│</fg> 520 - ", 521 - "<magenta>◒</fg> ", 522 - "<cursor.left count=1>", 523 - "<erase.down>", 524 - "<green>◇</fg> foo 525 - ", 526 - "<cursor.show>", 527 - ] 528 - `; 529 - 530 - exports[`spinner (isCI = false) > stop > renders message when cancelling 1`] = ` 531 - [ 532 - "<cursor.hide>", 533 - "<dim>│</fg> 534 - ", 535 - "<magenta>◒</fg> ", 536 - "<cursor.left count=1>", 537 - "<erase.down>", 538 - "<red>■</fg> too dizzy — spinning cancelled 539 - ", 540 - "<cursor.show>", 541 - ] 542 - `; 543 - 544 - exports[`spinner (isCI = false) > stop > renders message when erroring 1`] = ` 545 - [ 546 - "<cursor.hide>", 547 - "<dim>│</fg> 548 - ", 549 - "<magenta>◒</fg> ", 550 - "<cursor.left count=1>", 551 - "<erase.down>", 552 - "<red>▲</fg> error: spun too fast! 553 - ", 554 - "<cursor.show>", 555 - ] 556 - `; 557 - 558 - exports[`spinner (isCI = false) > stop > renders message without removing dots 1`] = ` 559 - [ 560 - "<cursor.hide>", 561 - "<dim>│</fg> 562 - ", 563 - "<magenta>◒</fg> ", 564 - "<cursor.left count=1>", 565 - "<erase.down>", 566 - "<green>◇</fg> foo. 567 - ", 568 - "<cursor.show>", 569 - ] 570 - `; 571 - 572 - exports[`spinner (isCI = false) > stop > renders submit symbol and stops spinner 1`] = ` 573 - [ 574 - "<cursor.hide>", 575 - "<dim>│</fg> 576 - ", 577 - "<magenta>◒</fg> ", 578 - "<cursor.left count=1>", 579 - "<erase.down>", 580 - "<green>◇</fg> 581 - ", 582 - "<cursor.show>", 583 - ] 584 - `; 585 - 586 - exports[`spinner (isCI = false) > withGuide: false removes guide 1`] = ` 587 - [ 588 - "<cursor.hide>", 589 - "<magenta>◒</fg> foo", 590 - "<cursor.left count=1>", 591 - "<erase.down>", 592 - "<green>◇</fg> 593 - ", 594 - "<cursor.show>", 595 - ] 596 - `; 597 - 598 - exports[`spinner (isCI = true) > can be aborted by a signal 1`] = ` 599 - [ 600 - "<cursor.hide>", 601 - "<dim>│</fg> 602 - ", 603 - "<red>■</fg> Canceled 604 - ", 605 - "<cursor.show>", 606 - ] 607 - `; 608 - 609 - exports[`spinner (isCI = true) > clear > stops and clears the spinner from the output 1`] = ` 610 - [ 611 - "<cursor.hide>", 612 - "<dim>│</fg> 613 - ", 614 - "<magenta>◒</fg> Loading...", 615 - " 616 - ", 617 - "<cursor.left count=1>", 618 - "<erase.down>", 619 - "<cursor.show>", 620 - ] 621 - `; 622 - 623 - exports[`spinner (isCI = true) > global withGuide: false removes guide 1`] = ` 624 - [ 625 - "<cursor.hide>", 626 - "<magenta>◒</fg> foo...", 627 - " 628 - ", 629 - "<cursor.left count=1>", 630 - "<erase.down>", 631 - "<green>◇</fg> 632 - ", 633 - "<cursor.show>", 634 - ] 635 - `; 636 - 637 - exports[`spinner (isCI = true) > indicator customization > custom delay 1`] = ` 638 - [ 639 - "<cursor.hide>", 640 - "<dim>│</fg> 641 - ", 642 - "<magenta>◒</fg> ...", 643 - " 644 - ", 645 - "<cursor.left count=1>", 646 - "<erase.down>", 647 - "<green>◇</fg> 648 - ", 649 - "<cursor.show>", 650 - ] 651 - `; 652 - 653 - exports[`spinner (isCI = true) > indicator customization > custom frame style 1`] = ` 654 - [ 655 - "<cursor.hide>", 656 - "<dim>│</fg> 657 - ", 658 - "<red>◒</fg> ...", 659 - " 660 - ", 661 - "<cursor.left count=1>", 662 - "<erase.down>", 663 - "<green>◇</fg> 664 - ", 665 - "<cursor.show>", 666 - ] 667 - `; 668 - 669 - exports[`spinner (isCI = true) > indicator customization > custom frames 1`] = ` 670 - [ 671 - "<cursor.hide>", 672 - "<dim>│</fg> 673 - ", 674 - "<magenta>🐴</fg> ...", 675 - " 676 - ", 677 - "<cursor.left count=1>", 678 - "<erase.down>", 679 - "<green>◇</fg> 680 - ", 681 - "<cursor.show>", 682 - ] 683 - `; 684 - 685 - exports[`spinner (isCI = true) > indicator customization > custom frames with lots of frame have consistent ellipsis display 1`] = ` 686 - [ 687 - "<cursor.hide>", 688 - "<dim>│</fg> 689 - ", 690 - "<magenta>0</fg> ...", 691 - " 692 - ", 693 - "<cursor.left count=1>", 694 - "<erase.down>", 695 - "<green>◇</fg> 696 - ", 697 - "<cursor.show>", 698 - ] 699 - `; 700 - 701 - exports[`spinner (isCI = true) > message > sets message for next frame 1`] = ` 702 - [ 703 - "<cursor.hide>", 704 - "<dim>│</fg> 705 - ", 706 - "<magenta>◒</fg> ...", 707 - " 708 - ", 709 - "<cursor.left count=1>", 710 - "<erase.down>", 711 - "<magenta>◐</fg> foo...", 712 - " 713 - ", 714 - "<cursor.left count=1>", 715 - "<erase.down>", 716 - "<green>◇</fg> 717 - ", 718 - "<cursor.show>", 719 - ] 720 - `; 721 - 722 - exports[`spinner (isCI = true) > process exit handling > prioritizes cancel option over global setting 1`] = ` 723 - [ 724 - "<cursor.hide>", 725 - "<dim>│</fg> 726 - ", 727 - "<red>■</fg> Spinner cancel message 728 - ", 729 - "<cursor.show>", 730 - ] 731 - `; 732 - 733 - exports[`spinner (isCI = true) > process exit handling > prioritizes error option over global setting 1`] = ` 734 - [ 735 - "<cursor.hide>", 736 - "<dim>│</fg> 737 - ", 738 - "<red>▲</fg> Spinner error message 739 - ", 740 - "<cursor.show>", 741 - ] 742 - `; 743 - 744 - exports[`spinner (isCI = true) > process exit handling > uses custom cancel message when provided directly 1`] = ` 745 - [ 746 - "<cursor.hide>", 747 - "<dim>│</fg> 748 - ", 749 - "<red>■</fg> Custom cancel message 750 - ", 751 - "<cursor.show>", 752 - ] 753 - `; 754 - 755 - exports[`spinner (isCI = true) > process exit handling > uses custom error message when provided directly 1`] = ` 756 - [ 757 - "<cursor.hide>", 758 - "<dim>│</fg> 759 - ", 760 - "<red>▲</fg> Custom error message 761 - ", 762 - "<cursor.show>", 763 - ] 764 - `; 765 - 766 - exports[`spinner (isCI = true) > process exit handling > uses default cancel message 1`] = ` 767 - [ 768 - "<cursor.hide>", 769 - "<dim>│</fg> 770 - ", 771 - "<red>■</fg> Canceled 772 - ", 773 - "<cursor.show>", 774 - ] 775 - `; 776 - 777 - exports[`spinner (isCI = true) > process exit handling > uses global custom cancel message from settings 1`] = ` 778 - [ 779 - "<cursor.hide>", 780 - "<dim>│</fg> 781 - ", 782 - "<red>■</fg> Global cancel message 783 - ", 784 - "<cursor.show>", 785 - ] 786 - `; 787 - 788 - exports[`spinner (isCI = true) > process exit handling > uses global custom error message from settings 1`] = ` 789 - [ 790 - "<cursor.hide>", 791 - "<dim>│</fg> 792 - ", 793 - "<red>▲</fg> Global error message 794 - ", 795 - "<cursor.show>", 796 - ] 797 - `; 798 - 799 - exports[`spinner (isCI = true) > start > handles multi-line messages 1`] = ` 800 - [ 801 - "<cursor.hide>", 802 - "<dim>│</fg> 803 - ", 804 - "<magenta>◒</fg> foo 805 - bar 806 - baz...", 807 - " 808 - ", 809 - "<cursor.up count=2>", 810 - "<cursor.left count=1>", 811 - "<erase.down>", 812 - "<green>◇</fg> 813 - ", 814 - "<cursor.show>", 815 - ] 816 - `; 817 - 818 - exports[`spinner (isCI = true) > start > handles wrapping 1`] = ` 819 - [ 820 - "<cursor.hide>", 821 - "<dim>│</fg> 822 - ", 823 - "<magenta>◒</fg> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 824 - xxxxxxxxxxxxx...", 825 - " 826 - ", 827 - "<cursor.up count=1>", 828 - "<cursor.left count=1>", 829 - "<erase.down>", 830 - "<green>◇</fg> stopped 831 - ", 832 - "<cursor.show>", 833 - ] 834 - `; 835 - 836 - exports[`spinner (isCI = true) > start > renders frames at interval 1`] = ` 837 - [ 838 - "<cursor.hide>", 839 - "<dim>│</fg> 840 - ", 841 - "<magenta>◒</fg> ...", 842 - " 843 - ", 844 - "<cursor.left count=1>", 845 - "<erase.down>", 846 - "<green>◇</fg> 847 - ", 848 - "<cursor.show>", 849 - ] 850 - `; 851 - 852 - exports[`spinner (isCI = true) > start > renders message 1`] = ` 853 - [ 854 - "<cursor.hide>", 855 - "<dim>│</fg> 856 - ", 857 - "<magenta>◒</fg> foo...", 858 - " 859 - ", 860 - "<cursor.left count=1>", 861 - "<erase.down>", 862 - "<green>◇</fg> 863 - ", 864 - "<cursor.show>", 865 - ] 866 - `; 867 - 868 - exports[`spinner (isCI = true) > start > renders timer when indicator is "timer" 1`] = ` 869 - [ 870 - "<cursor.hide>", 871 - "<dim>│</fg> 872 - ", 873 - "<magenta>◒</fg> ...", 874 - " 875 - ", 876 - "<cursor.left count=1>", 877 - "<erase.down>", 878 - "<green>◇</fg> [0s] 879 - ", 880 - "<cursor.show>", 881 - ] 882 - `; 883 - 884 - exports[`spinner (isCI = true) > stop > renders cancel symbol when calling cancel() 1`] = ` 885 - [ 886 - "<cursor.hide>", 887 - "<dim>│</fg> 888 - ", 889 - "<magenta>◒</fg> ...", 890 - " 891 - ", 892 - "<cursor.left count=1>", 893 - "<erase.down>", 894 - "<red>■</fg> 895 - ", 896 - "<cursor.show>", 897 - ] 898 - `; 899 - 900 - exports[`spinner (isCI = true) > stop > renders error symbol when calling error() 1`] = ` 901 - [ 902 - "<cursor.hide>", 903 - "<dim>│</fg> 904 - ", 905 - "<magenta>◒</fg> ...", 906 - " 907 - ", 908 - "<cursor.left count=1>", 909 - "<erase.down>", 910 - "<red>▲</fg> 911 - ", 912 - "<cursor.show>", 913 - ] 914 - `; 915 - 916 - exports[`spinner (isCI = true) > stop > renders message 1`] = ` 917 - [ 918 - "<cursor.hide>", 919 - "<dim>│</fg> 920 - ", 921 - "<magenta>◒</fg> ...", 922 - " 923 - ", 924 - "<cursor.left count=1>", 925 - "<erase.down>", 926 - "<green>◇</fg> foo 927 - ", 928 - "<cursor.show>", 929 - ] 930 - `; 931 - 932 - exports[`spinner (isCI = true) > stop > renders message when cancelling 1`] = ` 933 - [ 934 - "<cursor.hide>", 935 - "<dim>│</fg> 936 - ", 937 - "<magenta>◒</fg> ...", 938 - " 939 - ", 940 - "<cursor.left count=1>", 941 - "<erase.down>", 942 - "<red>■</fg> too dizzy — spinning cancelled 943 - ", 944 - "<cursor.show>", 945 - ] 946 - `; 947 - 948 - exports[`spinner (isCI = true) > stop > renders message when erroring 1`] = ` 949 - [ 950 - "<cursor.hide>", 951 - "<dim>│</fg> 952 - ", 953 - "<magenta>◒</fg> ...", 954 - " 955 - ", 956 - "<cursor.left count=1>", 957 - "<erase.down>", 958 - "<red>▲</fg> error: spun too fast! 959 - ", 960 - "<cursor.show>", 961 - ] 962 - `; 963 - 964 - exports[`spinner (isCI = true) > stop > renders message without removing dots 1`] = ` 965 - [ 966 - "<cursor.hide>", 967 - "<dim>│</fg> 968 - ", 969 - "<magenta>◒</fg> ...", 970 - " 971 - ", 972 - "<cursor.left count=1>", 973 - "<erase.down>", 974 - "<green>◇</fg> foo. 975 - ", 976 - "<cursor.show>", 977 - ] 978 - `; 979 - 980 - exports[`spinner (isCI = true) > stop > renders submit symbol and stops spinner 1`] = ` 981 - [ 982 - "<cursor.hide>", 983 - "<dim>│</fg> 984 - ", 985 - "<magenta>◒</fg> ...", 986 - " 987 - ", 988 - "<cursor.left count=1>", 989 - "<erase.down>", 990 - "<green>◇</fg> 991 - ", 992 - "<cursor.show>", 993 - ] 994 - `; 995 - 996 - exports[`spinner (isCI = true) > withGuide: false removes guide 1`] = ` 997 - [ 998 - "<cursor.hide>", 999 - "<magenta>◒</fg> foo...", 1000 - " 1001 - ", 1002 - "<cursor.left count=1>", 1003 - "<erase.down>", 1004 - "<green>◇</fg> 1005 - ", 1006 - "<cursor.show>", 1007 - ] 1008 - `;
-1738
packages/prompts/test/__snapshots__/task-log.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`taskLog (isCI = false) > error > clears output if showLog = false 1`] = ` 4 - [ 5 - "<dim>│</fg> 6 - ", 7 - "<green>◇</fg> foo 8 - ", 9 - "<dim>│</fg> 10 - ", 11 - "<dim>│</fg> <dim>line 0</bold> 12 - ", 13 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 14 - "<dim>│</fg> <dim>line 0</bold> 15 - <dim>│</fg> <dim>line 1</bold> 16 - ", 17 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 18 - "<dim>│</fg> 19 - <red>■</fg> some error! 20 - ", 21 - ] 22 - `; 23 - 24 - exports[`taskLog (isCI = false) > error > renders output with message 1`] = ` 25 - [ 26 - "<dim>│</fg> 27 - ", 28 - "<green>◇</fg> foo 29 - ", 30 - "<dim>│</fg> 31 - ", 32 - "<dim>│</fg> <dim>line 0</bold> 33 - ", 34 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 35 - "<dim>│</fg> <dim>line 0</bold> 36 - <dim>│</fg> <dim>line 1</bold> 37 - ", 38 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 39 - "<dim>│</fg> 40 - <red>■</fg> some error! 41 - ", 42 - "<dim>│</fg> 43 - <dim>│</fg> <dim>line 0</bold> 44 - <dim>│</fg> <dim>line 1</bold> 45 - ", 46 - ] 47 - `; 48 - 49 - exports[`taskLog (isCI = false) > group > applies limit per group 1`] = ` 50 - [ 51 - "<dim>│</fg> 52 - ", 53 - "<green>◇</fg> Some log 54 - ", 55 - "<dim>│</fg> 56 - ", 57 - "<dim>│</fg> <bold>Group 0</bold> 58 - ", 59 - "<dim>│</fg> <dim>Group 0 line 0</bold> 60 - ", 61 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 62 - "<dim>│</fg> <bold>Group 0</bold> 63 - ", 64 - "<dim>│</fg> <dim>Group 0 line 0</bold> 65 - ", 66 - "<dim>│</fg> <bold>Group 1</bold> 67 - ", 68 - "<dim>│</fg> <dim>Group 1 line 0</bold> 69 - ", 70 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 71 - "<dim>│</fg> <bold>Group 0</bold> 72 - ", 73 - "<dim>│</fg> <dim>Group 0 line 0</bold> 74 - <dim>│</fg> <dim>Group 0 line 1</bold> 75 - ", 76 - "<dim>│</fg> <bold>Group 1</bold> 77 - ", 78 - "<dim>│</fg> <dim>Group 1 line 0</bold> 79 - ", 80 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 81 - "<dim>│</fg> <bold>Group 0</bold> 82 - ", 83 - "<dim>│</fg> <dim>Group 0 line 0</bold> 84 - <dim>│</fg> <dim>Group 0 line 1</bold> 85 - ", 86 - "<dim>│</fg> <bold>Group 1</bold> 87 - ", 88 - "<dim>│</fg> <dim>Group 1 line 0</bold> 89 - <dim>│</fg> <dim>Group 1 line 1</bold> 90 - ", 91 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 92 - "<dim>│</fg> <bold>Group 0</bold> 93 - ", 94 - "<dim>│</fg> <dim>Group 0 line 1</bold> 95 - <dim>│</fg> <dim>Group 0 line 2</bold> 96 - ", 97 - "<dim>│</fg> <bold>Group 1</bold> 98 - ", 99 - "<dim>│</fg> <dim>Group 1 line 0</bold> 100 - <dim>│</fg> <dim>Group 1 line 1</bold> 101 - ", 102 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 103 - "<dim>│</fg> <bold>Group 0</bold> 104 - ", 105 - "<dim>│</fg> <dim>Group 0 line 1</bold> 106 - <dim>│</fg> <dim>Group 0 line 2</bold> 107 - ", 108 - "<dim>│</fg> <bold>Group 1</bold> 109 - ", 110 - "<dim>│</fg> <dim>Group 1 line 1</bold> 111 - <dim>│</fg> <dim>Group 1 line 2</bold> 112 - ", 113 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 114 - "<dim>│</fg> <bold>Group 0</bold> 115 - ", 116 - "<dim>│</fg> <dim>Group 0 line 2</bold> 117 - <dim>│</fg> <dim>Group 0 line 3</bold> 118 - ", 119 - "<dim>│</fg> <bold>Group 1</bold> 120 - ", 121 - "<dim>│</fg> <dim>Group 1 line 1</bold> 122 - <dim>│</fg> <dim>Group 1 line 2</bold> 123 - ", 124 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 125 - "<dim>│</fg> <bold>Group 0</bold> 126 - ", 127 - "<dim>│</fg> <dim>Group 0 line 2</bold> 128 - <dim>│</fg> <dim>Group 0 line 3</bold> 129 - ", 130 - "<dim>│</fg> <bold>Group 1</bold> 131 - ", 132 - "<dim>│</fg> <dim>Group 1 line 2</bold> 133 - <dim>│</fg> <dim>Group 1 line 3</bold> 134 - ", 135 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 136 - "<dim>│</fg> <bold>Group 0</bold> 137 - ", 138 - "<dim>│</fg> <dim>Group 0 line 3</bold> 139 - <dim>│</fg> <dim>Group 0 line 4</bold> 140 - ", 141 - "<dim>│</fg> <bold>Group 1</bold> 142 - ", 143 - "<dim>│</fg> <dim>Group 1 line 2</bold> 144 - <dim>│</fg> <dim>Group 1 line 3</bold> 145 - ", 146 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 147 - "<dim>│</fg> <bold>Group 0</bold> 148 - ", 149 - "<dim>│</fg> <dim>Group 0 line 3</bold> 150 - <dim>│</fg> <dim>Group 0 line 4</bold> 151 - ", 152 - "<dim>│</fg> <bold>Group 1</bold> 153 - ", 154 - "<dim>│</fg> <dim>Group 1 line 3</bold> 155 - <dim>│</fg> <dim>Group 1 line 4</bold> 156 - ", 157 - ] 158 - `; 159 - 160 - exports[`taskLog (isCI = false) > group > can render multiple groups of different sizes 1`] = ` 161 - [ 162 - "<dim>│</fg> 163 - ", 164 - "<green>◇</fg> Some log 165 - ", 166 - "<dim>│</fg> 167 - ", 168 - "<dim>│</fg> <bold>Group 0</bold> 169 - ", 170 - "<dim>│</fg> <dim>Group 0 line 0</bold> 171 - ", 172 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 173 - "<dim>│</fg> <bold>Group 0</bold> 174 - ", 175 - "<dim>│</fg> <dim>Group 0 line 0</bold> 176 - <dim>│</fg> <dim>Group 0 line 1</bold> 177 - ", 178 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 179 - "<dim>│</fg> <bold>Group 0</bold> 180 - ", 181 - "<dim>│</fg> <dim>Group 0 line 0</bold> 182 - <dim>│</fg> <dim>Group 0 line 1</bold> 183 - <dim>│</fg> <dim>Group 0 line 2</bold> 184 - ", 185 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 186 - "<dim>│</fg> <bold>Group 0</bold> 187 - ", 188 - "<dim>│</fg> <dim>Group 0 line 0</bold> 189 - <dim>│</fg> <dim>Group 0 line 1</bold> 190 - <dim>│</fg> <dim>Group 0 line 2</bold> 191 - ", 192 - "<dim>│</fg> <bold>Group 1</bold> 193 - ", 194 - "<dim>│</fg> <dim>Group 1 line 0</bold> 195 - ", 196 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 197 - "<dim>│</fg> <bold>Group 0</bold> 198 - ", 199 - "<dim>│</fg> <dim>Group 0 line 0</bold> 200 - <dim>│</fg> <dim>Group 0 line 1</bold> 201 - <dim>│</fg> <dim>Group 0 line 2</bold> 202 - ", 203 - "<dim>│</fg> <bold>Group 1</bold> 204 - ", 205 - "<dim>│</fg> <dim>Group 1 line 0</bold> 206 - <dim>│</fg> <dim>Group 1 line 1</bold> 207 - ", 208 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 209 - "<dim>│</fg> <bold>Group 0</bold> 210 - ", 211 - "<dim>│</fg> <dim>Group 0 line 0</bold> 212 - <dim>│</fg> <dim>Group 0 line 1</bold> 213 - <dim>│</fg> <dim>Group 0 line 2</bold> 214 - ", 215 - "<dim>│</fg> <bold>Group 1</bold> 216 - ", 217 - "<dim>│</fg> <dim>Group 1 line 0</bold> 218 - <dim>│</fg> <dim>Group 1 line 1</bold> 219 - <dim>│</fg> <dim>Group 1 line 2</bold> 220 - ", 221 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 222 - "<dim>│</fg> <bold>Group 0</bold> 223 - ", 224 - "<dim>│</fg> <dim>Group 0 line 0</bold> 225 - <dim>│</fg> <dim>Group 0 line 1</bold> 226 - <dim>│</fg> <dim>Group 0 line 2</bold> 227 - ", 228 - "<dim>│</fg> <bold>Group 1</bold> 229 - ", 230 - "<dim>│</fg> <dim>Group 1 line 0</bold> 231 - <dim>│</fg> <dim>Group 1 line 1</bold> 232 - <dim>│</fg> <dim>Group 1 line 2</bold> 233 - <dim>│</fg> <dim>Group 1 line 3</bold> 234 - ", 235 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 236 - "<dim>│</fg> <bold>Group 0</bold> 237 - ", 238 - "<dim>│</fg> <dim>Group 0 line 0</bold> 239 - <dim>│</fg> <dim>Group 0 line 1</bold> 240 - <dim>│</fg> <dim>Group 0 line 2</bold> 241 - ", 242 - "<dim>│</fg> <bold>Group 1</bold> 243 - ", 244 - "<dim>│</fg> <dim>Group 1 line 0</bold> 245 - <dim>│</fg> <dim>Group 1 line 1</bold> 246 - <dim>│</fg> <dim>Group 1 line 2</bold> 247 - <dim>│</fg> <dim>Group 1 line 3</bold> 248 - <dim>│</fg> <dim>Group 1 line 4</bold> 249 - ", 250 - ] 251 - `; 252 - 253 - exports[`taskLog (isCI = false) > group > can render multiple groups of equal size 1`] = ` 254 - [ 255 - "<dim>│</fg> 256 - ", 257 - "<green>◇</fg> Some log 258 - ", 259 - "<dim>│</fg> 260 - ", 261 - "<dim>│</fg> <bold>Group 0</bold> 262 - ", 263 - "<dim>│</fg> <dim>Group 0 line 0</bold> 264 - ", 265 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 266 - "<dim>│</fg> <bold>Group 0</bold> 267 - ", 268 - "<dim>│</fg> <dim>Group 0 line 0</bold> 269 - ", 270 - "<dim>│</fg> <bold>Group 1</bold> 271 - ", 272 - "<dim>│</fg> <dim>Group 1 line 0</bold> 273 - ", 274 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 275 - "<dim>│</fg> <bold>Group 0</bold> 276 - ", 277 - "<dim>│</fg> <dim>Group 0 line 0</bold> 278 - <dim>│</fg> <dim>Group 0 line 1</bold> 279 - ", 280 - "<dim>│</fg> <bold>Group 1</bold> 281 - ", 282 - "<dim>│</fg> <dim>Group 1 line 0</bold> 283 - ", 284 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 285 - "<dim>│</fg> <bold>Group 0</bold> 286 - ", 287 - "<dim>│</fg> <dim>Group 0 line 0</bold> 288 - <dim>│</fg> <dim>Group 0 line 1</bold> 289 - ", 290 - "<dim>│</fg> <bold>Group 1</bold> 291 - ", 292 - "<dim>│</fg> <dim>Group 1 line 0</bold> 293 - <dim>│</fg> <dim>Group 1 line 1</bold> 294 - ", 295 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 296 - "<dim>│</fg> <bold>Group 0</bold> 297 - ", 298 - "<dim>│</fg> <dim>Group 0 line 0</bold> 299 - <dim>│</fg> <dim>Group 0 line 1</bold> 300 - <dim>│</fg> <dim>Group 0 line 2</bold> 301 - ", 302 - "<dim>│</fg> <bold>Group 1</bold> 303 - ", 304 - "<dim>│</fg> <dim>Group 1 line 0</bold> 305 - <dim>│</fg> <dim>Group 1 line 1</bold> 306 - ", 307 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 308 - "<dim>│</fg> <bold>Group 0</bold> 309 - ", 310 - "<dim>│</fg> <dim>Group 0 line 0</bold> 311 - <dim>│</fg> <dim>Group 0 line 1</bold> 312 - <dim>│</fg> <dim>Group 0 line 2</bold> 313 - ", 314 - "<dim>│</fg> <bold>Group 1</bold> 315 - ", 316 - "<dim>│</fg> <dim>Group 1 line 0</bold> 317 - <dim>│</fg> <dim>Group 1 line 1</bold> 318 - <dim>│</fg> <dim>Group 1 line 2</bold> 319 - ", 320 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 321 - "<dim>│</fg> <bold>Group 0</bold> 322 - ", 323 - "<dim>│</fg> <dim>Group 0 line 0</bold> 324 - <dim>│</fg> <dim>Group 0 line 1</bold> 325 - <dim>│</fg> <dim>Group 0 line 2</bold> 326 - <dim>│</fg> <dim>Group 0 line 3</bold> 327 - ", 328 - "<dim>│</fg> <bold>Group 1</bold> 329 - ", 330 - "<dim>│</fg> <dim>Group 1 line 0</bold> 331 - <dim>│</fg> <dim>Group 1 line 1</bold> 332 - <dim>│</fg> <dim>Group 1 line 2</bold> 333 - ", 334 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 335 - "<dim>│</fg> <bold>Group 0</bold> 336 - ", 337 - "<dim>│</fg> <dim>Group 0 line 0</bold> 338 - <dim>│</fg> <dim>Group 0 line 1</bold> 339 - <dim>│</fg> <dim>Group 0 line 2</bold> 340 - <dim>│</fg> <dim>Group 0 line 3</bold> 341 - ", 342 - "<dim>│</fg> <bold>Group 1</bold> 343 - ", 344 - "<dim>│</fg> <dim>Group 1 line 0</bold> 345 - <dim>│</fg> <dim>Group 1 line 1</bold> 346 - <dim>│</fg> <dim>Group 1 line 2</bold> 347 - <dim>│</fg> <dim>Group 1 line 3</bold> 348 - ", 349 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 350 - "<dim>│</fg> <bold>Group 0</bold> 351 - ", 352 - "<dim>│</fg> <dim>Group 0 line 0</bold> 353 - <dim>│</fg> <dim>Group 0 line 1</bold> 354 - <dim>│</fg> <dim>Group 0 line 2</bold> 355 - <dim>│</fg> <dim>Group 0 line 3</bold> 356 - <dim>│</fg> <dim>Group 0 line 4</bold> 357 - ", 358 - "<dim>│</fg> <bold>Group 1</bold> 359 - ", 360 - "<dim>│</fg> <dim>Group 1 line 0</bold> 361 - <dim>│</fg> <dim>Group 1 line 1</bold> 362 - <dim>│</fg> <dim>Group 1 line 2</bold> 363 - <dim>│</fg> <dim>Group 1 line 3</bold> 364 - ", 365 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 366 - "<dim>│</fg> <bold>Group 0</bold> 367 - ", 368 - "<dim>│</fg> <dim>Group 0 line 0</bold> 369 - <dim>│</fg> <dim>Group 0 line 1</bold> 370 - <dim>│</fg> <dim>Group 0 line 2</bold> 371 - <dim>│</fg> <dim>Group 0 line 3</bold> 372 - <dim>│</fg> <dim>Group 0 line 4</bold> 373 - ", 374 - "<dim>│</fg> <bold>Group 1</bold> 375 - ", 376 - "<dim>│</fg> <dim>Group 1 line 0</bold> 377 - <dim>│</fg> <dim>Group 1 line 1</bold> 378 - <dim>│</fg> <dim>Group 1 line 2</bold> 379 - <dim>│</fg> <dim>Group 1 line 3</bold> 380 - <dim>│</fg> <dim>Group 1 line 4</bold> 381 - ", 382 - ] 383 - `; 384 - 385 - exports[`taskLog (isCI = false) > group > handles empty groups 1`] = ` 386 - [ 387 - "<dim>│</fg> 388 - ", 389 - "<green>◇</fg> Some log 390 - ", 391 - "<dim>│</fg> 392 - ", 393 - "<green>◆</fg> Group success! 394 - ", 395 - ] 396 - `; 397 - 398 - exports[`taskLog (isCI = false) > group > renders error state 1`] = ` 399 - [ 400 - "<dim>│</fg> 401 - ", 402 - "<green>◇</fg> Some log 403 - ", 404 - "<dim>│</fg> 405 - ", 406 - "<dim>│</fg> <bold>Group 0</bold> 407 - ", 408 - "<dim>│</fg> <dim>Group 0 line 0</bold> 409 - ", 410 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 411 - "<red>■</fg> Group error! 412 - ", 413 - ] 414 - `; 415 - 416 - exports[`taskLog (isCI = false) > group > renders group error state 1`] = ` 417 - [ 418 - "<dim>│</fg> 419 - ", 420 - "<green>◇</fg> Some log 421 - ", 422 - "<dim>│</fg> 423 - ", 424 - "<dim>│</fg> <bold>Group 0</bold> 425 - ", 426 - "<dim>│</fg> <dim>Group 0 line 0</bold> 427 - ", 428 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 429 - "<red>■</fg> Group error! 430 - ", 431 - ] 432 - `; 433 - 434 - exports[`taskLog (isCI = false) > group > renders group success state 1`] = ` 435 - [ 436 - "<dim>│</fg> 437 - ", 438 - "<green>◇</fg> Some log 439 - ", 440 - "<dim>│</fg> 441 - ", 442 - "<dim>│</fg> <bold>Group 0</bold> 443 - ", 444 - "<dim>│</fg> <dim>Group 0 line 0</bold> 445 - ", 446 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 447 - "<green>◆</fg> Group success! 448 - ", 449 - ] 450 - `; 451 - 452 - exports[`taskLog (isCI = false) > group > renders success state 1`] = ` 453 - [ 454 - "<dim>│</fg> 455 - ", 456 - "<green>◇</fg> Some log 457 - ", 458 - "<dim>│</fg> 459 - ", 460 - "<dim>│</fg> <bold>Group 0</bold> 461 - ", 462 - "<dim>│</fg> <dim>Group 0 line 0</bold> 463 - ", 464 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 465 - "<green>◆</fg> Group success! 466 - ", 467 - ] 468 - `; 469 - 470 - exports[`taskLog (isCI = false) > group > showLog shows all groups in order 1`] = ` 471 - [ 472 - "<dim>│</fg> 473 - ", 474 - "<green>◇</fg> Some log 475 - ", 476 - "<dim>│</fg> 477 - ", 478 - "<dim>│</fg> <bold>Group 0</bold> 479 - ", 480 - "<dim>│</fg> <dim>Group 0 line 0</bold> 481 - ", 482 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 483 - "<dim>│</fg> <bold>Group 0</bold> 484 - ", 485 - "<dim>│</fg> <dim>Group 0 line 0</bold> 486 - <dim>│</fg> <dim>Group 0 line 1</bold> 487 - ", 488 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 489 - "<dim>│</fg> <bold>Group 0</bold> 490 - ", 491 - "<dim>│</fg> <dim>Group 0 line 0</bold> 492 - <dim>│</fg> <dim>Group 0 line 1</bold> 493 - <dim>│</fg> <dim>Group 0 line 2</bold> 494 - ", 495 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 496 - "<dim>│</fg> <bold>Group 0</bold> 497 - ", 498 - "<dim>│</fg> <dim>Group 0 line 0</bold> 499 - <dim>│</fg> <dim>Group 0 line 1</bold> 500 - <dim>│</fg> <dim>Group 0 line 2</bold> 501 - ", 502 - "<dim>│</fg> <bold>Group 1</bold> 503 - ", 504 - "<dim>│</fg> <dim>Group 1 line 0</bold> 505 - ", 506 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 507 - "<dim>│</fg> <bold>Group 0</bold> 508 - ", 509 - "<dim>│</fg> <dim>Group 0 line 0</bold> 510 - <dim>│</fg> <dim>Group 0 line 1</bold> 511 - <dim>│</fg> <dim>Group 0 line 2</bold> 512 - ", 513 - "<dim>│</fg> <bold>Group 1</bold> 514 - ", 515 - "<dim>│</fg> <dim>Group 1 line 0</bold> 516 - <dim>│</fg> <dim>Group 1 line 1</bold> 517 - ", 518 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 519 - "<dim>│</fg> <bold>Group 0</bold> 520 - ", 521 - "<dim>│</fg> <dim>Group 0 line 0</bold> 522 - <dim>│</fg> <dim>Group 0 line 1</bold> 523 - <dim>│</fg> <dim>Group 0 line 2</bold> 524 - ", 525 - "<dim>│</fg> <bold>Group 1</bold> 526 - ", 527 - "<dim>│</fg> <dim>Group 1 line 0</bold> 528 - <dim>│</fg> <dim>Group 1 line 1</bold> 529 - <dim>│</fg> <dim>Group 1 line 2</bold> 530 - ", 531 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 532 - "<dim>│</fg> <bold>Group 0</bold> 533 - ", 534 - "<dim>│</fg> <dim>Group 0 line 0</bold> 535 - <dim>│</fg> <dim>Group 0 line 1</bold> 536 - <dim>│</fg> <dim>Group 0 line 2</bold> 537 - ", 538 - "<dim>│</fg> <bold>Group 1</bold> 539 - ", 540 - "<dim>│</fg> <dim>Group 1 line 0</bold> 541 - <dim>│</fg> <dim>Group 1 line 1</bold> 542 - <dim>│</fg> <dim>Group 1 line 2</bold> 543 - <dim>│</fg> <dim>Group 1 line 3</bold> 544 - ", 545 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 546 - "<dim>│</fg> <bold>Group 0</bold> 547 - ", 548 - "<dim>│</fg> <dim>Group 0 line 0</bold> 549 - <dim>│</fg> <dim>Group 0 line 1</bold> 550 - <dim>│</fg> <dim>Group 0 line 2</bold> 551 - ", 552 - "<dim>│</fg> <bold>Group 1</bold> 553 - ", 554 - "<dim>│</fg> <dim>Group 1 line 0</bold> 555 - <dim>│</fg> <dim>Group 1 line 1</bold> 556 - <dim>│</fg> <dim>Group 1 line 2</bold> 557 - <dim>│</fg> <dim>Group 1 line 3</bold> 558 - <dim>│</fg> <dim>Group 1 line 4</bold> 559 - ", 560 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 561 - "<green>◆</fg> Group 0 success! 562 - ", 563 - "<dim>│</fg> <bold>Group 1</bold> 564 - ", 565 - "<dim>│</fg> <dim>Group 1 line 0</bold> 566 - <dim>│</fg> <dim>Group 1 line 1</bold> 567 - <dim>│</fg> <dim>Group 1 line 2</bold> 568 - <dim>│</fg> <dim>Group 1 line 3</bold> 569 - <dim>│</fg> <dim>Group 1 line 4</bold> 570 - ", 571 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 572 - "<green>◆</fg> Group 0 success! 573 - ", 574 - "<red>■</fg> Group 1 error! 575 - ", 576 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 577 - "<dim>│</fg> 578 - <red>■</fg> overall error 579 - ", 580 - "<dim>│</fg> <bold>Group 0</bold> 581 - ", 582 - "<dim>│</fg> 583 - <dim>│</fg> <dim>Group 0 line 0</bold> 584 - <dim>│</fg> <dim>Group 0 line 1</bold> 585 - <dim>│</fg> <dim>Group 0 line 2</bold> 586 - ", 587 - "<dim>│</fg> <bold>Group 1</bold> 588 - ", 589 - "<dim>│</fg> 590 - <dim>│</fg> <dim>Group 1 line 0</bold> 591 - <dim>│</fg> <dim>Group 1 line 1</bold> 592 - <dim>│</fg> <dim>Group 1 line 2</bold> 593 - <dim>│</fg> <dim>Group 1 line 3</bold> 594 - <dim>│</fg> <dim>Group 1 line 4</bold> 595 - ", 596 - ] 597 - `; 598 - 599 - exports[`taskLog (isCI = false) > message > can write line by line 1`] = ` 600 - [ 601 - "<dim>│</fg> 602 - ", 603 - "<green>◇</fg> foo 604 - ", 605 - "<dim>│</fg> 606 - ", 607 - "<dim>│</fg> <dim>line 0</bold> 608 - ", 609 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 610 - "<dim>│</fg> <dim>line 0</bold> 611 - <dim>│</fg> <dim>line 1</bold> 612 - ", 613 - ] 614 - `; 615 - 616 - exports[`taskLog (isCI = false) > message > can write multiple lines 1`] = ` 617 - [ 618 - "<dim>│</fg> 619 - ", 620 - "<green>◇</fg> foo 621 - ", 622 - "<dim>│</fg> 623 - ", 624 - "<dim>│</fg> <dim>line 0</bold> 625 - <dim>│</fg> <dim>line 1</bold> 626 - ", 627 - ] 628 - `; 629 - 630 - exports[`taskLog (isCI = false) > message > destructive ansi codes are stripped 1`] = ` 631 - [ 632 - "<dim>│</fg> 633 - ", 634 - "<green>◇</fg> foo 635 - ", 636 - "<dim>│</fg> 637 - ", 638 - "<dim>│</fg> <dim>line 1</bold> 639 - ", 640 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 641 - "<dim>│</fg> <dim>line 1</bold> 642 - <dim>│</fg> <dim>line 2 bad ansi!</bold> 643 - ", 644 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 645 - "<dim>│</fg> <dim>line 1</bold> 646 - <dim>│</fg> <dim>line 2 bad ansi!</bold> 647 - <dim>│</fg> <dim>line 3</bold> 648 - ", 649 - ] 650 - `; 651 - 652 - exports[`taskLog (isCI = false) > message > enforces limit if set 1`] = ` 653 - [ 654 - "<dim>│</fg> 655 - ", 656 - "<green>◇</fg> foo 657 - ", 658 - "<dim>│</fg> 659 - ", 660 - "<dim>│</fg> <dim>line 0</bold> 661 - ", 662 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 663 - "<dim>│</fg> <dim>line 0</bold> 664 - <dim>│</fg> <dim>line 1</bold> 665 - ", 666 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 667 - "<dim>│</fg> <dim>line 1</bold> 668 - <dim>│</fg> <dim>line 2</bold> 669 - ", 670 - ] 671 - `; 672 - 673 - exports[`taskLog (isCI = false) > message > prints empty lines 1`] = ` 674 - [ 675 - "<dim>│</fg> 676 - ", 677 - "<green>◇</fg> foo 678 - ", 679 - "<dim>│</fg> 680 - ", 681 - "<dim>│</fg> <dim>line 1</bold> 682 - ", 683 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 684 - "<dim>│</fg> <dim>line 1</bold> 685 - <dim>│</fg> <dim></bold> 686 - ", 687 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 688 - "<dim>│</fg> <dim>line 1</bold> 689 - <dim>│</fg> <dim></bold> 690 - <dim>│</fg> <dim>line 3</bold> 691 - ", 692 - ] 693 - `; 694 - 695 - exports[`taskLog (isCI = false) > message > raw = true appends message text until newline 1`] = ` 696 - [ 697 - "<dim>│</fg> 698 - ", 699 - "<green>◇</fg> foo 700 - ", 701 - "<dim>│</fg> 702 - ", 703 - "<dim>│</fg> <dim>line 0</bold> 704 - ", 705 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 706 - "<dim>│</fg> <dim>line 0still line 0</bold> 707 - ", 708 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 709 - "<dim>│</fg> <dim>line 0still line 0</bold> 710 - <dim>│</fg> <dim>line 1</bold> 711 - ", 712 - ] 713 - `; 714 - 715 - exports[`taskLog (isCI = false) > message > raw = true works when mixed with non-raw messages 1`] = ` 716 - [ 717 - "<dim>│</fg> 718 - ", 719 - "<green>◇</fg> foo 720 - ", 721 - "<dim>│</fg> 722 - ", 723 - "<dim>│</fg> <dim>line 0</bold> 724 - ", 725 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 726 - "<dim>│</fg> <dim>line 0still line 0</bold> 727 - ", 728 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 729 - "<dim>│</fg> <dim>line 0still line 0</bold> 730 - <dim>│</fg> <dim>line 1</bold> 731 - ", 732 - ] 733 - `; 734 - 735 - exports[`taskLog (isCI = false) > message > raw = true works when started with non-raw messages 1`] = ` 736 - [ 737 - "<dim>│</fg> 738 - ", 739 - "<green>◇</fg> foo 740 - ", 741 - "<dim>│</fg> 742 - ", 743 - "<dim>│</fg> <dim>line 0</bold> 744 - ", 745 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 746 - "<dim>│</fg> <dim>line 0</bold> 747 - <dim>│</fg> <dim>line 1</bold> 748 - ", 749 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 750 - "<dim>│</fg> <dim>line 0</bold> 751 - <dim>│</fg> <dim>line 1still line 1</bold> 752 - ", 753 - ] 754 - `; 755 - 756 - exports[`taskLog (isCI = false) > retainLog > error > outputs limited log with limit by default 1`] = ` 757 - [ 758 - "<dim>│</fg> 759 - ", 760 - "<green>◇</fg> foo 761 - ", 762 - "<dim>│</fg> 763 - ", 764 - "<dim>│</fg> <dim>line 0</bold> 765 - ", 766 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 767 - "<dim>│</fg> <dim>line 0</bold> 768 - <dim>│</fg> <dim>line 1</bold> 769 - ", 770 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 771 - "<dim>│</fg> <dim>line 1</bold> 772 - <dim>│</fg> <dim>line 2</bold> 773 - ", 774 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 775 - "<dim>│</fg> <dim>line 2</bold> 776 - <dim>│</fg> <dim>line 3</bold> 777 - ", 778 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 779 - "<dim>│</fg> 780 - <red>■</fg> woo! 781 - ", 782 - "<dim>│</fg> 783 - <dim>│</fg> <dim>line 2</bold> 784 - <dim>│</fg> <dim>line 3</bold> 785 - ", 786 - ] 787 - `; 788 - 789 - exports[`taskLog (isCI = false) > retainLog > error > retainLog = false outputs full log without limit 1`] = ` 790 - [ 791 - "<dim>│</fg> 792 - ", 793 - "<green>◇</fg> foo 794 - ", 795 - "<dim>│</fg> 796 - ", 797 - "<dim>│</fg> <dim>line 0</bold> 798 - ", 799 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 800 - "<dim>│</fg> <dim>line 0</bold> 801 - <dim>│</fg> <dim>line 1</bold> 802 - ", 803 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 804 - "<dim>│</fg> <dim>line 0</bold> 805 - <dim>│</fg> <dim>line 1</bold> 806 - <dim>│</fg> <dim>line 2</bold> 807 - ", 808 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 809 - "<dim>│</fg> <dim>line 0</bold> 810 - <dim>│</fg> <dim>line 1</bold> 811 - <dim>│</fg> <dim>line 2</bold> 812 - <dim>│</fg> <dim>line 3</bold> 813 - ", 814 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 815 - "<dim>│</fg> 816 - <red>■</fg> woo! 817 - ", 818 - "<dim>│</fg> 819 - <dim>│</fg> <dim>line 0</bold> 820 - <dim>│</fg> <dim>line 1</bold> 821 - <dim>│</fg> <dim>line 2</bold> 822 - <dim>│</fg> <dim>line 3</bold> 823 - ", 824 - ] 825 - `; 826 - 827 - exports[`taskLog (isCI = false) > retainLog > error > retainLog = false outputs limited log with limit 1`] = ` 828 - [ 829 - "<dim>│</fg> 830 - ", 831 - "<green>◇</fg> foo 832 - ", 833 - "<dim>│</fg> 834 - ", 835 - "<dim>│</fg> <dim>line 0</bold> 836 - ", 837 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 838 - "<dim>│</fg> <dim>line 0</bold> 839 - <dim>│</fg> <dim>line 1</bold> 840 - ", 841 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 842 - "<dim>│</fg> <dim>line 1</bold> 843 - <dim>│</fg> <dim>line 2</bold> 844 - ", 845 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 846 - "<dim>│</fg> <dim>line 2</bold> 847 - <dim>│</fg> <dim>line 3</bold> 848 - ", 849 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 850 - "<dim>│</fg> 851 - <red>■</fg> woo! 852 - ", 853 - "<dim>│</fg> 854 - <dim>│</fg> <dim>line 2</bold> 855 - <dim>│</fg> <dim>line 3</bold> 856 - ", 857 - ] 858 - `; 859 - 860 - exports[`taskLog (isCI = false) > retainLog > error > retainLog = true outputs full log 1`] = ` 861 - [ 862 - "<dim>│</fg> 863 - ", 864 - "<green>◇</fg> foo 865 - ", 866 - "<dim>│</fg> 867 - ", 868 - "<dim>│</fg> <dim>line 0</bold> 869 - ", 870 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 871 - "<dim>│</fg> <dim>line 0</bold> 872 - <dim>│</fg> <dim>line 1</bold> 873 - ", 874 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 875 - "<dim>│</fg> <dim>line 0</bold> 876 - <dim>│</fg> <dim>line 1</bold> 877 - <dim>│</fg> <dim>line 2</bold> 878 - ", 879 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 880 - "<dim>│</fg> <dim>line 0</bold> 881 - <dim>│</fg> <dim>line 1</bold> 882 - <dim>│</fg> <dim>line 2</bold> 883 - <dim>│</fg> <dim>line 3</bold> 884 - ", 885 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 886 - "<dim>│</fg> 887 - <red>■</fg> woo! 888 - ", 889 - "<dim>│</fg> 890 - <dim>│</fg> <dim>line 0</bold> 891 - <dim>│</fg> <dim>line 1</bold> 892 - <dim>│</fg> <dim>line 2</bold> 893 - <dim>│</fg> <dim>line 3</bold> 894 - ", 895 - ] 896 - `; 897 - 898 - exports[`taskLog (isCI = false) > retainLog > error > retainLog = true outputs full log with limit 1`] = ` 899 - [ 900 - "<dim>│</fg> 901 - ", 902 - "<green>◇</fg> foo 903 - ", 904 - "<dim>│</fg> 905 - ", 906 - "<dim>│</fg> <dim>line 0</bold> 907 - ", 908 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 909 - "<dim>│</fg> <dim>line 0</bold> 910 - <dim>│</fg> <dim>line 1</bold> 911 - ", 912 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 913 - "<dim>│</fg> <dim>line 1</bold> 914 - <dim>│</fg> <dim>line 2</bold> 915 - ", 916 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 917 - "<dim>│</fg> <dim>line 2</bold> 918 - <dim>│</fg> <dim>line 3</bold> 919 - ", 920 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 921 - "<dim>│</fg> 922 - <red>■</fg> woo! 923 - ", 924 - "<dim>│</fg> 925 - <dim>│</fg> <dim>line 0</bold> 926 - <dim>│</fg> <dim>line 1</bold> 927 - <dim>│</fg> <dim>line 2</bold> 928 - <dim>│</fg> <dim>line 3</bold> 929 - ", 930 - ] 931 - `; 932 - 933 - exports[`taskLog (isCI = false) > retainLog > success > outputs limited log with limit by default 1`] = ` 934 - [ 935 - "<dim>│</fg> 936 - ", 937 - "<green>◇</fg> foo 938 - ", 939 - "<dim>│</fg> 940 - ", 941 - "<dim>│</fg> <dim>line 0</bold> 942 - ", 943 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 944 - "<dim>│</fg> <dim>line 0</bold> 945 - <dim>│</fg> <dim>line 1</bold> 946 - ", 947 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 948 - "<dim>│</fg> <dim>line 1</bold> 949 - <dim>│</fg> <dim>line 2</bold> 950 - ", 951 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 952 - "<dim>│</fg> <dim>line 2</bold> 953 - <dim>│</fg> <dim>line 3</bold> 954 - ", 955 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 956 - "<dim>│</fg> 957 - <green>◆</fg> woo! 958 - ", 959 - "<dim>│</fg> 960 - <dim>│</fg> <dim>line 2</bold> 961 - <dim>│</fg> <dim>line 3</bold> 962 - ", 963 - ] 964 - `; 965 - 966 - exports[`taskLog (isCI = false) > retainLog > success > retainLog = false outputs full log without limit 1`] = ` 967 - [ 968 - "<dim>│</fg> 969 - ", 970 - "<green>◇</fg> foo 971 - ", 972 - "<dim>│</fg> 973 - ", 974 - "<dim>│</fg> <dim>line 0</bold> 975 - ", 976 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 977 - "<dim>│</fg> <dim>line 0</bold> 978 - <dim>│</fg> <dim>line 1</bold> 979 - ", 980 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 981 - "<dim>│</fg> <dim>line 0</bold> 982 - <dim>│</fg> <dim>line 1</bold> 983 - <dim>│</fg> <dim>line 2</bold> 984 - ", 985 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 986 - "<dim>│</fg> <dim>line 0</bold> 987 - <dim>│</fg> <dim>line 1</bold> 988 - <dim>│</fg> <dim>line 2</bold> 989 - <dim>│</fg> <dim>line 3</bold> 990 - ", 991 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 992 - "<dim>│</fg> 993 - <green>◆</fg> woo! 994 - ", 995 - "<dim>│</fg> 996 - <dim>│</fg> <dim>line 0</bold> 997 - <dim>│</fg> <dim>line 1</bold> 998 - <dim>│</fg> <dim>line 2</bold> 999 - <dim>│</fg> <dim>line 3</bold> 1000 - ", 1001 - ] 1002 - `; 1003 - 1004 - exports[`taskLog (isCI = false) > retainLog > success > retainLog = false outputs limited log with limit 1`] = ` 1005 - [ 1006 - "<dim>│</fg> 1007 - ", 1008 - "<green>◇</fg> foo 1009 - ", 1010 - "<dim>│</fg> 1011 - ", 1012 - "<dim>│</fg> <dim>line 0</bold> 1013 - ", 1014 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1015 - "<dim>│</fg> <dim>line 0</bold> 1016 - <dim>│</fg> <dim>line 1</bold> 1017 - ", 1018 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1019 - "<dim>│</fg> <dim>line 1</bold> 1020 - <dim>│</fg> <dim>line 2</bold> 1021 - ", 1022 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1023 - "<dim>│</fg> <dim>line 2</bold> 1024 - <dim>│</fg> <dim>line 3</bold> 1025 - ", 1026 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1027 - "<dim>│</fg> 1028 - <green>◆</fg> woo! 1029 - ", 1030 - "<dim>│</fg> 1031 - <dim>│</fg> <dim>line 2</bold> 1032 - <dim>│</fg> <dim>line 3</bold> 1033 - ", 1034 - ] 1035 - `; 1036 - 1037 - exports[`taskLog (isCI = false) > retainLog > success > retainLog = true outputs full log 1`] = ` 1038 - [ 1039 - "<dim>│</fg> 1040 - ", 1041 - "<green>◇</fg> foo 1042 - ", 1043 - "<dim>│</fg> 1044 - ", 1045 - "<dim>│</fg> <dim>line 0</bold> 1046 - ", 1047 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1048 - "<dim>│</fg> <dim>line 0</bold> 1049 - <dim>│</fg> <dim>line 1</bold> 1050 - ", 1051 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1052 - "<dim>│</fg> <dim>line 0</bold> 1053 - <dim>│</fg> <dim>line 1</bold> 1054 - <dim>│</fg> <dim>line 2</bold> 1055 - ", 1056 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1057 - "<dim>│</fg> <dim>line 0</bold> 1058 - <dim>│</fg> <dim>line 1</bold> 1059 - <dim>│</fg> <dim>line 2</bold> 1060 - <dim>│</fg> <dim>line 3</bold> 1061 - ", 1062 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1063 - "<dim>│</fg> 1064 - <green>◆</fg> woo! 1065 - ", 1066 - "<dim>│</fg> 1067 - <dim>│</fg> <dim>line 0</bold> 1068 - <dim>│</fg> <dim>line 1</bold> 1069 - <dim>│</fg> <dim>line 2</bold> 1070 - <dim>│</fg> <dim>line 3</bold> 1071 - ", 1072 - ] 1073 - `; 1074 - 1075 - exports[`taskLog (isCI = false) > retainLog > success > retainLog = true outputs full log with limit 1`] = ` 1076 - [ 1077 - "<dim>│</fg> 1078 - ", 1079 - "<green>◇</fg> foo 1080 - ", 1081 - "<dim>│</fg> 1082 - ", 1083 - "<dim>│</fg> <dim>line 0</bold> 1084 - ", 1085 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1086 - "<dim>│</fg> <dim>line 0</bold> 1087 - <dim>│</fg> <dim>line 1</bold> 1088 - ", 1089 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1090 - "<dim>│</fg> <dim>line 1</bold> 1091 - <dim>│</fg> <dim>line 2</bold> 1092 - ", 1093 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1094 - "<dim>│</fg> <dim>line 2</bold> 1095 - <dim>│</fg> <dim>line 3</bold> 1096 - ", 1097 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1098 - "<dim>│</fg> 1099 - <green>◆</fg> woo! 1100 - ", 1101 - "<dim>│</fg> 1102 - <dim>│</fg> <dim>line 0</bold> 1103 - <dim>│</fg> <dim>line 1</bold> 1104 - <dim>│</fg> <dim>line 2</bold> 1105 - <dim>│</fg> <dim>line 3</bold> 1106 - ", 1107 - ] 1108 - `; 1109 - 1110 - exports[`taskLog (isCI = false) > success > clears output and renders message 1`] = ` 1111 - [ 1112 - "<dim>│</fg> 1113 - ", 1114 - "<green>◇</fg> foo 1115 - ", 1116 - "<dim>│</fg> 1117 - ", 1118 - "<dim>│</fg> <dim>line 0</bold> 1119 - ", 1120 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1121 - "<dim>│</fg> <dim>line 0</bold> 1122 - <dim>│</fg> <dim>line 1</bold> 1123 - ", 1124 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1125 - "<dim>│</fg> 1126 - <green>◆</fg> success! 1127 - ", 1128 - ] 1129 - `; 1130 - 1131 - exports[`taskLog (isCI = false) > success > renders output if showLog = true 1`] = ` 1132 - [ 1133 - "<dim>│</fg> 1134 - ", 1135 - "<green>◇</fg> foo 1136 - ", 1137 - "<dim>│</fg> 1138 - ", 1139 - "<dim>│</fg> <dim>line 0</bold> 1140 - ", 1141 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1142 - "<dim>│</fg> <dim>line 0</bold> 1143 - <dim>│</fg> <dim>line 1</bold> 1144 - ", 1145 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1146 - "<dim>│</fg> 1147 - <green>◆</fg> success! 1148 - ", 1149 - "<dim>│</fg> 1150 - <dim>│</fg> <dim>line 0</bold> 1151 - <dim>│</fg> <dim>line 1</bold> 1152 - ", 1153 - ] 1154 - `; 1155 - 1156 - exports[`taskLog (isCI = false) > writes message header 1`] = ` 1157 - [ 1158 - "<dim>│</fg> 1159 - ", 1160 - "<green>◇</fg> foo 1161 - ", 1162 - "<dim>│</fg> 1163 - ", 1164 - ] 1165 - `; 1166 - 1167 - exports[`taskLog (isCI = true) > error > clears output if showLog = false 1`] = ` 1168 - [ 1169 - "<dim>│</fg> 1170 - ", 1171 - "<green>◇</fg> foo 1172 - ", 1173 - "<dim>│</fg> 1174 - ", 1175 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1176 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1177 - "<dim>│</fg> 1178 - <red>■</fg> some error! 1179 - ", 1180 - ] 1181 - `; 1182 - 1183 - exports[`taskLog (isCI = true) > error > renders output with message 1`] = ` 1184 - [ 1185 - "<dim>│</fg> 1186 - ", 1187 - "<green>◇</fg> foo 1188 - ", 1189 - "<dim>│</fg> 1190 - ", 1191 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1192 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1193 - "<dim>│</fg> 1194 - <red>■</fg> some error! 1195 - ", 1196 - "<dim>│</fg> 1197 - <dim>│</fg> <dim>line 0</bold> 1198 - <dim>│</fg> <dim>line 1</bold> 1199 - ", 1200 - ] 1201 - `; 1202 - 1203 - exports[`taskLog (isCI = true) > group > applies limit per group 1`] = ` 1204 - [ 1205 - "<dim>│</fg> 1206 - ", 1207 - "<green>◇</fg> Some log 1208 - ", 1209 - "<dim>│</fg> 1210 - ", 1211 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1212 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1213 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1214 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1215 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1216 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1217 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1218 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1219 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1220 - ] 1221 - `; 1222 - 1223 - exports[`taskLog (isCI = true) > group > can render multiple groups of different sizes 1`] = ` 1224 - [ 1225 - "<dim>│</fg> 1226 - ", 1227 - "<green>◇</fg> Some log 1228 - ", 1229 - "<dim>│</fg> 1230 - ", 1231 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1232 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1233 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1234 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1235 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1236 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1237 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1238 - ] 1239 - `; 1240 - 1241 - exports[`taskLog (isCI = true) > group > can render multiple groups of equal size 1`] = ` 1242 - [ 1243 - "<dim>│</fg> 1244 - ", 1245 - "<green>◇</fg> Some log 1246 - ", 1247 - "<dim>│</fg> 1248 - ", 1249 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1250 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1251 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1252 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1253 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1254 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1255 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1256 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1257 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1258 - ] 1259 - `; 1260 - 1261 - exports[`taskLog (isCI = true) > group > handles empty groups 1`] = ` 1262 - [ 1263 - "<dim>│</fg> 1264 - ", 1265 - "<green>◇</fg> Some log 1266 - ", 1267 - "<dim>│</fg> 1268 - ", 1269 - ] 1270 - `; 1271 - 1272 - exports[`taskLog (isCI = true) > group > renders error state 1`] = ` 1273 - [ 1274 - "<dim>│</fg> 1275 - ", 1276 - "<green>◇</fg> Some log 1277 - ", 1278 - "<dim>│</fg> 1279 - ", 1280 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1281 - ] 1282 - `; 1283 - 1284 - exports[`taskLog (isCI = true) > group > renders group error state 1`] = ` 1285 - [ 1286 - "<dim>│</fg> 1287 - ", 1288 - "<green>◇</fg> Some log 1289 - ", 1290 - "<dim>│</fg> 1291 - ", 1292 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1293 - ] 1294 - `; 1295 - 1296 - exports[`taskLog (isCI = true) > group > renders group success state 1`] = ` 1297 - [ 1298 - "<dim>│</fg> 1299 - ", 1300 - "<green>◇</fg> Some log 1301 - ", 1302 - "<dim>│</fg> 1303 - ", 1304 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1305 - ] 1306 - `; 1307 - 1308 - exports[`taskLog (isCI = true) > group > renders success state 1`] = ` 1309 - [ 1310 - "<dim>│</fg> 1311 - ", 1312 - "<green>◇</fg> Some log 1313 - ", 1314 - "<dim>│</fg> 1315 - ", 1316 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1317 - ] 1318 - `; 1319 - 1320 - exports[`taskLog (isCI = true) > group > showLog shows all groups in order 1`] = ` 1321 - [ 1322 - "<dim>│</fg> 1323 - ", 1324 - "<green>◇</fg> Some log 1325 - ", 1326 - "<dim>│</fg> 1327 - ", 1328 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1329 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1330 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1331 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1332 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1333 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1334 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1335 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1336 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1337 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1338 - "<dim>│</fg> 1339 - <red>■</fg> overall error 1340 - ", 1341 - "<dim>│</fg> <bold>Group 0</bold> 1342 - ", 1343 - "<dim>│</fg> 1344 - <dim>│</fg> <dim>Group 0 line 0</bold> 1345 - <dim>│</fg> <dim>Group 0 line 1</bold> 1346 - <dim>│</fg> <dim>Group 0 line 2</bold> 1347 - ", 1348 - "<dim>│</fg> <bold>Group 1</bold> 1349 - ", 1350 - "<dim>│</fg> 1351 - <dim>│</fg> <dim>Group 1 line 0</bold> 1352 - <dim>│</fg> <dim>Group 1 line 1</bold> 1353 - <dim>│</fg> <dim>Group 1 line 2</bold> 1354 - <dim>│</fg> <dim>Group 1 line 3</bold> 1355 - <dim>│</fg> <dim>Group 1 line 4</bold> 1356 - ", 1357 - ] 1358 - `; 1359 - 1360 - exports[`taskLog (isCI = true) > message > can write line by line 1`] = ` 1361 - [ 1362 - "<dim>│</fg> 1363 - ", 1364 - "<green>◇</fg> foo 1365 - ", 1366 - "<dim>│</fg> 1367 - ", 1368 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1369 - ] 1370 - `; 1371 - 1372 - exports[`taskLog (isCI = true) > message > can write multiple lines 1`] = ` 1373 - [ 1374 - "<dim>│</fg> 1375 - ", 1376 - "<green>◇</fg> foo 1377 - ", 1378 - "<dim>│</fg> 1379 - ", 1380 - ] 1381 - `; 1382 - 1383 - exports[`taskLog (isCI = true) > message > destructive ansi codes are stripped 1`] = ` 1384 - [ 1385 - "<dim>│</fg> 1386 - ", 1387 - "<green>◇</fg> foo 1388 - ", 1389 - "<dim>│</fg> 1390 - ", 1391 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1392 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1393 - ] 1394 - `; 1395 - 1396 - exports[`taskLog (isCI = true) > message > enforces limit if set 1`] = ` 1397 - [ 1398 - "<dim>│</fg> 1399 - ", 1400 - "<green>◇</fg> foo 1401 - ", 1402 - "<dim>│</fg> 1403 - ", 1404 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1405 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1406 - ] 1407 - `; 1408 - 1409 - exports[`taskLog (isCI = true) > message > prints empty lines 1`] = ` 1410 - [ 1411 - "<dim>│</fg> 1412 - ", 1413 - "<green>◇</fg> foo 1414 - ", 1415 - "<dim>│</fg> 1416 - ", 1417 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1418 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1419 - ] 1420 - `; 1421 - 1422 - exports[`taskLog (isCI = true) > message > raw = true appends message text until newline 1`] = ` 1423 - [ 1424 - "<dim>│</fg> 1425 - ", 1426 - "<green>◇</fg> foo 1427 - ", 1428 - "<dim>│</fg> 1429 - ", 1430 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1431 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1432 - ] 1433 - `; 1434 - 1435 - exports[`taskLog (isCI = true) > message > raw = true works when mixed with non-raw messages 1`] = ` 1436 - [ 1437 - "<dim>│</fg> 1438 - ", 1439 - "<green>◇</fg> foo 1440 - ", 1441 - "<dim>│</fg> 1442 - ", 1443 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1444 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1445 - ] 1446 - `; 1447 - 1448 - exports[`taskLog (isCI = true) > message > raw = true works when started with non-raw messages 1`] = ` 1449 - [ 1450 - "<dim>│</fg> 1451 - ", 1452 - "<green>◇</fg> foo 1453 - ", 1454 - "<dim>│</fg> 1455 - ", 1456 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1457 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1458 - ] 1459 - `; 1460 - 1461 - exports[`taskLog (isCI = true) > retainLog > error > outputs limited log with limit by default 1`] = ` 1462 - [ 1463 - "<dim>│</fg> 1464 - ", 1465 - "<green>◇</fg> foo 1466 - ", 1467 - "<dim>│</fg> 1468 - ", 1469 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1470 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1471 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1472 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1473 - "<dim>│</fg> 1474 - <red>■</fg> woo! 1475 - ", 1476 - "<dim>│</fg> 1477 - <dim>│</fg> <dim>line 2</bold> 1478 - <dim>│</fg> <dim>line 3</bold> 1479 - ", 1480 - ] 1481 - `; 1482 - 1483 - exports[`taskLog (isCI = true) > retainLog > error > retainLog = false outputs full log without limit 1`] = ` 1484 - [ 1485 - "<dim>│</fg> 1486 - ", 1487 - "<green>◇</fg> foo 1488 - ", 1489 - "<dim>│</fg> 1490 - ", 1491 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1492 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1493 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1494 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1495 - "<dim>│</fg> 1496 - <red>■</fg> woo! 1497 - ", 1498 - "<dim>│</fg> 1499 - <dim>│</fg> <dim>line 0</bold> 1500 - <dim>│</fg> <dim>line 1</bold> 1501 - <dim>│</fg> <dim>line 2</bold> 1502 - <dim>│</fg> <dim>line 3</bold> 1503 - ", 1504 - ] 1505 - `; 1506 - 1507 - exports[`taskLog (isCI = true) > retainLog > error > retainLog = false outputs limited log with limit 1`] = ` 1508 - [ 1509 - "<dim>│</fg> 1510 - ", 1511 - "<green>◇</fg> foo 1512 - ", 1513 - "<dim>│</fg> 1514 - ", 1515 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1516 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1517 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1518 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1519 - "<dim>│</fg> 1520 - <red>■</fg> woo! 1521 - ", 1522 - "<dim>│</fg> 1523 - <dim>│</fg> <dim>line 2</bold> 1524 - <dim>│</fg> <dim>line 3</bold> 1525 - ", 1526 - ] 1527 - `; 1528 - 1529 - exports[`taskLog (isCI = true) > retainLog > error > retainLog = true outputs full log 1`] = ` 1530 - [ 1531 - "<dim>│</fg> 1532 - ", 1533 - "<green>◇</fg> foo 1534 - ", 1535 - "<dim>│</fg> 1536 - ", 1537 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1538 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1539 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1540 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1541 - "<dim>│</fg> 1542 - <red>■</fg> woo! 1543 - ", 1544 - "<dim>│</fg> 1545 - <dim>│</fg> <dim>line 0</bold> 1546 - <dim>│</fg> <dim>line 1</bold> 1547 - <dim>│</fg> <dim>line 2</bold> 1548 - <dim>│</fg> <dim>line 3</bold> 1549 - ", 1550 - ] 1551 - `; 1552 - 1553 - exports[`taskLog (isCI = true) > retainLog > error > retainLog = true outputs full log with limit 1`] = ` 1554 - [ 1555 - "<dim>│</fg> 1556 - ", 1557 - "<green>◇</fg> foo 1558 - ", 1559 - "<dim>│</fg> 1560 - ", 1561 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1562 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1563 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1564 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1565 - "<dim>│</fg> 1566 - <red>■</fg> woo! 1567 - ", 1568 - "<dim>│</fg> 1569 - <dim>│</fg> <dim>line 0</bold> 1570 - <dim>│</fg> <dim>line 1</bold> 1571 - <dim>│</fg> <dim>line 2</bold> 1572 - <dim>│</fg> <dim>line 3</bold> 1573 - ", 1574 - ] 1575 - `; 1576 - 1577 - exports[`taskLog (isCI = true) > retainLog > success > outputs limited log with limit by default 1`] = ` 1578 - [ 1579 - "<dim>│</fg> 1580 - ", 1581 - "<green>◇</fg> foo 1582 - ", 1583 - "<dim>│</fg> 1584 - ", 1585 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1586 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1587 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1588 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1589 - "<dim>│</fg> 1590 - <green>◆</fg> woo! 1591 - ", 1592 - "<dim>│</fg> 1593 - <dim>│</fg> <dim>line 2</bold> 1594 - <dim>│</fg> <dim>line 3</bold> 1595 - ", 1596 - ] 1597 - `; 1598 - 1599 - exports[`taskLog (isCI = true) > retainLog > success > retainLog = false outputs full log without limit 1`] = ` 1600 - [ 1601 - "<dim>│</fg> 1602 - ", 1603 - "<green>◇</fg> foo 1604 - ", 1605 - "<dim>│</fg> 1606 - ", 1607 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1608 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1609 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1610 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1611 - "<dim>│</fg> 1612 - <green>◆</fg> woo! 1613 - ", 1614 - "<dim>│</fg> 1615 - <dim>│</fg> <dim>line 0</bold> 1616 - <dim>│</fg> <dim>line 1</bold> 1617 - <dim>│</fg> <dim>line 2</bold> 1618 - <dim>│</fg> <dim>line 3</bold> 1619 - ", 1620 - ] 1621 - `; 1622 - 1623 - exports[`taskLog (isCI = true) > retainLog > success > retainLog = false outputs limited log with limit 1`] = ` 1624 - [ 1625 - "<dim>│</fg> 1626 - ", 1627 - "<green>◇</fg> foo 1628 - ", 1629 - "<dim>│</fg> 1630 - ", 1631 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1632 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1633 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1634 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1635 - "<dim>│</fg> 1636 - <green>◆</fg> woo! 1637 - ", 1638 - "<dim>│</fg> 1639 - <dim>│</fg> <dim>line 2</bold> 1640 - <dim>│</fg> <dim>line 3</bold> 1641 - ", 1642 - ] 1643 - `; 1644 - 1645 - exports[`taskLog (isCI = true) > retainLog > success > retainLog = true outputs full log 1`] = ` 1646 - [ 1647 - "<dim>│</fg> 1648 - ", 1649 - "<green>◇</fg> foo 1650 - ", 1651 - "<dim>│</fg> 1652 - ", 1653 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1654 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1655 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1656 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1657 - "<dim>│</fg> 1658 - <green>◆</fg> woo! 1659 - ", 1660 - "<dim>│</fg> 1661 - <dim>│</fg> <dim>line 0</bold> 1662 - <dim>│</fg> <dim>line 1</bold> 1663 - <dim>│</fg> <dim>line 2</bold> 1664 - <dim>│</fg> <dim>line 3</bold> 1665 - ", 1666 - ] 1667 - `; 1668 - 1669 - exports[`taskLog (isCI = true) > retainLog > success > retainLog = true outputs full log with limit 1`] = ` 1670 - [ 1671 - "<dim>│</fg> 1672 - ", 1673 - "<green>◇</fg> foo 1674 - ", 1675 - "<dim>│</fg> 1676 - ", 1677 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1678 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1679 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1680 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1681 - "<dim>│</fg> 1682 - <green>◆</fg> woo! 1683 - ", 1684 - "<dim>│</fg> 1685 - <dim>│</fg> <dim>line 0</bold> 1686 - <dim>│</fg> <dim>line 1</bold> 1687 - <dim>│</fg> <dim>line 2</bold> 1688 - <dim>│</fg> <dim>line 3</bold> 1689 - ", 1690 - ] 1691 - `; 1692 - 1693 - exports[`taskLog (isCI = true) > success > clears output and renders message 1`] = ` 1694 - [ 1695 - "<dim>│</fg> 1696 - ", 1697 - "<green>◇</fg> foo 1698 - ", 1699 - "<dim>│</fg> 1700 - ", 1701 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1702 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1703 - "<dim>│</fg> 1704 - <green>◆</fg> success! 1705 - ", 1706 - ] 1707 - `; 1708 - 1709 - exports[`taskLog (isCI = true) > success > renders output if showLog = true 1`] = ` 1710 - [ 1711 - "<dim>│</fg> 1712 - ", 1713 - "<green>◇</fg> foo 1714 - ", 1715 - "<dim>│</fg> 1716 - ", 1717 - "<erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1718 - "<erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.up count=1><erase.line><cursor.left count=1>", 1719 - "<dim>│</fg> 1720 - <green>◆</fg> success! 1721 - ", 1722 - "<dim>│</fg> 1723 - <dim>│</fg> <dim>line 0</bold> 1724 - <dim>│</fg> <dim>line 1</bold> 1725 - ", 1726 - ] 1727 - `; 1728 - 1729 - exports[`taskLog (isCI = true) > writes message header 1`] = ` 1730 - [ 1731 - "<dim>│</fg> 1732 - ", 1733 - "<green>◇</fg> foo 1734 - ", 1735 - "<dim>│</fg> 1736 - ", 1737 - ] 1738 - `;
-595
packages/prompts/test/__snapshots__/text.test.ts.snap
··· 1 - // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 - 3 - exports[`text (isCI = false) > can be aborted by a signal 1`] = ` 4 - [ 5 - "<cursor.hide>", 6 - "<dim>│</fg> 7 - <cyan>◆</fg> foo 8 - <cyan>│</fg> _ 9 - <cyan>└</fg> 10 - ", 11 - " 12 - ", 13 - "<cursor.show>", 14 - ] 15 - `; 16 - 17 - exports[`text (isCI = false) > can cancel 1`] = ` 18 - [ 19 - "<cursor.hide>", 20 - "<dim>│</fg> 21 - <cyan>◆</fg> foo 22 - <cyan>│</fg> _ 23 - <cyan>└</fg> 24 - ", 25 - "<cursor.backward count=999><cursor.up count=4>", 26 - "<cursor.down count=1>", 27 - "<erase.down>", 28 - "<red>■</fg> foo 29 - <dim>│</fg>", 30 - " 31 - ", 32 - "<cursor.show>", 33 - ] 34 - `; 35 - 36 - exports[`text (isCI = false) > defaultValue sets the value but does not render 1`] = ` 37 - [ 38 - "<cursor.hide>", 39 - "<dim>│</fg> 40 - <cyan>◆</fg> foo 41 - <cyan>│</fg> _ 42 - <cyan>└</fg> 43 - ", 44 - "<cursor.backward count=999><cursor.up count=4>", 45 - "<cursor.down count=1>", 46 - "<erase.down>", 47 - "<green>◇</fg> foo 48 - <dim>│</fg> <dim>bar</bold>", 49 - " 50 - ", 51 - "<cursor.show>", 52 - ] 53 - `; 54 - 55 - exports[`text (isCI = false) > empty string when no value and no default 1`] = ` 56 - [ 57 - "<cursor.hide>", 58 - "<dim>│</fg> 59 - <cyan>◆</fg> foo 60 - <cyan>│</fg>  <dim> (hit Enter to use default)</bold> 61 - <cyan>└</fg> 62 - ", 63 - "<cursor.backward count=999><cursor.up count=4>", 64 - "<cursor.down count=1>", 65 - "<erase.down>", 66 - "<green>◇</fg> foo 67 - <dim>│</fg>", 68 - " 69 - ", 70 - "<cursor.show>", 71 - ] 72 - `; 73 - 74 - exports[`text (isCI = false) > global withGuide: false removes guide 1`] = ` 75 - [ 76 - "<cursor.hide>", 77 - "<cyan>◆</fg> foo 78 - _ 79 - 80 - ", 81 - "<cursor.backward count=999><cursor.up count=3>", 82 - "<erase.down>", 83 - "<green>◇</fg> foo 84 - ", 85 - " 86 - ", 87 - "<cursor.show>", 88 - ] 89 - `; 90 - 91 - exports[`text (isCI = false) > placeholder is not used as value when pressing enter 1`] = ` 92 - [ 93 - "<cursor.hide>", 94 - "<dim>│</fg> 95 - <cyan>◆</fg> foo 96 - <cyan>│</fg>  <dim> (hit Enter to use default)</bold> 97 - <cyan>└</fg> 98 - ", 99 - "<cursor.backward count=999><cursor.up count=4>", 100 - "<cursor.down count=1>", 101 - "<erase.down>", 102 - "<green>◇</fg> foo 103 - <dim>│</fg> <dim>default-value</bold>", 104 - " 105 - ", 106 - "<cursor.show>", 107 - ] 108 - `; 109 - 110 - exports[`text (isCI = false) > renders cancelled value if one set 1`] = ` 111 - [ 112 - "<cursor.hide>", 113 - "<dim>│</fg> 114 - <cyan>◆</fg> foo 115 - <cyan>│</fg> _ 116 - <cyan>└</fg> 117 - ", 118 - "<cursor.backward count=999><cursor.up count=4>", 119 - "<cursor.down count=2>", 120 - "<erase.line><cursor.left count=1>", 121 - "<cyan>│</fg> x█", 122 - "<cursor.down count=2>", 123 - "<cursor.backward count=999><cursor.up count=4>", 124 - "<cursor.down count=2>", 125 - "<erase.line><cursor.left count=1>", 126 - "<cyan>│</fg> xy█", 127 - "<cursor.down count=2>", 128 - "<cursor.backward count=999><cursor.up count=4>", 129 - "<cursor.down count=1>", 130 - "<erase.down>", 131 - "<red>■</fg> foo 132 - <dim>│</fg> <dim>xy</bold> 133 - <dim>│</fg>", 134 - " 135 - ", 136 - "<cursor.show>", 137 - ] 138 - `; 139 - 140 - exports[`text (isCI = false) > renders message 1`] = ` 141 - [ 142 - "<cursor.hide>", 143 - "<dim>│</fg> 144 - <cyan>◆</fg> foo 145 - <cyan>│</fg> _ 146 - <cyan>└</fg> 147 - ", 148 - "<cursor.backward count=999><cursor.up count=4>", 149 - "<cursor.down count=1>", 150 - "<erase.down>", 151 - "<green>◇</fg> foo 152 - <dim>│</fg>", 153 - " 154 - ", 155 - "<cursor.show>", 156 - ] 157 - `; 158 - 159 - exports[`text (isCI = false) > renders placeholder if set 1`] = ` 160 - [ 161 - "<cursor.hide>", 162 - "<dim>│</fg> 163 - <cyan>◆</fg> foo 164 - <cyan>│</fg> b<dim>ar</bold> 165 - <cyan>└</fg> 166 - ", 167 - "<cursor.backward count=999><cursor.up count=4>", 168 - "<cursor.down count=1>", 169 - "<erase.down>", 170 - "<green>◇</fg> foo 171 - <dim>│</fg>", 172 - " 173 - ", 174 - "<cursor.show>", 175 - ] 176 - `; 177 - 178 - exports[`text (isCI = false) > renders submitted value 1`] = ` 179 - [ 180 - "<cursor.hide>", 181 - "<dim>│</fg> 182 - <cyan>◆</fg> foo 183 - <cyan>│</fg> _ 184 - <cyan>└</fg> 185 - ", 186 - "<cursor.backward count=999><cursor.up count=4>", 187 - "<cursor.down count=2>", 188 - "<erase.line><cursor.left count=1>", 189 - "<cyan>│</fg> x█", 190 - "<cursor.down count=2>", 191 - "<cursor.backward count=999><cursor.up count=4>", 192 - "<cursor.down count=2>", 193 - "<erase.line><cursor.left count=1>", 194 - "<cyan>│</fg> xy█", 195 - "<cursor.down count=2>", 196 - "<cursor.backward count=999><cursor.up count=4>", 197 - "<cursor.down count=1>", 198 - "<erase.down>", 199 - "<green>◇</fg> foo 200 - <dim>│</fg> <dim>xy</bold>", 201 - " 202 - ", 203 - "<cursor.show>", 204 - ] 205 - `; 206 - 207 - exports[`text (isCI = false) > validation errors render and clear (using Error) 1`] = ` 208 - [ 209 - "<cursor.hide>", 210 - "<dim>│</fg> 211 - <cyan>◆</fg> foo 212 - <cyan>│</fg> _ 213 - <cyan>└</fg> 214 - ", 215 - "<cursor.backward count=999><cursor.up count=4>", 216 - "<cursor.down count=2>", 217 - "<erase.line><cursor.left count=1>", 218 - "<cyan>│</fg> x█", 219 - "<cursor.down count=2>", 220 - "<cursor.backward count=999><cursor.up count=4>", 221 - "<cursor.down count=1>", 222 - "<erase.down>", 223 - "<yellow>▲</fg> foo 224 - <yellow>│</fg> x█ 225 - <yellow>└</fg> <yellow>should be xy</fg> 226 - ", 227 - "<cursor.backward count=999><cursor.up count=4>", 228 - "<cursor.down count=1>", 229 - "<erase.down>", 230 - "<cyan>◆</fg> foo 231 - <cyan>│</fg> xy█ 232 - <cyan>└</fg> 233 - ", 234 - "<cursor.backward count=999><cursor.up count=4>", 235 - "<cursor.down count=1>", 236 - "<erase.down>", 237 - "<green>◇</fg> foo 238 - <dim>│</fg> <dim>xy</bold>", 239 - " 240 - ", 241 - "<cursor.show>", 242 - ] 243 - `; 244 - 245 - exports[`text (isCI = false) > validation errors render and clear 1`] = ` 246 - [ 247 - "<cursor.hide>", 248 - "<dim>│</fg> 249 - <cyan>◆</fg> foo 250 - <cyan>│</fg> _ 251 - <cyan>└</fg> 252 - ", 253 - "<cursor.backward count=999><cursor.up count=4>", 254 - "<cursor.down count=2>", 255 - "<erase.line><cursor.left count=1>", 256 - "<cyan>│</fg> x█", 257 - "<cursor.down count=2>", 258 - "<cursor.backward count=999><cursor.up count=4>", 259 - "<cursor.down count=1>", 260 - "<erase.down>", 261 - "<yellow>▲</fg> foo 262 - <yellow>│</fg> x█ 263 - <yellow>└</fg> <yellow>should be xy</fg> 264 - ", 265 - "<cursor.backward count=999><cursor.up count=4>", 266 - "<cursor.down count=1>", 267 - "<erase.down>", 268 - "<cyan>◆</fg> foo 269 - <cyan>│</fg> xy█ 270 - <cyan>└</fg> 271 - ", 272 - "<cursor.backward count=999><cursor.up count=4>", 273 - "<cursor.down count=1>", 274 - "<erase.down>", 275 - "<green>◇</fg> foo 276 - <dim>│</fg> <dim>xy</bold>", 277 - " 278 - ", 279 - "<cursor.show>", 280 - ] 281 - `; 282 - 283 - exports[`text (isCI = false) > withGuide: false removes guide 1`] = ` 284 - [ 285 - "<cursor.hide>", 286 - "<cyan>◆</fg> foo 287 - _ 288 - 289 - ", 290 - "<cursor.backward count=999><cursor.up count=3>", 291 - "<erase.down>", 292 - "<green>◇</fg> foo 293 - ", 294 - " 295 - ", 296 - "<cursor.show>", 297 - ] 298 - `; 299 - 300 - exports[`text (isCI = true) > can be aborted by a signal 1`] = ` 301 - [ 302 - "<cursor.hide>", 303 - "<dim>│</fg> 304 - <cyan>◆</fg> foo 305 - <cyan>│</fg> _ 306 - <cyan>└</fg> 307 - ", 308 - " 309 - ", 310 - "<cursor.show>", 311 - ] 312 - `; 313 - 314 - exports[`text (isCI = true) > can cancel 1`] = ` 315 - [ 316 - "<cursor.hide>", 317 - "<dim>│</fg> 318 - <cyan>◆</fg> foo 319 - <cyan>│</fg> _ 320 - <cyan>└</fg> 321 - ", 322 - "<cursor.backward count=999><cursor.up count=4>", 323 - "<cursor.down count=1>", 324 - "<erase.down>", 325 - "<red>■</fg> foo 326 - <dim>│</fg>", 327 - " 328 - ", 329 - "<cursor.show>", 330 - ] 331 - `; 332 - 333 - exports[`text (isCI = true) > defaultValue sets the value but does not render 1`] = ` 334 - [ 335 - "<cursor.hide>", 336 - "<dim>│</fg> 337 - <cyan>◆</fg> foo 338 - <cyan>│</fg> _ 339 - <cyan>└</fg> 340 - ", 341 - "<cursor.backward count=999><cursor.up count=4>", 342 - "<cursor.down count=1>", 343 - "<erase.down>", 344 - "<green>◇</fg> foo 345 - <dim>│</fg> <dim>bar</bold>", 346 - " 347 - ", 348 - "<cursor.show>", 349 - ] 350 - `; 351 - 352 - exports[`text (isCI = true) > empty string when no value and no default 1`] = ` 353 - [ 354 - "<cursor.hide>", 355 - "<dim>│</fg> 356 - <cyan>◆</fg> foo 357 - <cyan>│</fg>  <dim> (hit Enter to use default)</bold> 358 - <cyan>└</fg> 359 - ", 360 - "<cursor.backward count=999><cursor.up count=4>", 361 - "<cursor.down count=1>", 362 - "<erase.down>", 363 - "<green>◇</fg> foo 364 - <dim>│</fg>", 365 - " 366 - ", 367 - "<cursor.show>", 368 - ] 369 - `; 370 - 371 - exports[`text (isCI = true) > global withGuide: false removes guide 1`] = ` 372 - [ 373 - "<cursor.hide>", 374 - "<cyan>◆</fg> foo 375 - _ 376 - 377 - ", 378 - "<cursor.backward count=999><cursor.up count=3>", 379 - "<erase.down>", 380 - "<green>◇</fg> foo 381 - ", 382 - " 383 - ", 384 - "<cursor.show>", 385 - ] 386 - `; 387 - 388 - exports[`text (isCI = true) > placeholder is not used as value when pressing enter 1`] = ` 389 - [ 390 - "<cursor.hide>", 391 - "<dim>│</fg> 392 - <cyan>◆</fg> foo 393 - <cyan>│</fg>  <dim> (hit Enter to use default)</bold> 394 - <cyan>└</fg> 395 - ", 396 - "<cursor.backward count=999><cursor.up count=4>", 397 - "<cursor.down count=1>", 398 - "<erase.down>", 399 - "<green>◇</fg> foo 400 - <dim>│</fg> <dim>default-value</bold>", 401 - " 402 - ", 403 - "<cursor.show>", 404 - ] 405 - `; 406 - 407 - exports[`text (isCI = true) > renders cancelled value if one set 1`] = ` 408 - [ 409 - "<cursor.hide>", 410 - "<dim>│</fg> 411 - <cyan>◆</fg> foo 412 - <cyan>│</fg> _ 413 - <cyan>└</fg> 414 - ", 415 - "<cursor.backward count=999><cursor.up count=4>", 416 - "<cursor.down count=2>", 417 - "<erase.line><cursor.left count=1>", 418 - "<cyan>│</fg> x█", 419 - "<cursor.down count=2>", 420 - "<cursor.backward count=999><cursor.up count=4>", 421 - "<cursor.down count=2>", 422 - "<erase.line><cursor.left count=1>", 423 - "<cyan>│</fg> xy█", 424 - "<cursor.down count=2>", 425 - "<cursor.backward count=999><cursor.up count=4>", 426 - "<cursor.down count=1>", 427 - "<erase.down>", 428 - "<red>■</fg> foo 429 - <dim>│</fg> <dim>xy</bold> 430 - <dim>│</fg>", 431 - " 432 - ", 433 - "<cursor.show>", 434 - ] 435 - `; 436 - 437 - exports[`text (isCI = true) > renders message 1`] = ` 438 - [ 439 - "<cursor.hide>", 440 - "<dim>│</fg> 441 - <cyan>◆</fg> foo 442 - <cyan>│</fg> _ 443 - <cyan>└</fg> 444 - ", 445 - "<cursor.backward count=999><cursor.up count=4>", 446 - "<cursor.down count=1>", 447 - "<erase.down>", 448 - "<green>◇</fg> foo 449 - <dim>│</fg>", 450 - " 451 - ", 452 - "<cursor.show>", 453 - ] 454 - `; 455 - 456 - exports[`text (isCI = true) > renders placeholder if set 1`] = ` 457 - [ 458 - "<cursor.hide>", 459 - "<dim>│</fg> 460 - <cyan>◆</fg> foo 461 - <cyan>│</fg> b<dim>ar</bold> 462 - <cyan>└</fg> 463 - ", 464 - "<cursor.backward count=999><cursor.up count=4>", 465 - "<cursor.down count=1>", 466 - "<erase.down>", 467 - "<green>◇</fg> foo 468 - <dim>│</fg>", 469 - " 470 - ", 471 - "<cursor.show>", 472 - ] 473 - `; 474 - 475 - exports[`text (isCI = true) > renders submitted value 1`] = ` 476 - [ 477 - "<cursor.hide>", 478 - "<dim>│</fg> 479 - <cyan>◆</fg> foo 480 - <cyan>│</fg> _ 481 - <cyan>└</fg> 482 - ", 483 - "<cursor.backward count=999><cursor.up count=4>", 484 - "<cursor.down count=2>", 485 - "<erase.line><cursor.left count=1>", 486 - "<cyan>│</fg> x█", 487 - "<cursor.down count=2>", 488 - "<cursor.backward count=999><cursor.up count=4>", 489 - "<cursor.down count=2>", 490 - "<erase.line><cursor.left count=1>", 491 - "<cyan>│</fg> xy█", 492 - "<cursor.down count=2>", 493 - "<cursor.backward count=999><cursor.up count=4>", 494 - "<cursor.down count=1>", 495 - "<erase.down>", 496 - "<green>◇</fg> foo 497 - <dim>│</fg> <dim>xy</bold>", 498 - " 499 - ", 500 - "<cursor.show>", 501 - ] 502 - `; 503 - 504 - exports[`text (isCI = true) > validation errors render and clear (using Error) 1`] = ` 505 - [ 506 - "<cursor.hide>", 507 - "<dim>│</fg> 508 - <cyan>◆</fg> foo 509 - <cyan>│</fg> _ 510 - <cyan>└</fg> 511 - ", 512 - "<cursor.backward count=999><cursor.up count=4>", 513 - "<cursor.down count=2>", 514 - "<erase.line><cursor.left count=1>", 515 - "<cyan>│</fg> x█", 516 - "<cursor.down count=2>", 517 - "<cursor.backward count=999><cursor.up count=4>", 518 - "<cursor.down count=1>", 519 - "<erase.down>", 520 - "<yellow>▲</fg> foo 521 - <yellow>│</fg> x█ 522 - <yellow>└</fg> <yellow>should be xy</fg> 523 - ", 524 - "<cursor.backward count=999><cursor.up count=4>", 525 - "<cursor.down count=1>", 526 - "<erase.down>", 527 - "<cyan>◆</fg> foo 528 - <cyan>│</fg> xy█ 529 - <cyan>└</fg> 530 - ", 531 - "<cursor.backward count=999><cursor.up count=4>", 532 - "<cursor.down count=1>", 533 - "<erase.down>", 534 - "<green>◇</fg> foo 535 - <dim>│</fg> <dim>xy</bold>", 536 - " 537 - ", 538 - "<cursor.show>", 539 - ] 540 - `; 541 - 542 - exports[`text (isCI = true) > validation errors render and clear 1`] = ` 543 - [ 544 - "<cursor.hide>", 545 - "<dim>│</fg> 546 - <cyan>◆</fg> foo 547 - <cyan>│</fg> _ 548 - <cyan>└</fg> 549 - ", 550 - "<cursor.backward count=999><cursor.up count=4>", 551 - "<cursor.down count=2>", 552 - "<erase.line><cursor.left count=1>", 553 - "<cyan>│</fg> x█", 554 - "<cursor.down count=2>", 555 - "<cursor.backward count=999><cursor.up count=4>", 556 - "<cursor.down count=1>", 557 - "<erase.down>", 558 - "<yellow>▲</fg> foo 559 - <yellow>│</fg> x█ 560 - <yellow>└</fg> <yellow>should be xy</fg> 561 - ", 562 - "<cursor.backward count=999><cursor.up count=4>", 563 - "<cursor.down count=1>", 564 - "<erase.down>", 565 - "<cyan>◆</fg> foo 566 - <cyan>│</fg> xy█ 567 - <cyan>└</fg> 568 - ", 569 - "<cursor.backward count=999><cursor.up count=4>", 570 - "<cursor.down count=1>", 571 - "<erase.down>", 572 - "<green>◇</fg> foo 573 - <dim>│</fg> <dim>xy</bold>", 574 - " 575 - ", 576 - "<cursor.show>", 577 - ] 578 - `; 579 - 580 - exports[`text (isCI = true) > withGuide: false removes guide 1`] = ` 581 - [ 582 - "<cursor.hide>", 583 - "<cyan>◆</fg> foo 584 - _ 585 - 586 - ", 587 - "<cursor.backward count=999><cursor.up count=3>", 588 - "<erase.down>", 589 - "<green>◇</fg> foo 590 - ", 591 - " 592 - ", 593 - "<cursor.show>", 594 - ] 595 - `;
+146 -161
packages/prompts/test/autocomplete.test.ts packages/prompts/src/autocomplete.test.ts
··· 1 - import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; 2 - import { autocomplete, autocompleteMultiselect } from '../src/autocomplete.js'; 3 - import { isCancel, updateSettings } from '../src/index.js'; 4 - import { MockReadable, MockWritable } from './test-utils.js'; 1 + import { afterEach, beforeEach, describe, expect, test } from 'vitest'; 2 + import { autocomplete, autocompleteMultiselect } from './autocomplete.js'; 3 + import { isCancel, updateSettings } from './index.js'; 4 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 5 5 6 6 describe('autocomplete', () => { 7 - let input: MockReadable; 8 - let output: MockWritable; 7 + let mocks: Mocks<{ input: true; output: true }>; 9 8 const testOptions = [ 10 9 { value: 'apple', label: 'Apple' }, 11 10 { value: 'banana', label: 'Banana' }, ··· 15 14 ]; 16 15 17 16 beforeEach(() => { 18 - input = new MockReadable(); 19 - output = new MockWritable(); 17 + mocks = createMocks({ input: true, output: true }); 20 18 }); 21 19 22 20 afterEach(() => { 23 - vi.restoreAllMocks(); 24 21 updateSettings({ withGuide: true }); 25 22 }); 26 23 ··· 28 25 const result = autocomplete({ 29 26 message: 'Select a fruit', 30 27 options: testOptions, 31 - input, 32 - output, 28 + input: mocks.input, 29 + output: mocks.output, 33 30 }); 34 31 35 - input.emit('keypress', '', { name: 'return' }); 32 + mocks.input.emit('keypress', '', { name: 'return' }); 36 33 await result; 37 - expect(output.buffer).toMatchSnapshot(); 34 + expect(mocks.output.buffer).toMatchSnapshot(); 38 35 }); 39 36 40 37 test('limits displayed options when maxItems is set', async () => { ··· 47 44 message: 'Select an option', 48 45 options, 49 46 maxItems: 6, 50 - input, 51 - output, 47 + input: mocks.input, 48 + output: mocks.output, 52 49 }); 53 50 54 - input.emit('keypress', '', { name: 'return' }); 51 + mocks.input.emit('keypress', '', { name: 'return' }); 55 52 await result; 56 - expect(output.buffer).toMatchSnapshot(); 53 + expect(mocks.output.buffer).toMatchSnapshot(); 57 54 }); 58 55 59 56 test('shows no matches message when search has no results', async () => { 60 57 const result = autocomplete({ 61 58 message: 'Select a fruit', 62 59 options: testOptions, 63 - input, 64 - output, 60 + input: mocks.input, 61 + output: mocks.output, 65 62 }); 66 63 67 64 // Type something that won't match 68 - input.emit('keypress', 'z', { name: 'z' }); 69 - input.emit('keypress', '', { name: 'return' }); 65 + mocks.input.emit('keypress', 'z', { name: 'z' }); 66 + mocks.input.emit('keypress', '', { name: 'return' }); 70 67 await result; 71 - expect(output.buffer).toMatchSnapshot(); 68 + expect(mocks.output.buffer).toMatchSnapshot(); 72 69 }); 73 70 74 71 test('shows hint when option has hint and is focused', async () => { 75 72 const result = autocomplete({ 76 73 message: 'Select a fruit', 77 74 options: [...testOptions, { value: 'kiwi', label: 'Kiwi', hint: 'New Zealand' }], 78 - input, 79 - output, 75 + input: mocks.input, 76 + output: mocks.output, 80 77 }); 81 78 82 79 // Navigate to the option with hint 83 - input.emit('keypress', '', { name: 'down' }); 84 - input.emit('keypress', '', { name: 'down' }); 85 - input.emit('keypress', '', { name: 'down' }); 86 - input.emit('keypress', '', { name: 'down' }); 87 - input.emit('keypress', '', { name: 'down' }); 88 - input.emit('keypress', '', { name: 'return' }); 80 + mocks.input.emit('keypress', '', { name: 'down' }); 81 + mocks.input.emit('keypress', '', { name: 'down' }); 82 + mocks.input.emit('keypress', '', { name: 'down' }); 83 + mocks.input.emit('keypress', '', { name: 'down' }); 84 + mocks.input.emit('keypress', '', { name: 'down' }); 85 + mocks.input.emit('keypress', '', { name: 'return' }); 89 86 await result; 90 - expect(output.buffer).toMatchSnapshot(); 87 + expect(mocks.output.buffer).toMatchSnapshot(); 91 88 }); 92 89 93 90 test('shows selected value in submit state', async () => { 94 91 const result = autocomplete({ 95 92 message: 'Select a fruit', 96 93 options: testOptions, 97 - input, 98 - output, 94 + input: mocks.input, 95 + output: mocks.output, 99 96 }); 100 97 101 98 // Select an option and submit 102 - input.emit('keypress', '', { name: 'down' }); 103 - input.emit('keypress', '', { name: 'return' }); 99 + mocks.input.emit('keypress', '', { name: 'down' }); 100 + mocks.input.emit('keypress', '', { name: 'return' }); 104 101 105 102 const value = await result; 106 103 expect(value).toBe('banana'); 107 - expect(output.buffer).toMatchSnapshot(); 104 + expect(mocks.output.buffer).toMatchSnapshot(); 108 105 }); 109 106 110 107 test('shows strikethrough in cancel state', async () => { 111 108 const result = autocomplete({ 112 109 message: 'Select a fruit', 113 110 options: testOptions, 114 - input, 115 - output, 111 + input: mocks.input, 112 + output: mocks.output, 116 113 }); 117 114 118 115 // Cancel with Ctrl+C 119 - input.emit('keypress', '\x03', { name: 'c', ctrl: true }); 116 + mocks.input.emit('keypress', '\x03', { name: 'c', ctrl: true }); 120 117 121 118 const value = await result; 122 119 expect(typeof value === 'symbol').toBe(true); 123 - expect(output.buffer).toMatchSnapshot(); 120 + expect(mocks.output.buffer).toMatchSnapshot(); 124 121 }); 125 122 126 123 test('renders placeholder if set', async () => { ··· 128 125 message: 'Select a fruit', 129 126 placeholder: 'Type to search...', 130 127 options: testOptions, 131 - input, 132 - output, 128 + input: mocks.input, 129 + output: mocks.output, 133 130 }); 134 131 135 - input.emit('keypress', '', { name: 'return' }); 132 + mocks.input.emit('keypress', '', { name: 'return' }); 136 133 const value = await result; 137 - expect(output.buffer).toMatchSnapshot(); 134 + expect(mocks.output.buffer).toMatchSnapshot(); 138 135 expect(value).toBe('apple'); 139 136 }); 140 137 ··· 143 140 message: 'Select a fruit', 144 141 placeholder: 'apple', 145 142 options: testOptions, 146 - input, 147 - output, 143 + input: mocks.input, 144 + output: mocks.output, 148 145 }); 149 146 150 - input.emit('keypress', '\t', { name: 'tab' }); 151 - input.emit('keypress', '', { name: 'return' }); 147 + mocks.input.emit('keypress', '\t', { name: 'tab' }); 148 + mocks.input.emit('keypress', '', { name: 'return' }); 152 149 const value = await result; 153 150 expect(value).toBe('apple'); 154 151 }); ··· 158 155 message: 'Select a fruit', 159 156 placeholder: 'Type to search...', 160 157 options: testOptions, 161 - input, 162 - output, 158 + input: mocks.input, 159 + output: mocks.output, 163 160 }); 164 161 165 - input.emit('keypress', '\t', { name: 'tab' }); 166 - input.emit('keypress', '', { name: 'return' }); 162 + mocks.input.emit('keypress', '\t', { name: 'tab' }); 163 + mocks.input.emit('keypress', '', { name: 'return' }); 167 164 const value = await result; 168 165 // Tab did not fill input with placeholder (no option matches), so Enter submits first option 169 166 expect(value).toBe('apple'); ··· 174 171 message: 'Select a fruit', 175 172 options: testOptions, 176 173 initialValue: 'cherry', 177 - input, 178 - output, 174 + input: mocks.input, 175 + output: mocks.output, 179 176 }); 180 177 181 - input.emit('keypress', '', { name: 'return' }); 178 + mocks.input.emit('keypress', '', { name: 'return' }); 182 179 const value = await result; 183 180 184 181 expect(value).toBe('cherry'); 185 - expect(output.buffer).toMatchSnapshot(); 182 + expect(mocks.output.buffer).toMatchSnapshot(); 186 183 }); 187 184 188 185 test('can be aborted by a signal', async () => { ··· 190 187 const result = autocomplete({ 191 188 message: 'foo', 192 189 options: testOptions, 193 - input, 194 - output, 190 + input: mocks.input, 191 + output: mocks.output, 195 192 signal: controller.signal, 196 193 }); 197 194 198 195 controller.abort(); 199 196 const value = await result; 200 197 expect(isCancel(value)).toBe(true); 201 - expect(output.buffer).toMatchSnapshot(); 198 + expect(mocks.output.buffer).toMatchSnapshot(); 202 199 }); 203 200 204 201 test('autocompleteMultiselect respects withGuide: false', async () => { ··· 206 203 message: 'Select fruits', 207 204 options: testOptions, 208 205 withGuide: false, 209 - input, 210 - output, 206 + input: mocks.input, 207 + output: mocks.output, 211 208 }); 212 209 213 - input.emit('keypress', '', { name: 'down' }); 214 - input.emit('keypress', '', { name: 'space' }); 215 - input.emit('keypress', '', { name: 'return' }); 210 + mocks.input.emit('keypress', '', { name: 'down' }); 211 + mocks.input.emit('keypress', '', { name: 'space' }); 212 + mocks.input.emit('keypress', '', { name: 'return' }); 216 213 217 214 const value = await result; 218 215 219 216 expect(value).toEqual(['banana']); 220 - expect(output.buffer).toMatchSnapshot(); 217 + expect(mocks.output.buffer).toMatchSnapshot(); 221 218 }); 222 219 223 220 test('autocompleteMultiselect respects global withGuide: false', async () => { ··· 226 223 const result = autocompleteMultiselect({ 227 224 message: 'Select fruits', 228 225 options: testOptions, 229 - input, 230 - output, 226 + input: mocks.input, 227 + output: mocks.output, 231 228 }); 232 229 233 - input.emit('keypress', '', { name: 'down' }); 234 - input.emit('keypress', '', { name: 'space' }); 235 - input.emit('keypress', '', { name: 'return' }); 230 + mocks.input.emit('keypress', '', { name: 'down' }); 231 + mocks.input.emit('keypress', '', { name: 'space' }); 232 + mocks.input.emit('keypress', '', { name: 'return' }); 236 233 237 234 const value = await result; 238 235 239 236 expect(value).toEqual(['banana']); 240 - expect(output.buffer).toMatchSnapshot(); 237 + expect(mocks.output.buffer).toMatchSnapshot(); 241 238 }); 242 239 243 240 test('renders bottom ellipsis when items do not fit', async () => { 244 - output.rows = 5; 241 + mocks.output.rows = 5; 245 242 246 243 const options = [ 247 244 { ··· 258 255 message: 'Select an option', 259 256 options, 260 257 maxItems: 5, 261 - input, 262 - output, 258 + input: mocks.input, 259 + output: mocks.output, 263 260 }); 264 261 265 - input.emit('keypress', '', { name: 'return' }); 262 + mocks.input.emit('keypress', '', { name: 'return' }); 266 263 await result; 267 - expect(output.buffer).toMatchSnapshot(); 264 + expect(mocks.output.buffer).toMatchSnapshot(); 268 265 }); 269 266 270 267 test('renders top ellipsis when scrolled down and its do not fit', async () => { 271 - output.rows = 5; 268 + mocks.output.rows = 5; 272 269 273 270 const options = [ 274 271 { ··· 288 285 options, 289 286 initialValue: 'option2', 290 287 maxItems: 5, 291 - input, 292 - output, 288 + input: mocks.input, 289 + output: mocks.output, 293 290 }); 294 291 295 - input.emit('keypress', '', { name: 'return' }); 292 + mocks.input.emit('keypress', '', { name: 'return' }); 296 293 await result; 297 - expect(output.buffer).toMatchSnapshot(); 294 + expect(mocks.output.buffer).toMatchSnapshot(); 298 295 }); 299 296 300 297 test('placeholder is shown if set', async () => { ··· 302 299 message: 'Select a fruit', 303 300 placeholder: 'Type to search...', 304 301 options: testOptions, 305 - input, 306 - output, 302 + input: mocks.input, 303 + output: mocks.output, 307 304 }); 308 305 309 - input.emit('keypress', 'g', { name: 'g' }); 310 - input.emit('keypress', '', { name: 'return' }); 306 + mocks.input.emit('keypress', 'g', { name: 'g' }); 307 + mocks.input.emit('keypress', '', { name: 'return' }); 311 308 const value = await result; 312 - expect(output.buffer).toMatchSnapshot(); 309 + expect(mocks.output.buffer).toMatchSnapshot(); 313 310 expect(value).toBe('grape'); 314 311 }); 315 312 ··· 318 315 const result = autocomplete({ 319 316 message: 'Select a fruit', 320 317 options: optionsWithDisabled, 321 - input, 322 - output, 318 + input: mocks.input, 319 + output: mocks.output, 323 320 }); 324 321 325 322 for (let i = 0; i < 5; i++) { 326 - input.emit('keypress', '', { name: 'down' }); 323 + mocks.input.emit('keypress', '', { name: 'down' }); 327 324 } 328 - input.emit('keypress', '', { name: 'return' }); 325 + mocks.input.emit('keypress', '', { name: 'return' }); 329 326 330 327 const value = await result; 331 328 expect(value).toBe('apple'); 332 - expect(output.buffer).toMatchSnapshot(); 329 + expect(mocks.output.buffer).toMatchSnapshot(); 333 330 }); 334 331 335 332 test('cannot select disabled options when only one left', async () => { ··· 337 334 const result = autocomplete({ 338 335 message: 'Select a fruit', 339 336 options: optionsWithDisabled, 340 - input, 341 - output, 337 + input: mocks.input, 338 + output: mocks.output, 342 339 }); 343 340 344 - input.emit('keypress', 'k', { name: 'k' }); 345 - input.emit('keypress', '', { name: 'return' }); 341 + mocks.input.emit('keypress', 'k', { name: 'k' }); 342 + mocks.input.emit('keypress', '', { name: 'return' }); 346 343 347 344 const value = await result; 348 345 expect(value).toBe(undefined); 349 - expect(output.buffer).toMatchSnapshot(); 346 + expect(mocks.output.buffer).toMatchSnapshot(); 350 347 }); 351 348 }); 352 349 353 350 describe('autocompleteMultiselect', () => { 354 - let input: MockReadable; 355 - let output: MockWritable; 351 + let mocks: Mocks<{ input: true; output: true }>; 356 352 const testOptions = [ 357 353 { value: 'apple', label: 'Apple' }, 358 354 { value: 'banana', label: 'Banana' }, ··· 362 358 ]; 363 359 364 360 beforeEach(() => { 365 - input = new MockReadable(); 366 - output = new MockWritable(); 367 - }); 368 - 369 - afterEach(() => { 370 - vi.restoreAllMocks(); 361 + mocks = createMocks({ input: true, output: true }); 371 362 }); 372 363 373 364 test('renders error when empty selection & required is true', async () => { ··· 375 366 message: 'Select a fruit', 376 367 options: testOptions, 377 368 required: true, 378 - input, 379 - output, 369 + input: mocks.input, 370 + output: mocks.output, 380 371 }); 381 372 382 - input.emit('keypress', '', { name: 'return' }); 383 - input.emit('keypress', '', { name: 'tab' }); 384 - input.emit('keypress', '', { name: 'return' }); 373 + mocks.input.emit('keypress', '', { name: 'return' }); 374 + mocks.input.emit('keypress', '', { name: 'tab' }); 375 + mocks.input.emit('keypress', '', { name: 'return' }); 385 376 await result; 386 - expect(output.buffer).toMatchSnapshot(); 377 + expect(mocks.output.buffer).toMatchSnapshot(); 387 378 }); 388 379 389 380 test('can be aborted by a signal', async () => { ··· 391 382 const result = autocompleteMultiselect({ 392 383 message: 'foo', 393 384 options: testOptions, 394 - input, 395 - output, 385 + input: mocks.input, 386 + output: mocks.output, 396 387 signal: controller.signal, 397 388 }); 398 389 399 390 controller.abort(); 400 391 const value = await result; 401 392 expect(isCancel(value)).toBe(true); 402 - expect(output.buffer).toMatchSnapshot(); 393 + expect(mocks.output.buffer).toMatchSnapshot(); 403 394 }); 404 395 405 396 test('can use navigation keys to select options', async () => { 406 397 const result = autocompleteMultiselect({ 407 398 message: 'Select fruits', 408 399 options: testOptions, 409 - input, 410 - output, 400 + input: mocks.input, 401 + output: mocks.output, 411 402 }); 412 403 413 - input.emit('keypress', '', { name: 'down' }); 414 - input.emit('keypress', '', { name: 'space' }); 415 - input.emit('keypress', '', { name: 'down' }); 416 - input.emit('keypress', '', { name: 'space' }); 417 - input.emit('keypress', '', { name: 'return' }); 404 + mocks.input.emit('keypress', '', { name: 'down' }); 405 + mocks.input.emit('keypress', '', { name: 'space' }); 406 + mocks.input.emit('keypress', '', { name: 'down' }); 407 + mocks.input.emit('keypress', '', { name: 'space' }); 408 + mocks.input.emit('keypress', '', { name: 'return' }); 418 409 419 410 const value = await result; 420 411 expect(value).toEqual(['banana', 'cherry']); 421 - expect(output.buffer).toMatchSnapshot(); 412 + expect(mocks.output.buffer).toMatchSnapshot(); 422 413 }); 423 414 424 415 test('supports custom filter function', async () => { 425 416 const result = autocompleteMultiselect({ 426 417 message: 'Select fruits', 427 418 options: testOptions, 428 - input, 429 - output, 419 + input: mocks.input, 420 + output: mocks.output, 430 421 // Custom filter that only matches exact prefix 431 422 filter: (search, option) => { 432 423 const label = option.label ?? String(option.value ?? ''); ··· 435 426 }); 436 427 437 428 // Type 'a' - should match 'Apple' only (not 'Banana' which contains 'a') 438 - input.emit('keypress', 'a', { name: 'a' }); 439 - input.emit('keypress', '', { name: 'tab' }); 440 - input.emit('keypress', '', { name: 'return' }); 429 + mocks.input.emit('keypress', 'a', { name: 'a' }); 430 + mocks.input.emit('keypress', '', { name: 'tab' }); 431 + mocks.input.emit('keypress', '', { name: 'return' }); 441 432 442 433 const value = await result; 443 434 expect(value).toEqual(['apple']); 444 - expect(output.buffer).toMatchSnapshot(); 435 + expect(mocks.output.buffer).toMatchSnapshot(); 445 436 }); 446 437 447 438 test('displays disabled options correctly', async () => { ··· 449 440 const result = autocompleteMultiselect({ 450 441 message: 'Select a fruit', 451 442 options: optionsWithDisabled, 452 - input, 453 - output, 443 + input: mocks.input, 444 + output: mocks.output, 454 445 }); 455 446 456 447 for (let i = 0; i < testOptions.length; i++) { 457 - input.emit('keypress', '', { name: 'down' }); 448 + mocks.input.emit('keypress', '', { name: 'down' }); 458 449 } 459 - input.emit('keypress', '', { name: 'tab' }); 460 - input.emit('keypress', '', { name: 'return' }); 450 + mocks.input.emit('keypress', '', { name: 'tab' }); 451 + mocks.input.emit('keypress', '', { name: 'return' }); 461 452 462 453 const value = await result; 463 454 expect(value).toEqual(['apple']); 464 - expect(output.buffer).toMatchSnapshot(); 455 + expect(mocks.output.buffer).toMatchSnapshot(); 465 456 }); 466 457 467 458 test('cannot select disabled options when only one left', async () => { ··· 469 460 const result = autocompleteMultiselect({ 470 461 message: 'Select a fruit', 471 462 options: optionsWithDisabled, 472 - input, 473 - output, 463 + input: mocks.input, 464 + output: mocks.output, 474 465 }); 475 466 476 - input.emit('keypress', 'k', { name: 'k' }); 477 - input.emit('keypress', '', { name: 'tab' }); 478 - input.emit('keypress', '', { name: 'return' }); 467 + mocks.input.emit('keypress', 'k', { name: 'k' }); 468 + mocks.input.emit('keypress', '', { name: 'tab' }); 469 + mocks.input.emit('keypress', '', { name: 'return' }); 479 470 480 471 const value = await result; 481 472 expect(value).toEqual([]); 482 - expect(output.buffer).toMatchSnapshot(); 473 + expect(mocks.output.buffer).toMatchSnapshot(); 483 474 }); 484 475 485 476 test('Tab with placeholder fills input; Enter submits current selection', async () => { ··· 487 478 message: 'Select fruits', 488 479 placeholder: 'apple', 489 480 options: testOptions, 490 - input, 491 - output, 481 + input: mocks.input, 482 + output: mocks.output, 492 483 }); 493 484 494 - input.emit('keypress', '\t', { name: 'tab' }); 495 - input.emit('keypress', '', { name: 'return' }); 485 + mocks.input.emit('keypress', '\t', { name: 'tab' }); 486 + mocks.input.emit('keypress', '', { name: 'return' }); 496 487 const value = await result; 497 488 expect(value).toEqual([]); 498 489 }); 499 490 }); 500 491 501 492 describe('autocomplete with custom filter', () => { 502 - let input: MockReadable; 503 - let output: MockWritable; 493 + let mocks: Mocks<{ input: true; output: true }>; 504 494 const testOptions = [ 505 495 { value: 'apple', label: 'Apple' }, 506 496 { value: 'banana', label: 'Banana' }, ··· 508 498 ]; 509 499 510 500 beforeEach(() => { 511 - input = new MockReadable(); 512 - output = new MockWritable(); 513 - }); 514 - 515 - afterEach(() => { 516 - vi.restoreAllMocks(); 501 + mocks = createMocks({ input: true, output: true }); 517 502 }); 518 503 519 504 test('uses custom filter function when provided', async () => { 520 505 const result = autocomplete({ 521 506 message: 'Select a fruit', 522 507 options: testOptions, 523 - input, 524 - output, 508 + input: mocks.input, 509 + output: mocks.output, 525 510 // Custom filter that only matches exact prefix 526 511 filter: (search, option) => { 527 512 const label = option.label ?? String(option.value ?? ''); ··· 530 515 }); 531 516 532 517 // Type 'a' - should match 'Apple' only (not 'Banana' which contains 'a') 533 - input.emit('keypress', 'a', { name: 'a' }); 534 - input.emit('keypress', '', { name: 'return' }); 518 + mocks.input.emit('keypress', 'a', { name: 'a' }); 519 + mocks.input.emit('keypress', '', { name: 'return' }); 535 520 536 521 const value = await result; 537 522 expect(value).toBe('apple'); 538 - expect(output.buffer).toMatchSnapshot(); 523 + expect(mocks.output.buffer).toMatchSnapshot(); 539 524 }); 540 525 541 526 test('falls back to default filter when not provided', async () => { 542 527 const result = autocomplete({ 543 528 message: 'Select a fruit', 544 529 options: testOptions, 545 - input, 546 - output, 530 + input: mocks.input, 531 + output: mocks.output, 547 532 }); 548 533 549 534 // Type 'a' - default filter should match both 'Apple' and 'Banana' 550 - input.emit('keypress', 'a', { name: 'a' }); 551 - input.emit('keypress', '', { name: 'return' }); 535 + mocks.input.emit('keypress', 'a', { name: 'a' }); 536 + mocks.input.emit('keypress', '', { name: 'return' }); 552 537 553 538 const value = await result; 554 539 // First match should be selected 555 540 expect(value).toBe('apple'); 556 - expect(output.buffer).toMatchSnapshot(); 541 + expect(mocks.output.buffer).toMatchSnapshot(); 557 542 }); 558 543 });
-273
packages/prompts/test/box.test.ts
··· 1 - import { styleText } from 'node:util'; 2 - import { updateSettings } from '@clack/core'; 3 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 4 - import * as prompts from '../src/index.js'; 5 - import { MockReadable, MockWritable } from './test-utils.js'; 6 - 7 - describe.each(['true', 'false'])('box (isCI = %s)', (isCI) => { 8 - let originalCI: string | undefined; 9 - let output: MockWritable; 10 - let input: MockReadable; 11 - 12 - beforeAll(() => { 13 - originalCI = process.env.CI; 14 - process.env.CI = isCI; 15 - }); 16 - 17 - afterAll(() => { 18 - process.env.CI = originalCI; 19 - }); 20 - 21 - beforeEach(() => { 22 - output = new MockWritable(); 23 - input = new MockReadable(); 24 - }); 25 - 26 - afterEach(() => { 27 - vi.restoreAllMocks(); 28 - updateSettings({ withGuide: true }); 29 - }); 30 - 31 - test('renders message', () => { 32 - prompts.box('message', undefined, { 33 - input, 34 - output, 35 - }); 36 - 37 - expect(output.buffer).toMatchSnapshot(); 38 - }); 39 - 40 - test('renders message with title', () => { 41 - prompts.box('message', 'some title', { 42 - input, 43 - output, 44 - }); 45 - 46 - expect(output.buffer).toMatchSnapshot(); 47 - }); 48 - 49 - test('renders as wide as longest line with width: auto', () => { 50 - prompts.box('short\nsomewhat questionably long line', 'title', { 51 - input, 52 - output, 53 - width: 'auto', 54 - }); 55 - 56 - expect(output.buffer).toMatchSnapshot(); 57 - }); 58 - 59 - test('renders as specified width', () => { 60 - prompts.box('short\nsomewhat questionably long line', 'title', { 61 - input, 62 - output, 63 - width: 0.5, 64 - }); 65 - 66 - expect(output.buffer).toMatchSnapshot(); 67 - }); 68 - 69 - test('wraps content to fit within specified width', () => { 70 - prompts.box('foo bar'.repeat(20), 'title', { 71 - input, 72 - output, 73 - width: 0.5, 74 - }); 75 - 76 - expect(output.buffer).toMatchSnapshot(); 77 - }); 78 - 79 - test('renders specified titlePadding', () => { 80 - prompts.box('message', 'title', { 81 - input, 82 - output, 83 - titlePadding: 6, 84 - width: 'auto', 85 - }); 86 - 87 - expect(output.buffer).toMatchSnapshot(); 88 - }); 89 - 90 - test('renders specified contentPadding', () => { 91 - prompts.box('message', 'title', { 92 - input, 93 - output, 94 - contentPadding: 6, 95 - width: 'auto', 96 - }); 97 - 98 - expect(output.buffer).toMatchSnapshot(); 99 - }); 100 - 101 - test('renders without guide when withGuide is false', () => { 102 - prompts.box('message', 'title', { 103 - input, 104 - output, 105 - withGuide: false, 106 - width: 'auto', 107 - }); 108 - 109 - expect(output.buffer).toMatchSnapshot(); 110 - }); 111 - 112 - test('renders without guide when global withGuide is false', () => { 113 - updateSettings({ withGuide: false }); 114 - 115 - prompts.box('message', 'title', { 116 - input, 117 - output, 118 - width: 'auto', 119 - }); 120 - 121 - expect(output.buffer).toMatchSnapshot(); 122 - }); 123 - 124 - test('renders truncated long titles', () => { 125 - prompts.box('message', 'foo'.repeat(20), { 126 - input, 127 - output, 128 - width: 0.2, 129 - }); 130 - 131 - expect(output.buffer).toMatchSnapshot(); 132 - }); 133 - 134 - test('cannot have width larger than 100%', () => { 135 - prompts.box('message', 'title', { 136 - input, 137 - output, 138 - width: 1.1, 139 - }); 140 - 141 - expect(output.buffer).toMatchSnapshot(); 142 - }); 143 - 144 - test('renders rounded corners when rounded is true', () => { 145 - prompts.box('message', 'title', { 146 - input, 147 - output, 148 - rounded: true, 149 - width: 'auto', 150 - }); 151 - 152 - expect(output.buffer).toMatchSnapshot(); 153 - }); 154 - 155 - test('renders auto width with content longer than title', () => { 156 - prompts.box('message'.repeat(4), 'title', { 157 - input, 158 - output, 159 - width: 'auto', 160 - }); 161 - 162 - expect(output.buffer).toMatchSnapshot(); 163 - }); 164 - 165 - test('renders auto width with title longer than content', () => { 166 - prompts.box('message', 'title'.repeat(4), { 167 - input, 168 - output, 169 - width: 'auto', 170 - }); 171 - 172 - expect(output.buffer).toMatchSnapshot(); 173 - }); 174 - 175 - test('renders left aligned title', () => { 176 - prompts.box('message', 'title', { 177 - input, 178 - output, 179 - titleAlign: 'left', 180 - width: 'auto', 181 - }); 182 - 183 - expect(output.buffer).toMatchSnapshot(); 184 - }); 185 - 186 - test('renders right aligned title', () => { 187 - prompts.box('message', 'title', { 188 - input, 189 - output, 190 - titleAlign: 'right', 191 - width: 'auto', 192 - }); 193 - 194 - expect(output.buffer).toMatchSnapshot(); 195 - }); 196 - 197 - test('renders center aligned title', () => { 198 - prompts.box('message', 'title', { 199 - input, 200 - output, 201 - titleAlign: 'center', 202 - width: 'auto', 203 - }); 204 - 205 - expect(output.buffer).toMatchSnapshot(); 206 - }); 207 - 208 - test('renders left aligned content', () => { 209 - prompts.box('message', 'title', { 210 - input, 211 - output, 212 - contentAlign: 'left', 213 - width: 'auto', 214 - }); 215 - 216 - expect(output.buffer).toMatchSnapshot(); 217 - }); 218 - 219 - test('renders right aligned content', () => { 220 - prompts.box('message', 'title', { 221 - input, 222 - output, 223 - contentAlign: 'right', 224 - width: 'auto', 225 - }); 226 - 227 - expect(output.buffer).toMatchSnapshot(); 228 - }); 229 - 230 - test('renders center aligned content', () => { 231 - prompts.box('message', 'title', { 232 - input, 233 - output, 234 - contentAlign: 'center', 235 - width: 'auto', 236 - }); 237 - 238 - expect(output.buffer).toMatchSnapshot(); 239 - }); 240 - 241 - test('renders with formatBorder formatting', () => { 242 - prompts.box('message', 'title', { 243 - input, 244 - output, 245 - width: 'auto', 246 - formatBorder: (text: string) => styleText('red', text), 247 - }); 248 - 249 - expect(output.buffer).toMatchSnapshot(); 250 - }); 251 - 252 - test('renders wide characters with auto width', () => { 253 - const messages = ['이게 첫 번째 줄이에요', 'これは次の行です']; 254 - prompts.box(messages.join('\n'), '这是标题', { 255 - input, 256 - output, 257 - width: 'auto', 258 - }); 259 - 260 - expect(output.buffer).toMatchSnapshot(); 261 - }); 262 - 263 - test('renders wide characters with specified width', () => { 264 - const messages = ['이게 첫 번째 줄이에요', 'これは次の行です']; 265 - prompts.box(messages.join('\n'), '这是标题', { 266 - input, 267 - output, 268 - width: 0.2, 269 - }); 270 - 271 - expect(output.buffer).toMatchSnapshot(); 272 - }); 273 - });
-216
packages/prompts/test/confirm.test.ts
··· 1 - import { updateSettings } from '@clack/core'; 2 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 3 - import * as prompts from '../src/index.js'; 4 - import { MockReadable, MockWritable } from './test-utils.js'; 5 - 6 - describe.each(['true', 'false'])('confirm (isCI = %s)', (isCI) => { 7 - let originalCI: string | undefined; 8 - let output: MockWritable; 9 - let input: MockReadable; 10 - 11 - beforeAll(() => { 12 - originalCI = process.env.CI; 13 - process.env.CI = isCI; 14 - }); 15 - 16 - afterAll(() => { 17 - process.env.CI = originalCI; 18 - }); 19 - 20 - beforeEach(() => { 21 - output = new MockWritable(); 22 - input = new MockReadable(); 23 - }); 24 - 25 - afterEach(() => { 26 - vi.restoreAllMocks(); 27 - updateSettings({ withGuide: true }); 28 - }); 29 - 30 - test('renders message with choices', async () => { 31 - const result = prompts.confirm({ 32 - message: 'foo', 33 - input, 34 - output, 35 - }); 36 - 37 - input.emit('keypress', '', { name: 'return' }); 38 - 39 - const value = await result; 40 - 41 - expect(value).toBe(true); 42 - expect(output.buffer).toMatchSnapshot(); 43 - }); 44 - 45 - test('renders custom active choice', async () => { 46 - const result = prompts.confirm({ 47 - message: 'foo', 48 - active: 'bleep', 49 - input, 50 - output, 51 - }); 52 - 53 - input.emit('keypress', '', { name: 'return' }); 54 - 55 - const value = await result; 56 - 57 - expect(value).toBe(true); 58 - expect(output.buffer).toMatchSnapshot(); 59 - }); 60 - 61 - test('renders custom inactive choice', async () => { 62 - const result = prompts.confirm({ 63 - message: 'foo', 64 - inactive: 'bleep', 65 - input, 66 - output, 67 - }); 68 - 69 - input.emit('keypress', '', { name: 'return' }); 70 - 71 - const value = await result; 72 - 73 - expect(value).toBe(true); 74 - expect(output.buffer).toMatchSnapshot(); 75 - }); 76 - 77 - test('renders options in vertical alignment', async () => { 78 - const result = prompts.confirm({ 79 - message: 'foo', 80 - vertical: true, 81 - input, 82 - output, 83 - }); 84 - 85 - input.emit('keypress', '', { name: 'return' }); 86 - 87 - const value = await result; 88 - 89 - expect(value).toBe(true); 90 - expect(output.buffer).toMatchSnapshot(); 91 - }); 92 - 93 - test('right arrow moves to next choice', async () => { 94 - const result = prompts.confirm({ 95 - message: 'foo', 96 - input, 97 - output, 98 - }); 99 - 100 - input.emit('keypress', 'right', { name: 'right' }); 101 - input.emit('keypress', '', { name: 'return' }); 102 - 103 - const value = await result; 104 - 105 - expect(value).toBe(false); 106 - expect(output.buffer).toMatchSnapshot(); 107 - }); 108 - 109 - test('left arrow moves to previous choice', async () => { 110 - const result = prompts.confirm({ 111 - message: 'foo', 112 - input, 113 - output, 114 - }); 115 - 116 - input.emit('keypress', 'right', { name: 'right' }); 117 - input.emit('keypress', 'left', { name: 'left' }); 118 - input.emit('keypress', '', { name: 'return' }); 119 - 120 - const value = await result; 121 - 122 - expect(value).toBe(true); 123 - expect(output.buffer).toMatchSnapshot(); 124 - }); 125 - 126 - test('can cancel', async () => { 127 - const result = prompts.confirm({ 128 - message: 'foo', 129 - input, 130 - output, 131 - }); 132 - 133 - input.emit('keypress', 'escape', { name: 'escape' }); 134 - 135 - const value = await result; 136 - 137 - expect(prompts.isCancel(value)).toBe(true); 138 - expect(output.buffer).toMatchSnapshot(); 139 - }); 140 - 141 - test('can set initialValue', async () => { 142 - const result = prompts.confirm({ 143 - message: 'foo', 144 - initialValue: false, 145 - input, 146 - output, 147 - }); 148 - 149 - input.emit('keypress', '', { name: 'return' }); 150 - 151 - const value = await result; 152 - 153 - expect(value).toBe(false); 154 - expect(output.buffer).toMatchSnapshot(); 155 - }); 156 - 157 - test('can be aborted by a signal', async () => { 158 - const controller = new AbortController(); 159 - const result = prompts.confirm({ 160 - message: 'yes?', 161 - input, 162 - output, 163 - signal: controller.signal, 164 - }); 165 - 166 - controller.abort(); 167 - const value = await result; 168 - expect(prompts.isCancel(value)).toBe(true); 169 - expect(output.buffer).toMatchSnapshot(); 170 - }); 171 - 172 - test('withGuide: false removes guide', async () => { 173 - const result = prompts.confirm({ 174 - message: 'foo', 175 - withGuide: false, 176 - input, 177 - output, 178 - }); 179 - 180 - input.emit('keypress', '', { name: 'return' }); 181 - 182 - await result; 183 - 184 - expect(output.buffer).toMatchSnapshot(); 185 - }); 186 - 187 - test('global withGuide: false removes guide', async () => { 188 - updateSettings({ withGuide: false }); 189 - 190 - const result = prompts.confirm({ 191 - message: 'foo', 192 - input, 193 - output, 194 - }); 195 - 196 - input.emit('keypress', '', { name: 'return' }); 197 - 198 - await result; 199 - 200 - expect(output.buffer).toMatchSnapshot(); 201 - }); 202 - 203 - test('renders multi-line messages correctly', async () => { 204 - const result = prompts.confirm({ 205 - message: 'foo\nbar\nbaz', 206 - input, 207 - output, 208 - }); 209 - 210 - input.emit('keypress', '', { name: 'return' }); 211 - 212 - await result; 213 - 214 - expect(output.buffer).toMatchSnapshot(); 215 - }); 216 - });
+38 -51
packages/prompts/test/date.test.ts packages/prompts/src/date.test.ts
··· 1 1 import { updateSettings } from '@clack/core'; 2 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 3 - import * as prompts from '../src/index.js'; 4 - import { MockReadable, MockWritable } from './test-utils.js'; 2 + import { afterEach, beforeEach, describe, expect, test } from 'vitest'; 3 + import * as prompts from './index.js'; 4 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 5 5 6 6 const d = (iso: string) => { 7 7 const [y, m, day] = iso.slice(0, 10).split('-').map(Number); ··· 9 9 }; 10 10 11 11 describe.each(['true', 'false'])('date (isCI = %s)', (isCI) => { 12 - let originalCI: string | undefined; 13 - let output: MockWritable; 14 - let input: MockReadable; 15 - 16 - beforeAll(() => { 17 - originalCI = process.env.CI; 18 - process.env.CI = isCI; 19 - }); 20 - 21 - afterAll(() => { 22 - process.env.CI = originalCI; 23 - }); 12 + let mocks: Mocks<{ input: true; output: true }>; 24 13 25 14 beforeEach(() => { 26 - output = new MockWritable(); 27 - input = new MockReadable(); 15 + mocks = createMocks({ input: true, output: true, env: { CI: isCI } }); 28 16 }); 29 17 30 18 afterEach(() => { 31 - vi.restoreAllMocks(); 32 19 updateSettings({ withGuide: true }); 33 20 }); 34 21 ··· 37 24 message: 'Pick a date', 38 25 locale: 'en-US', 39 26 initialValue: d('2025-01-15'), 40 - input, 41 - output, 27 + input: mocks.input, 28 + output: mocks.output, 42 29 }); 43 30 44 - input.emit('keypress', undefined, { name: 'return' }); 31 + mocks.input.emit('keypress', undefined, { name: 'return' }); 45 32 46 33 await result; 47 34 48 - expect(output.buffer).toMatchSnapshot(); 35 + expect(mocks.output.buffer).toMatchSnapshot(); 49 36 }); 50 37 51 38 test('renders initial value', async () => { ··· 53 40 message: 'Pick a date', 54 41 locale: 'en-US', 55 42 initialValue: d('2025-01-15'), 56 - input, 57 - output, 43 + input: mocks.input, 44 + output: mocks.output, 58 45 }); 59 46 60 - input.emit('keypress', undefined, { name: 'return' }); 47 + mocks.input.emit('keypress', undefined, { name: 'return' }); 61 48 62 49 const value = await result; 63 50 64 51 expect(value).toBeInstanceOf(Date); 65 52 expect((value as Date).toISOString().slice(0, 10)).toBe('2025-01-15'); 66 - expect(output.buffer).toMatchSnapshot(); 53 + expect(mocks.output.buffer).toMatchSnapshot(); 67 54 }); 68 55 69 56 test('can cancel', async () => { 70 57 const result = prompts.date({ 71 58 message: 'Pick a date', 72 59 locale: 'en-US', 73 - input, 74 - output, 60 + input: mocks.input, 61 + output: mocks.output, 75 62 }); 76 63 77 - input.emit('keypress', 'escape', { name: 'escape' }); 64 + mocks.input.emit('keypress', 'escape', { name: 'escape' }); 78 65 79 66 const value = await result; 80 67 81 68 expect(prompts.isCancel(value)).toBe(true); 82 - expect(output.buffer).toMatchSnapshot(); 69 + expect(mocks.output.buffer).toMatchSnapshot(); 83 70 }); 84 71 85 72 test('renders submitted value', async () => { ··· 87 74 message: 'Pick a date', 88 75 locale: 'en-US', 89 76 initialValue: d('2025-06-15'), 90 - input, 91 - output, 77 + input: mocks.input, 78 + output: mocks.output, 92 79 }); 93 80 94 - input.emit('keypress', undefined, { name: 'return' }); 81 + mocks.input.emit('keypress', undefined, { name: 'return' }); 95 82 96 83 const value = await result; 97 84 98 85 expect(value).toBeInstanceOf(Date); 99 86 expect((value as Date).toISOString().slice(0, 10)).toBe('2025-06-15'); 100 - expect(output.buffer).toMatchSnapshot(); 87 + expect(mocks.output.buffer).toMatchSnapshot(); 101 88 }); 102 89 103 90 test('defaultValue used when empty submit', async () => { ··· 105 92 message: 'Pick a date', 106 93 locale: 'en-US', 107 94 defaultValue: d('2025-12-25'), 108 - input, 109 - output, 95 + input: mocks.input, 96 + output: mocks.output, 110 97 }); 111 98 112 - input.emit('keypress', undefined, { name: 'return' }); 99 + mocks.input.emit('keypress', undefined, { name: 'return' }); 113 100 114 101 const value = await result; 115 102 116 103 expect(value).toBeInstanceOf(Date); 117 104 expect((value as Date).toISOString().slice(0, 10)).toBe('2025-12-25'); 118 - expect(output.buffer).toMatchSnapshot(); 105 + expect(mocks.output.buffer).toMatchSnapshot(); 119 106 }); 120 107 121 108 test('withGuide: false removes guide', async () => { ··· 124 111 locale: 'en-US', 125 112 withGuide: false, 126 113 initialValue: d('2025-01-15'), 127 - input, 128 - output, 114 + input: mocks.input, 115 + output: mocks.output, 129 116 }); 130 117 131 - input.emit('keypress', undefined, { name: 'return' }); 118 + mocks.input.emit('keypress', undefined, { name: 'return' }); 132 119 133 120 await result; 134 121 135 - expect(output.buffer).toMatchSnapshot(); 122 + expect(mocks.output.buffer).toMatchSnapshot(); 136 123 }); 137 124 138 125 test('supports MDY format', async () => { ··· 140 127 message: 'Pick a date', 141 128 format: 'MDY', 142 129 initialValue: d('2025-01-15'), 143 - input, 144 - output, 130 + input: mocks.input, 131 + output: mocks.output, 145 132 }); 146 133 147 - input.emit('keypress', undefined, { name: 'return' }); 134 + mocks.input.emit('keypress', undefined, { name: 'return' }); 148 135 149 136 const value = await result; 150 137 151 138 expect(value).toBeInstanceOf(Date); 152 139 expect((value as Date).toISOString().slice(0, 10)).toBe('2025-01-15'); 153 - expect(output.buffer).toMatchSnapshot(); 140 + expect(mocks.output.buffer).toMatchSnapshot(); 154 141 }); 155 142 156 143 test('minDate shows error when date before min and submit', async () => { ··· 159 146 locale: 'en-US', 160 147 initialValue: d('2025-01-10'), 161 148 minDate: d('2025-01-15'), 162 - input, 163 - output, 149 + input: mocks.input, 150 + output: mocks.output, 164 151 }); 165 152 166 - input.emit('keypress', undefined, { name: 'return' }); 153 + mocks.input.emit('keypress', undefined, { name: 'return' }); 167 154 await new Promise((r) => setImmediate(r)); 168 155 169 - const hasError = output.buffer.some( 156 + const hasError = mocks.output.buffer.some( 170 157 (s) => typeof s === 'string' && s.includes('Date must be on or after') 171 158 ); 172 159 expect(hasError).toBe(true); 173 160 174 - input.emit('keypress', 'escape', { name: 'escape' }); 161 + mocks.input.emit('keypress', 'escape', { name: 'escape' }); 175 162 const value = await result; 176 163 expect(prompts.isCancel(value)).toBe(true); 177 164 });
-414
packages/prompts/test/group-multi-select.test.ts
··· 1 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 2 - import * as prompts from '../src/index.js'; 3 - import { MockReadable, MockWritable } from './test-utils.js'; 4 - 5 - describe.each(['true', 'false'])('groupMultiselect (isCI = %s)', (isCI) => { 6 - let originalCI: string | undefined; 7 - let output: MockWritable; 8 - let input: MockReadable; 9 - 10 - beforeAll(() => { 11 - originalCI = process.env.CI; 12 - process.env.CI = isCI; 13 - }); 14 - 15 - afterAll(() => { 16 - process.env.CI = originalCI; 17 - }); 18 - 19 - beforeEach(() => { 20 - output = new MockWritable(); 21 - input = new MockReadable(); 22 - }); 23 - 24 - afterEach(() => { 25 - vi.restoreAllMocks(); 26 - prompts.updateSettings({ withGuide: true }); 27 - }); 28 - 29 - test('renders message with options', async () => { 30 - const result = prompts.groupMultiselect({ 31 - message: 'foo', 32 - input, 33 - output, 34 - options: { 35 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 36 - group2: [{ value: 'group2value0' }], 37 - }, 38 - }); 39 - 40 - // Select the first non-group option 41 - input.emit('keypress', '', { name: 'down' }); 42 - input.emit('keypress', '', { name: 'space' }); 43 - 44 - // submit 45 - input.emit('keypress', '', { name: 'return' }); 46 - 47 - const value = await result; 48 - 49 - expect(value).toEqual(['group1value0']); 50 - expect(output.buffer).toMatchSnapshot(); 51 - }); 52 - 53 - test('can select multiple options', async () => { 54 - const result = prompts.groupMultiselect({ 55 - message: 'foo', 56 - input, 57 - output, 58 - options: { 59 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }, { value: 'group1value2' }], 60 - }, 61 - }); 62 - 63 - // Select the first non-group option 64 - input.emit('keypress', '', { name: 'down' }); 65 - input.emit('keypress', '', { name: 'space' }); 66 - // Select the second non-group option 67 - input.emit('keypress', '', { name: 'down' }); 68 - input.emit('keypress', '', { name: 'space' }); 69 - 70 - // submit 71 - input.emit('keypress', '', { name: 'return' }); 72 - 73 - const value = await result; 74 - 75 - expect(value).toEqual(['group1value0', 'group1value1']); 76 - expect(output.buffer).toMatchSnapshot(); 77 - }); 78 - 79 - test('can select a group', async () => { 80 - const result = prompts.groupMultiselect({ 81 - message: 'foo', 82 - input, 83 - output, 84 - options: { 85 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 86 - }, 87 - }); 88 - 89 - // Select the group as a whole 90 - input.emit('keypress', '', { name: 'space' }); 91 - 92 - // submit 93 - input.emit('keypress', '', { name: 'return' }); 94 - 95 - const value = await result; 96 - 97 - expect(value).toEqual(['group1value0', 'group1value1']); 98 - expect(output.buffer).toMatchSnapshot(); 99 - }); 100 - 101 - test('can select a group by selecting all members', async () => { 102 - const result = prompts.groupMultiselect({ 103 - message: 'foo', 104 - input, 105 - output, 106 - options: { 107 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 108 - }, 109 - }); 110 - 111 - // Select the first group option 112 - input.emit('keypress', '', { name: 'down' }); 113 - input.emit('keypress', '', { name: 'space' }); 114 - // Select the second group option 115 - input.emit('keypress', '', { name: 'down' }); 116 - input.emit('keypress', '', { name: 'space' }); 117 - 118 - // submit 119 - input.emit('keypress', '', { name: 'return' }); 120 - 121 - const value = await result; 122 - 123 - expect(value).toEqual(['group1value0', 'group1value1']); 124 - expect(output.buffer).toMatchSnapshot(); 125 - }); 126 - 127 - test('can deselect an option', async () => { 128 - const result = prompts.groupMultiselect({ 129 - message: 'foo', 130 - input, 131 - output, 132 - options: { 133 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 134 - }, 135 - }); 136 - 137 - // Select the first group option 138 - input.emit('keypress', '', { name: 'down' }); 139 - input.emit('keypress', '', { name: 'space' }); 140 - // Select the second group option 141 - input.emit('keypress', '', { name: 'down' }); 142 - input.emit('keypress', '', { name: 'space' }); 143 - // Deselect it 144 - input.emit('keypress', '', { name: 'space' }); 145 - 146 - // submit 147 - input.emit('keypress', '', { name: 'return' }); 148 - 149 - const value = await result; 150 - 151 - expect(value).toEqual(['group1value0']); 152 - expect(output.buffer).toMatchSnapshot(); 153 - }); 154 - 155 - test('renders error when nothing selected', async () => { 156 - const result = prompts.groupMultiselect({ 157 - message: 'foo', 158 - input, 159 - output, 160 - options: { 161 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 162 - }, 163 - }); 164 - 165 - // try submit 166 - input.emit('keypress', '', { name: 'return' }); 167 - // now select something and submit 168 - input.emit('keypress', '', { name: 'down' }); 169 - input.emit('keypress', '', { name: 'space' }); 170 - input.emit('keypress', '', { name: 'return' }); 171 - 172 - const value = await result; 173 - 174 - expect(value).toEqual(['group1value0']); 175 - expect(output.buffer).toMatchSnapshot(); 176 - }); 177 - 178 - describe('selectableGroups = false', () => { 179 - test('cannot select groups', async () => { 180 - const result = prompts.groupMultiselect({ 181 - message: 'foo', 182 - input, 183 - output, 184 - options: { 185 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 186 - }, 187 - selectableGroups: false, 188 - }); 189 - 190 - // first selectable item should be group's child 191 - input.emit('keypress', '', { name: 'space' }); 192 - input.emit('keypress', '', { name: 'return' }); 193 - 194 - const value = await result; 195 - 196 - expect(value).toEqual(['group1value0']); 197 - expect(output.buffer).toMatchSnapshot(); 198 - }); 199 - 200 - test('selecting all members of group does not select group', async () => { 201 - const result = prompts.groupMultiselect({ 202 - message: 'foo', 203 - input, 204 - output, 205 - options: { 206 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 207 - }, 208 - selectableGroups: false, 209 - }); 210 - 211 - // first selectable item should be group's child 212 - input.emit('keypress', '', { name: 'space' }); 213 - // select second item 214 - input.emit('keypress', '', { name: 'down' }); 215 - input.emit('keypress', '', { name: 'space' }); 216 - // submit 217 - input.emit('keypress', '', { name: 'return' }); 218 - 219 - const value = await result; 220 - 221 - expect(value).toEqual(['group1value0', 'group1value1']); 222 - expect(output.buffer).toMatchSnapshot(); 223 - }); 224 - }); 225 - 226 - test('can submit empty selection when require = false', async () => { 227 - const result = prompts.groupMultiselect({ 228 - message: 'foo', 229 - input, 230 - output, 231 - options: { 232 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 233 - }, 234 - required: false, 235 - }); 236 - 237 - input.emit('keypress', '', { name: 'return' }); 238 - 239 - const value = await result; 240 - 241 - expect(value).toEqual([]); 242 - expect(output.buffer).toMatchSnapshot(); 243 - }); 244 - 245 - test('cursorAt sets initial selection', async () => { 246 - const result = prompts.groupMultiselect({ 247 - message: 'foo', 248 - input, 249 - output, 250 - options: { 251 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 252 - }, 253 - cursorAt: 'group1value1', 254 - }); 255 - 256 - input.emit('keypress', '', { name: 'space' }); 257 - input.emit('keypress', '', { name: 'return' }); 258 - 259 - const value = await result; 260 - 261 - expect(value).toEqual(['group1value1']); 262 - expect(output.buffer).toMatchSnapshot(); 263 - }); 264 - 265 - test('initial values can be set', async () => { 266 - const result = prompts.groupMultiselect({ 267 - message: 'foo', 268 - input, 269 - output, 270 - options: { 271 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 272 - }, 273 - initialValues: ['group1value1'], 274 - }); 275 - 276 - input.emit('keypress', '', { name: 'return' }); 277 - 278 - const value = await result; 279 - 280 - expect(value).toEqual(['group1value1']); 281 - expect(output.buffer).toMatchSnapshot(); 282 - }); 283 - 284 - test('values can be non-primitive', async () => { 285 - const value0 = Symbol(); 286 - const value1 = Symbol(); 287 - const result = prompts.groupMultiselect({ 288 - message: 'foo', 289 - input, 290 - output, 291 - options: { 292 - group1: [ 293 - { value: value0, label: 'value0' }, 294 - { value: value1, label: 'value1' }, 295 - ], 296 - }, 297 - }); 298 - 299 - input.emit('keypress', '', { name: 'down' }); 300 - input.emit('keypress', '', { name: 'space' }); 301 - input.emit('keypress', '', { name: 'return' }); 302 - 303 - const value = await result; 304 - 305 - expect(value).toEqual([value0]); 306 - expect(output.buffer).toMatchSnapshot(); 307 - }); 308 - 309 - describe('groupSpacing', () => { 310 - test('renders spaced groups', async () => { 311 - const result = prompts.groupMultiselect({ 312 - message: 'foo', 313 - input, 314 - output, 315 - options: { 316 - group1: [{ value: 'group1value0' }], 317 - group2: [{ value: 'group2value0' }], 318 - }, 319 - groupSpacing: 2, 320 - }); 321 - 322 - input.emit('keypress', '', { name: 'down' }); 323 - input.emit('keypress', '', { name: 'space' }); 324 - input.emit('keypress', '', { name: 'return' }); 325 - 326 - await result; 327 - 328 - expect(output.buffer).toMatchSnapshot(); 329 - }); 330 - 331 - test('negative spacing is ignored', async () => { 332 - const result = prompts.groupMultiselect({ 333 - message: 'foo', 334 - input, 335 - output, 336 - options: { 337 - group1: [{ value: 'group1value0' }], 338 - group2: [{ value: 'group2value0' }], 339 - }, 340 - groupSpacing: -2, 341 - }); 342 - 343 - input.emit('keypress', '', { name: 'down' }); 344 - input.emit('keypress', '', { name: 'space' }); 345 - input.emit('keypress', '', { name: 'return' }); 346 - 347 - await result; 348 - 349 - expect(output.buffer).toMatchSnapshot(); 350 - }); 351 - }); 352 - 353 - test('can be aborted by a signal', async () => { 354 - const controller = new AbortController(); 355 - const result = prompts.groupMultiselect({ 356 - message: 'Select a fruit', 357 - options: { 358 - group1: [{ value: 'group1value0' }], 359 - group2: [{ value: 'group2value0' }], 360 - }, 361 - input, 362 - output, 363 - signal: controller.signal, 364 - }); 365 - 366 - controller.abort(); 367 - const value = await result; 368 - expect(prompts.isCancel(value)).toBe(true); 369 - expect(output.buffer).toMatchSnapshot(); 370 - }); 371 - 372 - test('withGuide: false removes guide', async () => { 373 - const result = prompts.groupMultiselect({ 374 - message: 'foo', 375 - input, 376 - output, 377 - withGuide: false, 378 - options: { 379 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 380 - }, 381 - }); 382 - 383 - input.emit('keypress', '', { name: 'down' }); 384 - input.emit('keypress', '', { name: 'space' }); 385 - input.emit('keypress', '', { name: 'return' }); 386 - 387 - const value = await result; 388 - 389 - expect(value).toEqual(['group1value0']); 390 - expect(output.buffer).toMatchSnapshot(); 391 - }); 392 - 393 - test('global withGuide: false removes guide', async () => { 394 - prompts.updateSettings({ withGuide: false }); 395 - 396 - const result = prompts.groupMultiselect({ 397 - message: 'foo', 398 - input, 399 - output, 400 - options: { 401 - group1: [{ value: 'group1value0' }, { value: 'group1value1' }], 402 - }, 403 - }); 404 - 405 - input.emit('keypress', '', { name: 'down' }); 406 - input.emit('keypress', '', { name: 'space' }); 407 - input.emit('keypress', '', { name: 'return' }); 408 - 409 - const value = await result; 410 - 411 - expect(value).toEqual(['group1value0']); 412 - expect(output.buffer).toMatchSnapshot(); 413 - }); 414 - });
+12 -12
packages/prompts/test/limit-options.test.ts packages/prompts/src/limit-options.test.ts
··· 1 1 import { styleText } from 'node:util'; 2 2 import { beforeEach, describe, expect, test } from 'vitest'; 3 - import { type LimitOptionsParams, limitOptions } from '../src/index.js'; 4 - import { MockWritable } from './test-utils.js'; 3 + import { type LimitOptionsParams, limitOptions } from './index.js'; 4 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 5 5 6 6 describe('limitOptions', () => { 7 - let output: MockWritable; 7 + let mocks: Mocks<{ output: true }>; 8 8 let options: LimitOptionsParams<{ value: string }>; 9 9 10 10 beforeEach(() => { 11 - output = new MockWritable(); 11 + mocks = createMocks({ output: true }); 12 12 options = { 13 - output, 13 + output: mocks.output, 14 14 options: [], 15 15 maxItems: undefined, 16 16 cursor: 0, ··· 55 55 { value: 'Item 9' }, 56 56 { value: 'Item 10' }, 57 57 ]; 58 - output.rows = 20; 58 + mocks.output.rows = 20; 59 59 options.maxItems = 5; 60 60 options.cursor = 6; 61 61 const result = limitOptions(options); ··· 106 106 { value: 'Item 9' }, 107 107 { value: 'Item 10' }, 108 108 ]; 109 - output.rows = 7; 109 + mocks.output.rows = 7; 110 110 options.maxItems = 10; 111 111 const result = limitOptions(options); 112 112 expect(result).toEqual(['Item 1', 'Item 2', styleText('dim', '...')]); ··· 129 129 { value: 'Item 9' }, 130 130 { value: 'Item 10' }, 131 131 ]; 132 - output.rows = 14; 132 + mocks.output.rows = 14; 133 133 options.maxItems = 10; 134 134 const result = limitOptions(options); 135 135 expect(result).toEqual([ ··· 165 165 { value: 'Item 9' }, 166 166 { value: 'Item 10' }, 167 167 ]; 168 - output.rows = 14; 168 + mocks.output.rows = 14; 169 169 options.maxItems = 10; 170 170 options.cursor = 7; 171 171 const result = limitOptions(options); ··· 202 202 { value: 'Item 9' }, 203 203 { value: 'Item 10' }, 204 204 ]; 205 - output.rows = 14; 205 + mocks.output.rows = 14; 206 206 options.maxItems = 10; 207 207 options.cursor = 9; 208 208 const result = limitOptions(options); ··· 261 261 { value: 'Item 9' }, 262 262 { value: 'Item 10' }, 263 263 ]; 264 - output.rows = 12; 264 + mocks.output.rows = 12; 265 265 options.rowPadding = 6; 266 266 // Available rows for options = 12 - 6 = 6 267 267 const result = limitOptions(options); ··· 288 288 { value: 'Item 9' }, 289 289 { value: 'Item 10' }, 290 290 ]; 291 - output.rows = 12; 291 + mocks.output.rows = 12; 292 292 // Simulate a multiline message that takes 6 lines 293 293 options.rowPadding = 6; 294 294 // Move cursor to middle of list
-173
packages/prompts/test/log.test.ts
··· 1 - import { styleText } from 'node:util'; 2 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 3 - import * as prompts from '../src/index.js'; 4 - import { MockWritable } from './test-utils.js'; 5 - 6 - describe.each(['true', 'false'])('log (isCI = %s)', (isCI) => { 7 - let originalCI: string | undefined; 8 - let output: MockWritable; 9 - 10 - beforeAll(() => { 11 - originalCI = process.env.CI; 12 - process.env.CI = isCI; 13 - }); 14 - 15 - afterAll(() => { 16 - process.env.CI = originalCI; 17 - }); 18 - 19 - beforeEach(() => { 20 - output = new MockWritable(); 21 - }); 22 - 23 - afterEach(() => { 24 - vi.restoreAllMocks(); 25 - }); 26 - 27 - describe('message', () => { 28 - test('renders message', () => { 29 - prompts.log.message('message', { 30 - output, 31 - }); 32 - 33 - expect(output.buffer).toMatchSnapshot(); 34 - }); 35 - 36 - test('renders multiline message', () => { 37 - prompts.log.message('line 1\nline 2\nline 3', { 38 - output, 39 - }); 40 - 41 - expect(output.buffer).toMatchSnapshot(); 42 - }); 43 - 44 - test('renders message from array', () => { 45 - prompts.log.message(['line 1', 'line 2', 'line 3'], { 46 - output, 47 - }); 48 - 49 - expect(output.buffer).toMatchSnapshot(); 50 - }); 51 - 52 - test('renders message with custom symbols and spacing', () => { 53 - prompts.log.message('custom\nsymbols', { 54 - symbol: styleText('red', '>>'), 55 - secondarySymbol: styleText('yellow', '--'), 56 - output, 57 - }); 58 - 59 - expect(output.buffer).toMatchSnapshot(); 60 - }); 61 - 62 - test('renders message with guide disabled', () => { 63 - prompts.log.message('standalone message', { 64 - withGuide: false, 65 - output, 66 - }); 67 - 68 - expect(output.buffer).toMatchSnapshot(); 69 - }); 70 - 71 - test('renders multiline message with guide disabled', () => { 72 - prompts.log.message('line 1\nline 2\nline 3', { 73 - withGuide: false, 74 - output, 75 - }); 76 - 77 - expect(output.buffer).toMatchSnapshot(); 78 - }); 79 - 80 - test('renders message with custom spacing', () => { 81 - prompts.log.message('spaced message', { 82 - spacing: 3, 83 - output, 84 - }); 85 - 86 - expect(output.buffer).toMatchSnapshot(); 87 - }); 88 - 89 - test('renders empty message correctly', () => { 90 - prompts.log.message('', { 91 - output, 92 - }); 93 - 94 - expect(output.buffer).toMatchSnapshot(); 95 - }); 96 - 97 - test('renders empty message with guide disabled', () => { 98 - prompts.log.message('', { 99 - withGuide: false, 100 - output, 101 - }); 102 - 103 - expect(output.buffer).toMatchSnapshot(); 104 - }); 105 - 106 - test('renders empty lines correctly', () => { 107 - prompts.log.message('foo\n\nbar', { 108 - output, 109 - }); 110 - 111 - expect(output.buffer).toMatchSnapshot(); 112 - }); 113 - 114 - test('renders empty lines with guide disabled', () => { 115 - prompts.log.message('foo\n\nbar', { 116 - withGuide: false, 117 - output, 118 - }); 119 - 120 - expect(output.buffer).toMatchSnapshot(); 121 - }); 122 - }); 123 - 124 - describe('info', () => { 125 - test('renders info message', () => { 126 - prompts.log.info('info message', { 127 - output, 128 - }); 129 - 130 - expect(output.buffer).toMatchSnapshot(); 131 - }); 132 - }); 133 - 134 - describe('success', () => { 135 - test('renders success message', () => { 136 - prompts.log.success('success message', { 137 - output, 138 - }); 139 - 140 - expect(output.buffer).toMatchSnapshot(); 141 - }); 142 - }); 143 - 144 - describe('step', () => { 145 - test('renders step message', () => { 146 - prompts.log.step('step message', { 147 - output, 148 - }); 149 - 150 - expect(output.buffer).toMatchSnapshot(); 151 - }); 152 - }); 153 - 154 - describe('warn', () => { 155 - test('renders warn message', () => { 156 - prompts.log.warn('warn message', { 157 - output, 158 - }); 159 - 160 - expect(output.buffer).toMatchSnapshot(); 161 - }); 162 - }); 163 - 164 - describe('error', () => { 165 - test('renders error message', () => { 166 - prompts.log.error('error message', { 167 - output, 168 - }); 169 - 170 - expect(output.buffer).toMatchSnapshot(); 171 - }); 172 - }); 173 - });
-272
packages/prompts/test/multi-line.test.ts
··· 1 - import { updateSettings } from '@clack/core'; 2 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 3 - import * as prompts from '../src/index.js'; 4 - import { MockReadable, MockWritable } from './test-utils.js'; 5 - 6 - describe.each(['true', 'false'])('multiline (isCI = %s)', (isCI) => { 7 - let originalCI: string | undefined; 8 - let output: MockWritable; 9 - let input: MockReadable; 10 - 11 - beforeAll(() => { 12 - originalCI = process.env.CI; 13 - process.env.CI = isCI; 14 - }); 15 - 16 - afterAll(() => { 17 - process.env.CI = originalCI; 18 - }); 19 - 20 - beforeEach(() => { 21 - output = new MockWritable(); 22 - input = new MockReadable(); 23 - }); 24 - 25 - afterEach(() => { 26 - vi.restoreAllMocks(); 27 - updateSettings({ withGuide: true }); 28 - }); 29 - 30 - test('renders message', async () => { 31 - const result = prompts.multiline({ 32 - message: 'foo', 33 - input, 34 - output, 35 - }); 36 - 37 - input.emit('keypress', '', { name: 'return' }); 38 - input.emit('keypress', '', { name: 'return' }); 39 - 40 - await result; 41 - 42 - expect(output.buffer).toMatchSnapshot(); 43 - }); 44 - 45 - test('renders placeholder if set', async () => { 46 - const result = prompts.multiline({ 47 - message: 'foo', 48 - placeholder: 'bar', 49 - input, 50 - output, 51 - }); 52 - 53 - input.emit('keypress', '', { name: 'return' }); 54 - input.emit('keypress', '', { name: 'return' }); 55 - 56 - const value = await result; 57 - 58 - expect(output.buffer).toMatchSnapshot(); 59 - expect(value).toBe(''); 60 - }); 61 - 62 - test('can cancel', async () => { 63 - const result = prompts.multiline({ 64 - message: 'foo', 65 - input, 66 - output, 67 - }); 68 - 69 - input.emit('keypress', 'escape', { name: 'escape' }); 70 - 71 - const value = await result; 72 - 73 - expect(prompts.isCancel(value)).toBe(true); 74 - expect(output.buffer).toMatchSnapshot(); 75 - }); 76 - 77 - test('renders cancelled value if one set', async () => { 78 - const result = prompts.multiline({ 79 - message: 'foo', 80 - input, 81 - output, 82 - }); 83 - 84 - input.emit('keypress', 'x', { name: 'x' }); 85 - input.emit('keypress', 'y', { name: 'y' }); 86 - input.emit('keypress', '', { name: 'escape' }); 87 - 88 - const value = await result; 89 - 90 - expect(prompts.isCancel(value)).toBe(true); 91 - expect(output.buffer).toMatchSnapshot(); 92 - }); 93 - 94 - test('renders submitted value', async () => { 95 - const result = prompts.multiline({ 96 - message: 'foo', 97 - input, 98 - output, 99 - }); 100 - 101 - input.emit('keypress', 'x', { name: 'x' }); 102 - input.emit('keypress', 'y', { name: 'y' }); 103 - input.emit('keypress', '', { name: 'return' }); 104 - input.emit('keypress', '', { name: 'return' }); 105 - 106 - const value = await result; 107 - 108 - expect(value).toBe('xy'); 109 - expect(output.buffer).toMatchSnapshot(); 110 - }); 111 - 112 - test('defaultValue sets the value but does not render', async () => { 113 - const result = prompts.multiline({ 114 - message: 'foo', 115 - defaultValue: 'bar', 116 - input, 117 - output, 118 - }); 119 - 120 - input.emit('keypress', '', { name: 'return' }); 121 - input.emit('keypress', '', { name: 'return' }); 122 - 123 - const value = await result; 124 - 125 - expect(value).toBe('bar'); 126 - expect(output.buffer).toMatchSnapshot(); 127 - }); 128 - 129 - test('validation errors render and clear', async () => { 130 - const result = prompts.multiline({ 131 - message: 'foo', 132 - validate: (val) => (val !== 'xy' ? 'should be xy' : undefined), 133 - input, 134 - output, 135 - }); 136 - 137 - input.emit('keypress', 'x', { name: 'x' }); 138 - input.emit('keypress', '', { name: 'return' }); 139 - input.emit('keypress', '', { name: 'return' }); 140 - input.emit('keypress', 'y', { name: 'y' }); 141 - input.emit('keypress', '', { name: 'return' }); 142 - input.emit('keypress', '', { name: 'return' }); 143 - 144 - const value = await result; 145 - 146 - expect(value).toBe('xy'); 147 - expect(output.buffer).toMatchSnapshot(); 148 - }); 149 - 150 - test('validation errors render and clear (using Error)', async () => { 151 - const result = prompts.multiline({ 152 - message: 'foo', 153 - validate: (val) => (val !== 'xy' ? new Error('should be xy') : undefined), 154 - input, 155 - output, 156 - }); 157 - 158 - input.emit('keypress', 'x', { name: 'x' }); 159 - input.emit('keypress', '', { name: 'return' }); 160 - input.emit('keypress', '', { name: 'return' }); 161 - input.emit('keypress', 'y', { name: 'y' }); 162 - input.emit('keypress', '', { name: 'return' }); 163 - input.emit('keypress', '', { name: 'return' }); 164 - 165 - const value = await result; 166 - 167 - expect(value).toBe('xy'); 168 - expect(output.buffer).toMatchSnapshot(); 169 - }); 170 - 171 - test('placeholder is not used as value when pressing enter', async () => { 172 - const result = prompts.multiline({ 173 - message: 'foo', 174 - placeholder: ' (submit to use default)', 175 - defaultValue: 'default-value', 176 - input, 177 - output, 178 - }); 179 - 180 - input.emit('keypress', '', { name: 'return' }); 181 - input.emit('keypress', '', { name: 'return' }); 182 - 183 - const value = await result; 184 - 185 - expect(value).toBe('default-value'); 186 - expect(output.buffer).toMatchSnapshot(); 187 - }); 188 - 189 - test('empty string when no value and no default', async () => { 190 - const result = prompts.multiline({ 191 - message: 'foo', 192 - placeholder: ' (submit to use default)', 193 - input, 194 - output, 195 - }); 196 - 197 - input.emit('keypress', '', { name: 'return' }); 198 - input.emit('keypress', '', { name: 'return' }); 199 - 200 - const value = await result; 201 - 202 - expect(value).toBe(''); 203 - expect(output.buffer).toMatchSnapshot(); 204 - }); 205 - 206 - test('can be aborted by a signal', async () => { 207 - const controller = new AbortController(); 208 - const result = prompts.multiline({ 209 - message: 'foo', 210 - input, 211 - output, 212 - signal: controller.signal, 213 - }); 214 - 215 - controller.abort(); 216 - const value = await result; 217 - expect(prompts.isCancel(value)).toBe(true); 218 - expect(output.buffer).toMatchSnapshot(); 219 - }); 220 - 221 - test('withGuide: false removes guide', async () => { 222 - const result = prompts.multiline({ 223 - message: 'foo', 224 - withGuide: false, 225 - input, 226 - output, 227 - }); 228 - 229 - input.emit('keypress', '', { name: 'return' }); 230 - input.emit('keypress', '', { name: 'return' }); 231 - 232 - await result; 233 - 234 - expect(output.buffer).toMatchSnapshot(); 235 - }); 236 - 237 - test('global withGuide: false removes guide', async () => { 238 - updateSettings({ withGuide: false }); 239 - 240 - const result = prompts.multiline({ 241 - message: 'foo', 242 - input, 243 - output, 244 - }); 245 - 246 - input.emit('keypress', '', { name: 'return' }); 247 - input.emit('keypress', '', { name: 'return' }); 248 - 249 - await result; 250 - 251 - expect(output.buffer).toMatchSnapshot(); 252 - }); 253 - 254 - test('renders submit button', async () => { 255 - const result = prompts.multiline({ 256 - message: 'foo', 257 - input, 258 - output, 259 - showSubmit: true, 260 - }); 261 - 262 - input.emit('keypress', 'x', { name: 'x' }); 263 - input.emit('keypress', 'y', { name: 'y' }); 264 - input.emit('keypress', '\t', { name: 'tab' }); 265 - input.emit('keypress', '', { name: 'return' }); 266 - 267 - const value = await result; 268 - 269 - expect(value).toBe('xy'); 270 - expect(output.buffer).toMatchSnapshot(); 271 - }); 272 - });
-440
packages/prompts/test/multi-select.test.ts
··· 1 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 2 - import * as prompts from '../src/index.js'; 3 - import { MockReadable, MockWritable } from './test-utils.js'; 4 - 5 - describe.each(['true', 'false'])('multiselect (isCI = %s)', (isCI) => { 6 - let originalCI: string | undefined; 7 - let output: MockWritable; 8 - let input: MockReadable; 9 - 10 - beforeAll(() => { 11 - originalCI = process.env.CI; 12 - process.env.CI = isCI; 13 - }); 14 - 15 - afterAll(() => { 16 - process.env.CI = originalCI; 17 - }); 18 - 19 - beforeEach(() => { 20 - output = new MockWritable(); 21 - input = new MockReadable(); 22 - }); 23 - 24 - afterEach(() => { 25 - vi.restoreAllMocks(); 26 - prompts.updateSettings({ withGuide: true }); 27 - }); 28 - 29 - test('renders message', async () => { 30 - const result = prompts.multiselect({ 31 - message: 'foo', 32 - options: [{ value: 'opt0' }, { value: 'opt1' }], 33 - input, 34 - output, 35 - }); 36 - 37 - input.emit('keypress', '', { name: 'space' }); 38 - input.emit('keypress', '', { name: 'return' }); 39 - 40 - const value = await result; 41 - 42 - expect(value).toEqual(['opt0']); 43 - expect(output.buffer).toMatchSnapshot(); 44 - }); 45 - 46 - test('renders multiple selected options', async () => { 47 - const result = prompts.multiselect({ 48 - message: 'foo', 49 - options: [{ value: 'opt0' }, { value: 'opt1' }, { value: 'opt2' }], 50 - input, 51 - output, 52 - }); 53 - 54 - input.emit('keypress', '', { name: 'space' }); 55 - input.emit('keypress', '', { name: 'down' }); 56 - input.emit('keypress', '', { name: 'space' }); 57 - input.emit('keypress', '', { name: 'down' }); 58 - input.emit('keypress', '', { name: 'return' }); 59 - 60 - const value = await result; 61 - 62 - expect(value).toEqual(['opt0', 'opt1']); 63 - expect(output.buffer).toMatchSnapshot(); 64 - }); 65 - 66 - test('can cancel', async () => { 67 - const result = prompts.multiselect({ 68 - message: 'foo', 69 - options: [{ value: 'opt0' }, { value: 'opt1' }], 70 - input, 71 - output, 72 - }); 73 - 74 - input.emit('keypress', 'escape', { name: 'escape' }); 75 - 76 - const value = await result; 77 - 78 - expect(prompts.isCancel(value)).toBe(true); 79 - expect(output.buffer).toMatchSnapshot(); 80 - }); 81 - 82 - test('renders validation errors', async () => { 83 - const result = prompts.multiselect({ 84 - message: 'foo', 85 - options: [{ value: 'opt0' }, { value: 'opt1' }], 86 - input, 87 - output, 88 - }); 89 - 90 - // try submit with nothing selected 91 - input.emit('keypress', '', { name: 'return' }); 92 - // select and submit 93 - input.emit('keypress', '', { name: 'space' }); 94 - input.emit('keypress', '', { name: 'return' }); 95 - 96 - const value = await result; 97 - 98 - expect(value).toEqual(['opt0']); 99 - expect(output.buffer).toMatchSnapshot(); 100 - }); 101 - 102 - test('can submit without selection when required = false', async () => { 103 - const result = prompts.multiselect({ 104 - message: 'foo', 105 - options: [{ value: 'opt0' }, { value: 'opt1' }], 106 - required: false, 107 - input, 108 - output, 109 - }); 110 - 111 - input.emit('keypress', '', { name: 'return' }); 112 - 113 - const value = await result; 114 - 115 - expect(value).toEqual([]); 116 - expect(output.buffer).toMatchSnapshot(); 117 - }); 118 - 119 - test('can set cursorAt to preselect an option', async () => { 120 - const result = prompts.multiselect({ 121 - message: 'foo', 122 - options: [{ value: 'opt0' }, { value: 'opt1' }], 123 - cursorAt: 'opt1', 124 - input, 125 - output, 126 - }); 127 - 128 - input.emit('keypress', '', { name: 'space' }); 129 - input.emit('keypress', '', { name: 'return' }); 130 - 131 - const value = await result; 132 - 133 - expect(value).toEqual(['opt1']); 134 - expect(output.buffer).toMatchSnapshot(); 135 - }); 136 - 137 - test('can set initial values', async () => { 138 - const result = prompts.multiselect({ 139 - message: 'foo', 140 - options: [{ value: 'opt0' }, { value: 'opt1' }], 141 - initialValues: ['opt1'], 142 - input, 143 - output, 144 - }); 145 - 146 - input.emit('keypress', '', { name: 'return' }); 147 - 148 - const value = await result; 149 - 150 - expect(value).toEqual(['opt1']); 151 - expect(output.buffer).toMatchSnapshot(); 152 - }); 153 - 154 - test('maxItems renders a sliding window', async () => { 155 - const result = prompts.multiselect({ 156 - message: 'foo', 157 - options: [...Array(12).keys()].map((k) => ({ 158 - value: `opt${k}`, 159 - })), 160 - maxItems: 6, 161 - input, 162 - output, 163 - }); 164 - 165 - for (let i = 0; i < 6; i++) { 166 - input.emit('keypress', '', { name: 'down' }); 167 - } 168 - input.emit('keypress', '', { name: 'space' }); 169 - input.emit('keypress', '', { name: 'return' }); 170 - 171 - const value = await result; 172 - 173 - expect(value).toEqual(['opt6']); 174 - expect(output.buffer).toMatchSnapshot(); 175 - }); 176 - 177 - test('sliding window loops upwards', async () => { 178 - const result = prompts.multiselect({ 179 - message: 'foo', 180 - options: [...Array(12).keys()].map((k) => ({ 181 - value: `opt${k}`, 182 - })), 183 - maxItems: 6, 184 - input, 185 - output, 186 - }); 187 - 188 - input.emit('keypress', '', { name: 'up' }); 189 - input.emit('keypress', '', { name: 'space' }); 190 - input.emit('keypress', '', { name: 'return' }); 191 - 192 - const value = await result; 193 - 194 - expect(value).toEqual(['opt11']); 195 - expect(output.buffer).toMatchSnapshot(); 196 - }); 197 - 198 - test('sliding window loops downwards', async () => { 199 - const result = prompts.multiselect({ 200 - message: 'foo', 201 - options: [...Array(12).keys()].map((k) => ({ 202 - value: `opt${k}`, 203 - })), 204 - maxItems: 6, 205 - input, 206 - output, 207 - }); 208 - 209 - for (let i = 0; i < 12; i++) { 210 - input.emit('keypress', '', { name: 'down' }); 211 - } 212 - input.emit('keypress', '', { name: 'space' }); 213 - input.emit('keypress', '', { name: 'return' }); 214 - 215 - const value = await result; 216 - 217 - expect(value).toEqual(['opt0']); 218 - expect(output.buffer).toMatchSnapshot(); 219 - }); 220 - 221 - test('can set custom labels', async () => { 222 - const result = prompts.multiselect({ 223 - message: 'foo', 224 - options: [ 225 - { value: 'opt0', label: 'Option 0' }, 226 - { value: 'opt1', label: 'Option 1' }, 227 - ], 228 - input, 229 - output, 230 - }); 231 - 232 - input.emit('keypress', '', { name: 'space' }); 233 - input.emit('keypress', '', { name: 'return' }); 234 - 235 - const value = await result; 236 - 237 - expect(value).toEqual(['opt0']); 238 - expect(output.buffer).toMatchSnapshot(); 239 - }); 240 - 241 - test('can render option hints', async () => { 242 - const result = prompts.multiselect({ 243 - message: 'foo', 244 - options: [ 245 - { value: 'opt0', hint: 'Hint 0' }, 246 - { value: 'opt1', hint: 'Hint 1' }, 247 - ], 248 - input, 249 - output, 250 - }); 251 - 252 - input.emit('keypress', '', { name: 'space' }); 253 - input.emit('keypress', '', { name: 'return' }); 254 - 255 - const value = await result; 256 - 257 - expect(value).toEqual(['opt0']); 258 - expect(output.buffer).toMatchSnapshot(); 259 - }); 260 - 261 - test('shows hints for all selected options', async () => { 262 - const result = prompts.multiselect({ 263 - message: 'foo', 264 - options: [ 265 - { value: 'opt0', hint: 'Hint 0' }, 266 - { value: 'opt1', hint: 'Hint 1' }, 267 - { value: 'opt2', hint: 'Hint 2' }, 268 - ], 269 - initialValues: ['opt0', 'opt1'], 270 - input, 271 - output, 272 - }); 273 - 274 - // Check that both selected options show their hints 275 - input.emit('keypress', '', { name: 'down' }); 276 - input.emit('keypress', '', { name: 'down' }); 277 - input.emit('keypress', '', { name: 'return' }); 278 - 279 - const value = await result; 280 - 281 - expect(value).toEqual(['opt0', 'opt1']); 282 - expect(output.buffer).toMatchSnapshot(); 283 - }); 284 - 285 - test('renders multiple cancelled values', async () => { 286 - const result = prompts.multiselect({ 287 - message: 'foo', 288 - options: [{ value: 'opt0' }, { value: 'opt1' }, { value: 'opt2' }], 289 - input, 290 - output, 291 - }); 292 - 293 - input.emit('keypress', '', { name: 'space' }); 294 - input.emit('keypress', '', { name: 'down' }); 295 - input.emit('keypress', '', { name: 'space' }); 296 - input.emit('keypress', '', { name: 'escape' }); 297 - 298 - const value = await result; 299 - 300 - expect(prompts.isCancel(value)).toBe(true); 301 - expect(output.buffer).toMatchSnapshot(); 302 - }); 303 - 304 - test('can be aborted by a signal', async () => { 305 - const controller = new AbortController(); 306 - const result = prompts.multiselect({ 307 - message: 'foo', 308 - options: [{ value: 'opt0' }, { value: 'opt1' }], 309 - input, 310 - output, 311 - signal: controller.signal, 312 - }); 313 - 314 - controller.abort(); 315 - const value = await result; 316 - expect(prompts.isCancel(value)).toBe(true); 317 - expect(output.buffer).toMatchSnapshot(); 318 - }); 319 - 320 - test('renders disabled options', async () => { 321 - const result = prompts.multiselect({ 322 - message: 'foo', 323 - options: [ 324 - { value: 'opt0', disabled: true }, 325 - { value: 'opt1' }, 326 - { value: 'opt2', disabled: true, hint: 'Hint 2' }, 327 - ], 328 - input, 329 - output, 330 - }); 331 - 332 - input.emit('keypress', '', { name: 'space' }); 333 - input.emit('keypress', '', { name: 'return' }); 334 - 335 - const value = await result; 336 - 337 - expect(value).toEqual(['opt1']); 338 - expect(output.buffer).toMatchSnapshot(); 339 - }); 340 - 341 - test('wraps long messages', async () => { 342 - output.columns = 40; 343 - 344 - const result = prompts.multiselect({ 345 - message: 'foo '.repeat(20).trim(), 346 - options: [{ value: 'opt0' }, { value: 'opt1' }], 347 - input, 348 - output, 349 - }); 350 - 351 - input.emit('keypress', '', { name: 'space' }); 352 - input.emit('keypress', '', { name: 'return' }); 353 - 354 - const value = await result; 355 - 356 - expect(value).toEqual(['opt0']); 357 - expect(output.buffer).toMatchSnapshot(); 358 - }); 359 - 360 - test('wraps cancelled state with long options', async () => { 361 - output.columns = 40; 362 - 363 - const result = prompts.multiselect({ 364 - message: 'foo', 365 - options: [ 366 - { value: 'opt0', label: 'Option 0 '.repeat(10).trim() }, 367 - { value: 'opt1', label: 'Option 1 '.repeat(10).trim() }, 368 - ], 369 - input, 370 - output, 371 - }); 372 - 373 - input.emit('keypress', '', { name: 'space' }); 374 - input.emit('keypress', 'escape', { name: 'escape' }); 375 - 376 - const value = await result; 377 - 378 - expect(prompts.isCancel(value)).toBe(true); 379 - expect(output.buffer).toMatchSnapshot(); 380 - }); 381 - 382 - test('wraps success state with long options', async () => { 383 - output.columns = 40; 384 - 385 - const result = prompts.multiselect({ 386 - message: 'foo', 387 - options: [ 388 - { value: 'opt0', label: 'Option 0 '.repeat(10).trim() }, 389 - { value: 'opt1', label: 'Option 1 '.repeat(10).trim() }, 390 - ], 391 - input, 392 - output, 393 - }); 394 - 395 - input.emit('keypress', '', { name: 'space' }); 396 - input.emit('keypress', '', { name: 'return' }); 397 - 398 - const value = await result; 399 - 400 - expect(value).toEqual(['opt0']); 401 - expect(output.buffer).toMatchSnapshot(); 402 - }); 403 - 404 - test('withGuide: false removes guide', async () => { 405 - const result = prompts.multiselect({ 406 - message: 'foo', 407 - options: [{ value: 'opt0' }, { value: 'opt1' }], 408 - withGuide: false, 409 - input, 410 - output, 411 - }); 412 - 413 - input.emit('keypress', '', { name: 'space' }); 414 - input.emit('keypress', '', { name: 'return' }); 415 - 416 - const value = await result; 417 - 418 - expect(value).toEqual(['opt0']); 419 - expect(output.buffer).toMatchSnapshot(); 420 - }); 421 - 422 - test('global withGuide: false removes guide', async () => { 423 - prompts.updateSettings({ withGuide: false }); 424 - 425 - const result = prompts.multiselect({ 426 - message: 'foo', 427 - options: [{ value: 'opt0' }, { value: 'opt1' }], 428 - input, 429 - output, 430 - }); 431 - 432 - input.emit('keypress', '', { name: 'space' }); 433 - input.emit('keypress', '', { name: 'return' }); 434 - 435 - const value = await result; 436 - 437 - expect(value).toEqual(['opt0']); 438 - expect(output.buffer).toMatchSnapshot(); 439 - }); 440 - });
-122
packages/prompts/test/note.test.ts
··· 1 - import { styleText } from 'node:util'; 2 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 3 - import * as prompts from '../src/index.js'; 4 - import { MockReadable, MockWritable } from './test-utils.js'; 5 - 6 - describe.each(['true', 'false'])('note (isCI = %s)', (isCI) => { 7 - let originalCI: string | undefined; 8 - let output: MockWritable; 9 - let input: MockReadable; 10 - 11 - beforeAll(() => { 12 - originalCI = process.env.CI; 13 - process.env.CI = isCI; 14 - }); 15 - 16 - afterAll(() => { 17 - process.env.CI = originalCI; 18 - }); 19 - 20 - beforeEach(() => { 21 - output = new MockWritable(); 22 - input = new MockReadable(); 23 - }); 24 - 25 - afterEach(() => { 26 - vi.restoreAllMocks(); 27 - }); 28 - 29 - test('renders message with title', () => { 30 - prompts.note('message', 'title', { 31 - input, 32 - output, 33 - }); 34 - 35 - expect(output.buffer).toMatchSnapshot(); 36 - }); 37 - 38 - test('renders as wide as longest line', () => { 39 - prompts.note('short\nsomewhat questionably long line', 'title', { 40 - input, 41 - output, 42 - }); 43 - 44 - expect(output.buffer).toMatchSnapshot(); 45 - }); 46 - 47 - test('formatter which adds length works', () => { 48 - prompts.note('line 0\nline 1\nline 2', 'title', { 49 - format: (line) => `* ${line} *`, 50 - input, 51 - output, 52 - }); 53 - 54 - expect(output.buffer).toMatchSnapshot(); 55 - }); 56 - 57 - test('formatter which adds colors works', () => { 58 - prompts.note('line 0\nline 1\nline 2', 'title', { 59 - format: (line) => styleText('red', line), 60 - input, 61 - output, 62 - }); 63 - 64 - expect(output.buffer).toMatchSnapshot(); 65 - }); 66 - 67 - test("don't overflow", () => { 68 - const message = `${'test string '.repeat(32)}\n`.repeat(4).trim(); 69 - output.columns = 75; 70 - prompts.note(message, 'title', { 71 - input, 72 - output, 73 - }); 74 - 75 - expect(output.buffer).toMatchSnapshot(); 76 - }); 77 - 78 - test("don't overflow with formatter", () => { 79 - const message = `${'test string '.repeat(32)}\n`.repeat(4).trim(); 80 - output.columns = 75; 81 - prompts.note(message, 'title', { 82 - format: (line) => styleText('red', `* ${styleText('cyan', line)} *`), 83 - input, 84 - output, 85 - }); 86 - 87 - expect(output.buffer).toMatchSnapshot(); 88 - }); 89 - 90 - test('handle wide characters', () => { 91 - const messages = ['이게 첫 번째 줄이에요', 'これは次の行です']; 92 - output.columns = 10; 93 - prompts.note(messages.join('\n'), '这是标题', { 94 - input, 95 - output, 96 - }); 97 - 98 - expect(output.buffer).toMatchSnapshot(); 99 - }); 100 - 101 - test('handle wide characters with formatter', () => { 102 - const messages = ['이게 첫 번째 줄이에요', 'これは次の行です']; 103 - output.columns = 10; 104 - prompts.note(messages.join('\n'), '这是标题', { 105 - format: (line) => styleText('red', `* ${styleText('cyan', line)} *`), 106 - input, 107 - output, 108 - }); 109 - 110 - expect(output.buffer).toMatchSnapshot(); 111 - }); 112 - 113 - test('without guide', () => { 114 - prompts.note('message', 'title', { 115 - input, 116 - output, 117 - withGuide: false, 118 - }); 119 - 120 - expect(output.buffer).toMatchSnapshot(); 121 - }); 122 - });
-185
packages/prompts/test/password.test.ts
··· 1 - import { updateSettings } from '@clack/core'; 2 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 3 - import * as prompts from '../src/index.js'; 4 - import { MockReadable, MockWritable } from './test-utils.js'; 5 - 6 - describe.each(['true', 'false'])('password (isCI = %s)', (isCI) => { 7 - let originalCI: string | undefined; 8 - let output: MockWritable; 9 - let input: MockReadable; 10 - 11 - beforeAll(() => { 12 - originalCI = process.env.CI; 13 - process.env.CI = isCI; 14 - }); 15 - 16 - afterAll(() => { 17 - process.env.CI = originalCI; 18 - }); 19 - 20 - beforeEach(() => { 21 - output = new MockWritable(); 22 - input = new MockReadable(); 23 - }); 24 - 25 - afterEach(() => { 26 - vi.restoreAllMocks(); 27 - updateSettings({ withGuide: true }); 28 - }); 29 - 30 - test('renders message', async () => { 31 - const result = prompts.password({ 32 - message: 'foo', 33 - input, 34 - output, 35 - }); 36 - 37 - input.emit('keypress', '', { name: 'return' }); 38 - 39 - await result; 40 - 41 - expect(output.buffer).toMatchSnapshot(); 42 - }); 43 - 44 - test('renders masked value', async () => { 45 - const result = prompts.password({ 46 - message: 'foo', 47 - input, 48 - output, 49 - }); 50 - 51 - input.emit('keypress', 'x', { name: 'x' }); 52 - input.emit('keypress', 'y', { name: 'y' }); 53 - input.emit('keypress', '', { name: 'return' }); 54 - 55 - const value = await result; 56 - 57 - expect(value).toBe('xy'); 58 - expect(output.buffer).toMatchSnapshot(); 59 - }); 60 - 61 - test('renders custom mask', async () => { 62 - const result = prompts.password({ 63 - message: 'foo', 64 - mask: '*', 65 - input, 66 - output, 67 - }); 68 - 69 - input.emit('keypress', 'x', { name: 'x' }); 70 - input.emit('keypress', 'y', { name: 'y' }); 71 - input.emit('keypress', '', { name: 'return' }); 72 - 73 - await result; 74 - 75 - expect(output.buffer).toMatchSnapshot(); 76 - }); 77 - 78 - test('renders and clears validation errors', async () => { 79 - const result = prompts.password({ 80 - message: 'foo', 81 - validate: (value) => { 82 - if (!value || value.length < 2) { 83 - return 'Password must be at least 2 characters'; 84 - } 85 - 86 - return undefined; 87 - }, 88 - input, 89 - output, 90 - }); 91 - 92 - input.emit('keypress', 'x', { name: 'x' }); 93 - input.emit('keypress', '', { name: 'return' }); 94 - input.emit('keypress', 'y', { name: 'y' }); 95 - input.emit('keypress', '', { name: 'return' }); 96 - 97 - const value = await result; 98 - 99 - expect(value).toBe('xy'); 100 - expect(output.buffer).toMatchSnapshot(); 101 - }); 102 - 103 - test('renders cancelled value', async () => { 104 - const result = prompts.password({ 105 - message: 'foo', 106 - input, 107 - output, 108 - }); 109 - 110 - input.emit('keypress', 'x', { name: 'x' }); 111 - input.emit('keypress', '', { name: 'escape' }); 112 - 113 - const value = await result; 114 - 115 - expect(prompts.isCancel(value)).toBe(true); 116 - expect(output.buffer).toMatchSnapshot(); 117 - }); 118 - 119 - test('can be aborted by a signal', async () => { 120 - const controller = new AbortController(); 121 - const result = prompts.password({ 122 - message: 'foo', 123 - input, 124 - output, 125 - signal: controller.signal, 126 - }); 127 - 128 - controller.abort(); 129 - const value = await result; 130 - expect(prompts.isCancel(value)).toBe(true); 131 - expect(output.buffer).toMatchSnapshot(); 132 - }); 133 - 134 - test('clears input on error when clearOnError is true', async () => { 135 - const result = prompts.password({ 136 - message: 'foo', 137 - input, 138 - output, 139 - validate: (v) => (v === 'yz' ? undefined : 'Error'), 140 - clearOnError: true, 141 - }); 142 - 143 - input.emit('keypress', 'x', { name: 'x' }); 144 - input.emit('keypress', '', { name: 'return' }); 145 - input.emit('keypress', 'y', { name: 'y' }); 146 - input.emit('keypress', 'z', { name: 'z' }); 147 - input.emit('keypress', '', { name: 'return' }); 148 - 149 - const value = await result; 150 - 151 - expect(value).toBe('yz'); 152 - expect(output.buffer).toMatchSnapshot(); 153 - }); 154 - 155 - test('withGuide: false removes guide', async () => { 156 - const result = prompts.password({ 157 - message: 'foo', 158 - withGuide: false, 159 - input, 160 - output, 161 - }); 162 - 163 - input.emit('keypress', '', { name: 'return' }); 164 - 165 - await result; 166 - 167 - expect(output.buffer).toMatchSnapshot(); 168 - }); 169 - 170 - test('global withGuide: false removes guide', async () => { 171 - updateSettings({ withGuide: false }); 172 - 173 - const result = prompts.password({ 174 - message: 'foo', 175 - input, 176 - output, 177 - }); 178 - 179 - input.emit('keypress', '', { name: 'return' }); 180 - 181 - await result; 182 - 183 - expect(output.buffer).toMatchSnapshot(); 184 - }); 185 - });
-283
packages/prompts/test/path.test.ts
··· 1 - import { vol } from 'memfs'; 2 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 3 - import * as prompts from '../src/index.js'; 4 - import { MockReadable, MockWritable } from './test-utils.js'; 5 - 6 - vi.mock('node:fs'); 7 - 8 - describe.each(['true', 'false'])('text (isCI = %s)', (isCI) => { 9 - let originalCI: string | undefined; 10 - let output: MockWritable; 11 - let input: MockReadable; 12 - 13 - beforeAll(() => { 14 - originalCI = process.env.CI; 15 - process.env.CI = isCI; 16 - }); 17 - 18 - afterAll(() => { 19 - process.env.CI = originalCI; 20 - }); 21 - 22 - beforeEach(() => { 23 - output = new MockWritable(); 24 - input = new MockReadable(); 25 - vol.reset(); 26 - vol.fromJSON( 27 - { 28 - './foo/bar.txt': '1', 29 - './foo/baz.text': '2', 30 - './hello/world.jpg': '3', 31 - './hello/john.jpg': '4', 32 - './hello/jeanne.png': '5', 33 - './root.zip': '6', 34 - './bar': '7', 35 - }, 36 - '/tmp' 37 - ); 38 - }); 39 - 40 - afterEach(() => { 41 - vi.restoreAllMocks(); 42 - }); 43 - 44 - test('renders message', async () => { 45 - const result = prompts.path({ 46 - message: 'foo', 47 - input, 48 - output, 49 - root: '/tmp/', 50 - }); 51 - 52 - input.emit('keypress', '', { name: 'return' }); 53 - 54 - const value = await result; 55 - 56 - expect(output.buffer).toMatchSnapshot(); 57 - expect(value).toBe('/tmp/bar'); 58 - }); 59 - 60 - test('can cancel', async () => { 61 - const result = prompts.path({ 62 - message: 'foo', 63 - root: '/tmp/', 64 - input, 65 - output, 66 - }); 67 - 68 - input.emit('keypress', 'escape', { name: 'escape' }); 69 - 70 - const value = await result; 71 - 72 - expect(prompts.isCancel(value)).toBe(true); 73 - expect(output.buffer).toMatchSnapshot(); 74 - }); 75 - 76 - test('renders cancelled value if one set', async () => { 77 - const result = prompts.path({ 78 - message: 'foo', 79 - input, 80 - output, 81 - root: '/tmp/', 82 - }); 83 - 84 - input.emit('keypress', 'x', { name: 'x' }); 85 - input.emit('keypress', 'y', { name: 'y' }); 86 - input.emit('keypress', '', { name: 'escape' }); 87 - 88 - const value = await result; 89 - 90 - expect(prompts.isCancel(value)).toBe(true); 91 - expect(output.buffer).toMatchSnapshot(); 92 - }); 93 - 94 - test('renders submitted value', async () => { 95 - const result = prompts.path({ 96 - message: 'foo', 97 - root: '/tmp/', 98 - input, 99 - output, 100 - }); 101 - 102 - input.emit('keypress', 'b', { name: 'b' }); 103 - input.emit('keypress', 'a', { name: 'a' }); 104 - input.emit('keypress', '', { name: 'return' }); 105 - 106 - const value = await result; 107 - 108 - expect(value).toBe('/tmp/bar'); 109 - expect(output.buffer).toMatchSnapshot(); 110 - }); 111 - 112 - test('cannot submit unknown value', async () => { 113 - const result = prompts.path({ 114 - message: 'foo', 115 - root: '/tmp/', 116 - input, 117 - output, 118 - }); 119 - 120 - input.emit('keypress', '_', { name: '_' }); 121 - input.emit('keypress', '', { name: 'return' }); 122 - input.emit('keypress', '', { name: 'h', ctrl: true }); 123 - input.emit('keypress', 'b', { name: 'b' }); 124 - input.emit('keypress', '', { name: 'return' }); 125 - 126 - const value = await result; 127 - 128 - expect(value).toBe('/tmp/bar'); 129 - expect(output.buffer).toMatchSnapshot(); 130 - }); 131 - 132 - test('initialValue sets the value', async () => { 133 - const result = prompts.path({ 134 - message: 'foo', 135 - initialValue: '/tmp/bar', 136 - root: '/tmp/', 137 - input, 138 - output, 139 - }); 140 - 141 - input.emit('keypress', '', { name: 'return' }); 142 - 143 - const value = await result; 144 - 145 - expect(value).toBe('/tmp/bar'); 146 - expect(output.buffer).toMatchSnapshot(); 147 - }); 148 - 149 - test('directory mode only allows selecting directories', async () => { 150 - const result = prompts.path({ 151 - message: 'foo', 152 - root: '/tmp/', 153 - directory: true, 154 - input, 155 - output, 156 - }); 157 - 158 - input.emit('keypress', 'f', { name: 'f' }); 159 - input.emit('keypress', '', { name: 'return' }); 160 - 161 - const value = await result; 162 - 163 - expect(value).toBe('/tmp/foo'); 164 - }); 165 - 166 - test('directory mode submits initial directory value on enter', async () => { 167 - const result = prompts.path({ 168 - message: 'foo', 169 - root: '/tmp/', 170 - initialValue: '/tmp', 171 - directory: true, 172 - input, 173 - output, 174 - }); 175 - 176 - input.emit('keypress', '', { name: 'return' }); 177 - 178 - const value = await result; 179 - 180 - expect(value).toBe('/tmp'); 181 - }); 182 - 183 - test('directory mode traverses into child when trailing slash entered', async () => { 184 - const result = prompts.path({ 185 - message: 'foo', 186 - root: '/tmp/', 187 - initialValue: '/tmp', 188 - directory: true, 189 - input, 190 - output, 191 - }); 192 - 193 - input.emit('keypress', '/', { name: '/' }); 194 - input.emit('keypress', '', { name: 'return' }); 195 - 196 - const value = await result; 197 - 198 - expect(value).toBe('/tmp/foo'); 199 - }); 200 - 201 - test('directory mode can navigate from initial directory to child directory', async () => { 202 - const result = prompts.path({ 203 - message: 'foo', 204 - root: '/tmp/', 205 - initialValue: '/tmp/', 206 - directory: true, 207 - input, 208 - output, 209 - }); 210 - 211 - input.emit('keypress', 'f', { name: 'f' }); 212 - input.emit('keypress', '', { name: 'return' }); 213 - 214 - const value = await result; 215 - 216 - expect(value).toBe('/tmp/foo'); 217 - }); 218 - 219 - test('default mode allows selecting files', async () => { 220 - const result = prompts.path({ 221 - message: 'foo', 222 - root: '/tmp/', 223 - input, 224 - output, 225 - }); 226 - 227 - input.emit('keypress', 'r', { name: 'r' }); 228 - input.emit('keypress', 'o', { name: 'o' }); 229 - input.emit('keypress', 'o', { name: 'o' }); 230 - input.emit('keypress', 't', { name: 't' }); 231 - input.emit('keypress', '', { name: 'return' }); 232 - 233 - const value = await result; 234 - 235 - expect(value).toBe('/tmp/root.zip'); 236 - }); 237 - 238 - test('validation errors render and clear', async () => { 239 - const result = prompts.path({ 240 - message: 'foo', 241 - root: '/tmp/', 242 - validate: (val) => (val !== '/tmp/bar' ? 'should be /tmp/bar' : undefined), 243 - input, 244 - output, 245 - }); 246 - 247 - // to match `root.zip` 248 - input.emit('keypress', 'r', { name: 'r' }); 249 - input.emit('keypress', '', { name: 'return' }); 250 - // delete what we had 251 - input.emit('keypress', '', { name: 'h', ctrl: true }); 252 - input.emit('keypress', 'b', { name: 'b' }); 253 - input.emit('keypress', '', { name: 'return' }); 254 - 255 - const value = await result; 256 - 257 - expect(value).toBe('/tmp/bar'); 258 - expect(output.buffer).toMatchSnapshot(); 259 - }); 260 - 261 - test('validation errors render and clear (using Error)', async () => { 262 - const result = prompts.path({ 263 - message: 'foo', 264 - root: '/tmp/', 265 - validate: (val) => (val !== '/tmp/bar' ? new Error('should be /tmp/bar') : undefined), 266 - input, 267 - output, 268 - }); 269 - 270 - // to match `root.zip` 271 - input.emit('keypress', 'r', { name: 'r' }); 272 - input.emit('keypress', '', { name: 'return' }); 273 - // delete what we had 274 - input.emit('keypress', '', { name: 'h', ctrl: true }); 275 - input.emit('keypress', 'b', { name: 'b' }); 276 - input.emit('keypress', '', { name: 'return' }); 277 - 278 - const value = await result; 279 - 280 - expect(value).toBe('/tmp/bar'); 281 - expect(output.buffer).toMatchSnapshot(); 282 - }); 283 - });
+45 -56
packages/prompts/test/progress-bar.test.ts packages/prompts/src/progress-bar.test.ts
··· 1 1 import process from 'node:process'; 2 2 import { EventEmitter } from 'node:stream'; 3 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 4 - import type { ProgressOptions } from '../src/index.js'; 5 - import * as prompts from '../src/index.js'; 6 - import { MockWritable } from './test-utils.js'; 3 + import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; 4 + import type { ProgressOptions } from './index.js'; 5 + import * as prompts from './index.js'; 6 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 7 7 8 8 describe.each(['true', 'false'])('prompts - progress (isCI = %s)', (isCI) => { 9 - let originalCI: string | undefined; 10 - let output: MockWritable; 11 - 12 - beforeAll(() => { 13 - originalCI = process.env.CI; 14 - process.env.CI = isCI; 15 - }); 16 - 17 - afterAll(() => { 18 - process.env.CI = originalCI; 19 - }); 9 + let mocks: Mocks<{ output: true }>; 20 10 21 11 beforeEach(() => { 22 - output = new MockWritable(); 12 + mocks = createMocks({ output: true, env: { CI: isCI } }); 23 13 vi.useFakeTimers(); 24 14 }); 25 15 26 16 afterEach(() => { 27 - vi.restoreAllMocks(); 28 17 vi.useRealTimers(); 29 18 }); 30 19 31 20 test('returns progress API', () => { 32 - const api = prompts.progress({ output }); 21 + const api = prompts.progress({ output: mocks.output }); 33 22 34 23 expect(api.stop).toBeTypeOf('function'); 35 24 expect(api.start).toBeTypeOf('function'); ··· 39 28 40 29 describe('start', () => { 41 30 test('renders frames at interval', () => { 42 - const result = prompts.progress({ output }); 31 + const result = prompts.progress({ output: mocks.output }); 43 32 44 33 result.start(); 45 34 ··· 48 37 vi.advanceTimersByTime(80); 49 38 } 50 39 51 - expect(output.buffer).toMatchSnapshot(); 40 + expect(mocks.output.buffer).toMatchSnapshot(); 52 41 }); 53 42 54 43 test('renders message', () => { 55 - const result = prompts.progress({ output }); 44 + const result = prompts.progress({ output: mocks.output }); 56 45 57 46 result.start('foo'); 58 47 59 48 vi.advanceTimersByTime(80); 60 49 61 - expect(output.buffer).toMatchSnapshot(); 50 + expect(mocks.output.buffer).toMatchSnapshot(); 62 51 }); 63 52 64 53 test('renders timer when indicator is "timer"', () => { 65 - const result = prompts.progress({ output, indicator: 'timer' }); 54 + const result = prompts.progress({ output: mocks.output, indicator: 'timer' }); 66 55 67 56 result.start(); 68 57 69 58 vi.advanceTimersByTime(80); 70 59 71 - expect(output.buffer).toMatchSnapshot(); 60 + expect(mocks.output.buffer).toMatchSnapshot(); 72 61 }); 73 62 }); 74 63 75 64 describe('stop', () => { 76 65 test('renders submit symbol and stops progress', () => { 77 - const result = prompts.progress({ output }); 66 + const result = prompts.progress({ output: mocks.output }); 78 67 79 68 result.start(); 80 69 ··· 84 73 85 74 vi.advanceTimersByTime(80); 86 75 87 - expect(output.buffer).toMatchSnapshot(); 76 + expect(mocks.output.buffer).toMatchSnapshot(); 88 77 }); 89 78 90 79 test('renders cancel symbol when calling cancel()', () => { 91 - const result = prompts.progress({ output }); 80 + const result = prompts.progress({ output: mocks.output }); 92 81 93 82 result.start(); 94 83 ··· 96 85 97 86 result.cancel(); 98 87 99 - expect(output.buffer).toMatchSnapshot(); 88 + expect(mocks.output.buffer).toMatchSnapshot(); 100 89 }); 101 90 102 91 test('renders error symbol when calling error()', () => { 103 - const result = prompts.progress({ output }); 92 + const result = prompts.progress({ output: mocks.output }); 104 93 105 94 result.start(); 106 95 ··· 108 97 109 98 result.error(); 110 99 111 - expect(output.buffer).toMatchSnapshot(); 100 + expect(mocks.output.buffer).toMatchSnapshot(); 112 101 }); 113 102 114 103 test('renders message', () => { 115 - const result = prompts.progress({ output }); 104 + const result = prompts.progress({ output: mocks.output }); 116 105 117 106 result.start(); 118 107 ··· 120 109 121 110 result.stop('foo'); 122 111 123 - expect(output.buffer).toMatchSnapshot(); 112 + expect(mocks.output.buffer).toMatchSnapshot(); 124 113 }); 125 114 126 115 test('renders message without removing dots', () => { 127 - const result = prompts.progress({ output }); 116 + const result = prompts.progress({ output: mocks.output }); 128 117 129 118 result.start(); 130 119 ··· 132 121 133 122 result.stop('foo.'); 134 123 135 - expect(output.buffer).toMatchSnapshot(); 124 + expect(mocks.output.buffer).toMatchSnapshot(); 136 125 }); 137 126 138 127 test('renders message when cancelling', () => { 139 - const result = prompts.progress({ output }); 128 + const result = prompts.progress({ output: mocks.output }); 140 129 141 130 result.start(); 142 131 ··· 144 133 145 134 result.cancel('cancelled :-('); 146 135 147 - expect(output.buffer).toMatchSnapshot(); 136 + expect(mocks.output.buffer).toMatchSnapshot(); 148 137 }); 149 138 150 139 test('renders message when erroring', () => { 151 - const result = prompts.progress({ output }); 140 + const result = prompts.progress({ output: mocks.output }); 152 141 153 142 result.start(); 154 143 ··· 156 145 157 146 result.error('FATAL ERROR!'); 158 147 159 - expect(output.buffer).toMatchSnapshot(); 148 + expect(mocks.output.buffer).toMatchSnapshot(); 160 149 }); 161 150 }); 162 151 163 152 describe('message', () => { 164 153 test('sets message for next frame', () => { 165 - const result = prompts.progress({ output }); 154 + const result = prompts.progress({ output: mocks.output }); 166 155 167 156 result.start(); 168 157 ··· 172 161 173 162 vi.advanceTimersByTime(80); 174 163 175 - expect(output.buffer).toMatchSnapshot(); 164 + expect(mocks.output.buffer).toMatchSnapshot(); 176 165 }); 177 166 }); 178 167 ··· 198 187 }); 199 188 200 189 test('uses default cancel message', () => { 201 - const result = prompts.progress({ output }); 190 + const result = prompts.progress({ output: mocks.output }); 202 191 result.start('Test operation'); 203 192 204 193 processEmitter.emit('SIGINT'); 205 194 206 - expect(output.buffer).toMatchSnapshot(); 195 + expect(mocks.output.buffer).toMatchSnapshot(); 207 196 }); 208 197 209 198 test('uses custom cancel message when provided directly', () => { 210 199 const result = prompts.progress({ 211 - output, 200 + output: mocks.output, 212 201 cancelMessage: 'Custom cancel message', 213 202 }); 214 203 result.start('Test operation'); 215 204 216 205 processEmitter.emit('SIGINT'); 217 206 218 - expect(output.buffer).toMatchSnapshot(); 207 + expect(mocks.output.buffer).toMatchSnapshot(); 219 208 }); 220 209 221 210 test('uses custom error message when provided directly', () => { 222 211 const result = prompts.progress({ 223 - output, 212 + output: mocks.output, 224 213 errorMessage: 'Custom error message', 225 214 }); 226 215 result.start('Test operation'); 227 216 228 217 processEmitter.emit('exit', 2); 229 218 230 - expect(output.buffer).toMatchSnapshot(); 219 + expect(mocks.output.buffer).toMatchSnapshot(); 231 220 }); 232 221 233 222 test('uses global custom cancel message from settings', () => { ··· 237 226 // Set custom message 238 227 prompts.settings.messages.cancel = 'Global cancel message'; 239 228 240 - const result = prompts.progress({ output }); 229 + const result = prompts.progress({ output: mocks.output }); 241 230 result.start('Test operation'); 242 231 243 232 processEmitter.emit('SIGINT'); 244 233 245 - expect(output.buffer).toMatchSnapshot(); 234 + expect(mocks.output.buffer).toMatchSnapshot(); 246 235 } finally { 247 236 // Reset to original 248 237 prompts.settings.messages.cancel = originalCancelMessage; ··· 256 245 // Set custom message 257 246 prompts.settings.messages.error = 'Global error message'; 258 247 259 - const result = prompts.progress({ output }); 248 + const result = prompts.progress({ output: mocks.output }); 260 249 result.start('Test operation'); 261 250 262 251 processEmitter.emit('exit', 2); 263 252 264 - expect(output.buffer).toMatchSnapshot(); 253 + expect(mocks.output.buffer).toMatchSnapshot(); 265 254 } finally { 266 255 // Reset to original 267 256 prompts.settings.messages.error = originalErrorMessage; ··· 277 266 prompts.settings.messages.error = 'Global error message'; 278 267 279 268 const result = prompts.progress({ 280 - output, 269 + output: mocks.output, 281 270 errorMessage: 'Progress error message', 282 271 }); 283 272 result.start('Test operation'); 284 273 285 274 processEmitter.emit('exit', 2); 286 - expect(output.buffer).toMatchSnapshot(); 275 + expect(mocks.output.buffer).toMatchSnapshot(); 287 276 } finally { 288 277 // Reset to original values 289 278 prompts.settings.messages.error = originalErrorMessage; ··· 299 288 prompts.settings.messages.cancel = 'Global cancel message'; 300 289 301 290 const result = prompts.progress({ 302 - output, 291 + output: mocks.output, 303 292 cancelMessage: 'Progress cancel message', 304 293 }); 305 294 result.start('Test operation'); 306 295 307 296 processEmitter.emit('SIGINT'); 308 - expect(output.buffer).toMatchSnapshot(); 297 + expect(mocks.output.buffer).toMatchSnapshot(); 309 298 } finally { 310 299 // Reset to original values 311 300 prompts.settings.messages.cancel = originalCancelMessage; ··· 317 306 test.each(['block', 'heavy', 'light'] satisfies Array<ProgressOptions['style']>)( 318 307 'renders %s progressbar', 319 308 (style) => { 320 - const result = prompts.progress({ output, style, max: 2, size: 10 }); 309 + const result = prompts.progress({ output: mocks.output, style, max: 2, size: 10 }); 321 310 result.start(); 322 311 vi.advanceTimersByTime(160); 323 312 result.advance(); 324 313 vi.advanceTimersByTime(160); 325 314 result.stop(); 326 315 327 - expect(output.buffer).toMatchSnapshot(); 316 + expect(mocks.output.buffer).toMatchSnapshot(); 328 317 } 329 318 ); 330 319 });
+57 -70
packages/prompts/test/select-key.test.ts packages/prompts/src/select-key.test.ts
··· 1 1 import { updateSettings } from '@clack/core'; 2 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 3 - import * as prompts from '../src/index.js'; 4 - import { MockReadable, MockWritable } from './test-utils.js'; 2 + import { afterEach, beforeEach, describe, expect, test } from 'vitest'; 3 + import * as prompts from './index.js'; 4 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 5 5 6 6 describe.each(['true', 'false'])('text (isCI = %s)', (isCI) => { 7 - let originalCI: string | undefined; 8 - let output: MockWritable; 9 - let input: MockReadable; 10 - 11 - beforeAll(() => { 12 - originalCI = process.env.CI; 13 - process.env.CI = isCI; 14 - }); 15 - 16 - afterAll(() => { 17 - process.env.CI = originalCI; 18 - }); 7 + let mocks: Mocks<{ input: true; output: true }>; 19 8 20 9 beforeEach(() => { 21 - output = new MockWritable(); 22 - input = new MockReadable(); 10 + mocks = createMocks({ input: true, output: true, env: { CI: isCI } }); 23 11 }); 24 12 25 13 afterEach(() => { 26 - vi.restoreAllMocks(); 27 14 updateSettings({ withGuide: true }); 28 15 }); 29 16 ··· 34 21 { label: 'Option A', value: 'a' }, 35 22 { label: 'Option B', value: 'b' }, 36 23 ], 37 - input, 38 - output, 24 + input: mocks.input, 25 + output: mocks.output, 39 26 }); 40 27 41 - input.emit('keypress', '', { name: 'return' }); 28 + mocks.input.emit('keypress', '', { name: 'return' }); 42 29 43 30 const value = await result; 44 31 45 - expect(output.buffer).toMatchSnapshot(); 32 + expect(mocks.output.buffer).toMatchSnapshot(); 46 33 expect(value).toBe(undefined); 47 34 }); 48 35 ··· 53 40 { label: 'Option A', value: 'a' }, 54 41 { label: 'Option B', value: 'b' }, 55 42 ], 56 - input, 57 - output, 43 + input: mocks.input, 44 + output: mocks.output, 58 45 }); 59 46 60 - input.emit('keypress', 'b', { name: 'b' }); 47 + mocks.input.emit('keypress', 'b', { name: 'b' }); 61 48 62 49 const value = await result; 63 50 64 - expect(output.buffer).toMatchSnapshot(); 51 + expect(mocks.output.buffer).toMatchSnapshot(); 65 52 expect(value).toBe('b'); 66 53 }); 67 54 ··· 72 59 { label: 'Option A', value: 'a' }, 73 60 { label: 'Option B', value: 'b' }, 74 61 ], 75 - input, 76 - output, 62 + input: mocks.input, 63 + output: mocks.output, 77 64 }); 78 65 79 - input.emit('keypress', 'escape', { name: 'escape' }); 66 + mocks.input.emit('keypress', 'escape', { name: 'escape' }); 80 67 81 68 const value = await result; 82 69 83 - expect(output.buffer).toMatchSnapshot(); 70 + expect(mocks.output.buffer).toMatchSnapshot(); 84 71 expect(prompts.isCancel(value)).toBe(true); 85 72 }); 86 73 ··· 91 78 { label: 'Option A', value: 'A' }, 92 79 { label: 'Option B', value: 'b' }, 93 80 ], 94 - input, 95 - output, 81 + input: mocks.input, 82 + output: mocks.output, 96 83 }); 97 84 98 - input.emit('keypress', 'a', { name: 'a' }); 85 + mocks.input.emit('keypress', 'a', { name: 'a' }); 99 86 100 87 const value = await result; 101 88 102 - expect(output.buffer).toMatchSnapshot(); 89 + expect(mocks.output.buffer).toMatchSnapshot(); 103 90 expect(value).toBe('A'); 104 91 }); 105 92 ··· 110 97 { label: 'Option A', value: 'a' }, 111 98 { label: 'Option B', value: 'b' }, 112 99 ], 113 - input, 114 - output, 100 + input: mocks.input, 101 + output: mocks.output, 115 102 }); 116 103 117 - input.emit('keypress', 'a', { name: 'a', shift: true }); 104 + mocks.input.emit('keypress', 'a', { name: 'a', shift: true }); 118 105 119 106 const value = await result; 120 107 121 - expect(output.buffer).toMatchSnapshot(); 108 + expect(mocks.output.buffer).toMatchSnapshot(); 122 109 expect(value).toBe('a'); 123 110 }); 124 111 ··· 130 117 { label: 'Option B', value: 'b' }, 131 118 ], 132 119 caseSensitive: true, 133 - input, 134 - output, 120 + input: mocks.input, 121 + output: mocks.output, 135 122 }); 136 123 137 - input.emit('keypress', 'a', { name: 'a' }); 138 - input.emit('keypress', '', { name: 'escape' }); 124 + mocks.input.emit('keypress', 'a', { name: 'a' }); 125 + mocks.input.emit('keypress', '', { name: 'escape' }); 139 126 140 127 const value = await result; 141 128 142 - expect(output.buffer).toMatchSnapshot(); 129 + expect(mocks.output.buffer).toMatchSnapshot(); 143 130 expect(prompts.isCancel(value)).toBe(true); 144 131 }); 145 132 ··· 152 139 { label: 'Option B', value: 'b' }, 153 140 ], 154 141 caseSensitive: true, 155 - input, 156 - output, 142 + input: mocks.input, 143 + output: mocks.output, 157 144 }); 158 145 159 - input.emit('keypress', 'a', { name: 'a', shift: true }); 146 + mocks.input.emit('keypress', 'a', { name: 'a', shift: true }); 160 147 161 148 const value = await result; 162 149 163 - expect(output.buffer).toMatchSnapshot(); 150 + expect(mocks.output.buffer).toMatchSnapshot(); 164 151 expect(value).toBe('A'); 165 152 }); 166 153 167 154 test('long option labels are wrapped correctly', async () => { 168 - output.columns = 40; 155 + mocks.output.columns = 40; 169 156 170 157 const result = prompts.selectKey({ 171 158 message: 'Select an option:', ··· 176 163 }, 177 164 { label: 'Short label', value: 'b' }, 178 165 ], 179 - input, 180 - output, 166 + input: mocks.input, 167 + output: mocks.output, 181 168 }); 182 169 183 - input.emit('keypress', 'a', { name: 'a' }); 170 + mocks.input.emit('keypress', 'a', { name: 'a' }); 184 171 185 172 const value = await result; 186 173 187 - expect(output.buffer).toMatchSnapshot(); 174 + expect(mocks.output.buffer).toMatchSnapshot(); 188 175 expect(value).toBe('a'); 189 176 }); 190 177 191 178 test('long cancelled labels are wrapped correctly', async () => { 192 - output.columns = 40; 179 + mocks.output.columns = 40; 193 180 194 181 const result = prompts.selectKey({ 195 182 message: 'Select an option:', ··· 200 187 }, 201 188 { label: 'Short label', value: 'b' }, 202 189 ], 203 - input, 204 - output, 190 + input: mocks.input, 191 + output: mocks.output, 205 192 }); 206 193 207 - input.emit('keypress', '', { name: 'escape' }); 194 + mocks.input.emit('keypress', '', { name: 'escape' }); 208 195 209 196 await result; 210 197 211 - expect(output.buffer).toMatchSnapshot(); 198 + expect(mocks.output.buffer).toMatchSnapshot(); 212 199 }); 213 200 214 201 test('withGuide: false removes guide', async () => { ··· 219 206 { label: 'Option B', value: 'b' }, 220 207 ], 221 208 withGuide: false, 222 - input, 223 - output, 209 + input: mocks.input, 210 + output: mocks.output, 224 211 }); 225 212 226 - input.emit('keypress', 'a', { name: 'a' }); 213 + mocks.input.emit('keypress', 'a', { name: 'a' }); 227 214 228 215 await result; 229 216 230 - expect(output.buffer).toMatchSnapshot(); 217 + expect(mocks.output.buffer).toMatchSnapshot(); 231 218 }); 232 219 233 220 test('global withGuide: false removes guide', async () => { ··· 239 226 { label: 'Option A', value: 'a' }, 240 227 { label: 'Option B', value: 'b' }, 241 228 ], 242 - input, 243 - output, 229 + input: mocks.input, 230 + output: mocks.output, 244 231 }); 245 232 246 - input.emit('keypress', 'a', { name: 'a' }); 233 + mocks.input.emit('keypress', 'a', { name: 'a' }); 247 234 248 235 await result; 249 236 250 - expect(output.buffer).toMatchSnapshot(); 237 + expect(mocks.output.buffer).toMatchSnapshot(); 251 238 }); 252 239 253 240 test('long submitted labels are wrapped correctly', async () => { 254 - output.columns = 40; 241 + mocks.output.columns = 40; 255 242 256 243 const result = prompts.selectKey({ 257 244 message: 'Select an option:', ··· 262 249 }, 263 250 { label: 'Short label', value: 'b' }, 264 251 ], 265 - input, 266 - output, 252 + input: mocks.input, 253 + output: mocks.output, 267 254 }); 268 255 269 - input.emit('keypress', 'a', { name: 'a' }); 256 + mocks.input.emit('keypress', 'a', { name: 'a' }); 270 257 271 258 await result; 272 259 273 - expect(output.buffer).toMatchSnapshot(); 260 + expect(mocks.output.buffer).toMatchSnapshot(); 274 261 }); 275 262 });
-368
packages/prompts/test/select.test.ts
··· 1 - import { updateSettings } from '@clack/core'; 2 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 3 - import * as prompts from '../src/index.js'; 4 - import { MockReadable, MockWritable } from './test-utils.js'; 5 - 6 - describe.each(['true', 'false'])('select (isCI = %s)', (isCI) => { 7 - let originalCI: string | undefined; 8 - let output: MockWritable; 9 - let input: MockReadable; 10 - 11 - beforeAll(() => { 12 - originalCI = process.env.CI; 13 - process.env.CI = isCI; 14 - }); 15 - 16 - afterAll(() => { 17 - process.env.CI = originalCI; 18 - }); 19 - 20 - beforeEach(() => { 21 - output = new MockWritable(); 22 - input = new MockReadable(); 23 - }); 24 - 25 - afterEach(() => { 26 - vi.restoreAllMocks(); 27 - updateSettings({ withGuide: true }); 28 - }); 29 - 30 - test('renders options and message', async () => { 31 - const result = prompts.select({ 32 - message: 'foo', 33 - options: [{ value: 'opt0' }, { value: 'opt1' }], 34 - input, 35 - output, 36 - }); 37 - 38 - input.emit('keypress', '', { name: 'return' }); 39 - 40 - const value = await result; 41 - 42 - expect(value).toBe('opt0'); 43 - expect(output.buffer).toMatchSnapshot(); 44 - }); 45 - 46 - test('down arrow selects next option', async () => { 47 - const result = prompts.select({ 48 - message: 'foo', 49 - options: [{ value: 'opt0' }, { value: 'opt1' }], 50 - input, 51 - output, 52 - }); 53 - 54 - input.emit('keypress', '', { name: 'down' }); 55 - input.emit('keypress', '', { name: 'return' }); 56 - 57 - const value = await result; 58 - 59 - expect(value).toBe('opt1'); 60 - expect(output.buffer).toMatchSnapshot(); 61 - }); 62 - 63 - test('up arrow selects previous option', async () => { 64 - const result = prompts.select({ 65 - message: 'foo', 66 - options: [{ value: 'opt0' }, { value: 'opt1' }], 67 - input, 68 - output, 69 - }); 70 - 71 - input.emit('keypress', '', { name: 'down' }); 72 - input.emit('keypress', '', { name: 'up' }); 73 - input.emit('keypress', '', { name: 'return' }); 74 - 75 - const value = await result; 76 - 77 - expect(value).toBe('opt0'); 78 - expect(output.buffer).toMatchSnapshot(); 79 - }); 80 - 81 - test('can cancel', async () => { 82 - const result = prompts.select({ 83 - message: 'foo', 84 - options: [{ value: 'opt0' }, { value: 'opt1' }], 85 - input, 86 - output, 87 - }); 88 - 89 - input.emit('keypress', 'escape', { name: 'escape' }); 90 - 91 - const value = await result; 92 - 93 - expect(prompts.isCancel(value)).toBe(true); 94 - expect(output.buffer).toMatchSnapshot(); 95 - }); 96 - 97 - test('renders option labels', async () => { 98 - const result = prompts.select({ 99 - message: 'foo', 100 - options: [ 101 - { value: 'opt0', label: 'Option 0' }, 102 - { value: 'opt1', label: 'Option 1' }, 103 - ], 104 - input, 105 - output, 106 - }); 107 - 108 - input.emit('keypress', '', { name: 'return' }); 109 - 110 - const value = await result; 111 - 112 - expect(value).toBe('opt0'); 113 - expect(output.buffer).toMatchSnapshot(); 114 - }); 115 - 116 - test('renders option hints', async () => { 117 - const result = prompts.select({ 118 - message: 'foo', 119 - options: [ 120 - { value: 'opt0', hint: 'Hint 0' }, 121 - { value: 'opt1', hint: 'Hint 1' }, 122 - ], 123 - input, 124 - output, 125 - }); 126 - 127 - input.emit('keypress', '', { name: 'return' }); 128 - 129 - const value = await result; 130 - 131 - expect(value).toBe('opt0'); 132 - expect(output.buffer).toMatchSnapshot(); 133 - }); 134 - 135 - test('can be aborted by a signal', async () => { 136 - const controller = new AbortController(); 137 - const result = prompts.select({ 138 - message: 'foo', 139 - options: [{ value: 'opt0' }, { value: 'opt1' }], 140 - input, 141 - output, 142 - signal: controller.signal, 143 - }); 144 - 145 - controller.abort(); 146 - const value = await result; 147 - expect(prompts.isCancel(value)).toBe(true); 148 - expect(output.buffer).toMatchSnapshot(); 149 - }); 150 - 151 - test('renders disabled options', async () => { 152 - const result = prompts.select({ 153 - message: 'foo', 154 - options: [ 155 - { value: 'opt0', label: 'Option 0', disabled: true }, 156 - { value: 'opt1', label: 'Option 1' }, 157 - { value: 'opt2', label: 'Option 2', disabled: true, hint: 'Hint 2' }, 158 - ], 159 - input, 160 - output, 161 - }); 162 - 163 - input.emit('keypress', '', { name: 'return' }); 164 - 165 - const value = await result; 166 - 167 - expect(value).toBe('opt1'); 168 - expect(output.buffer).toMatchSnapshot(); 169 - }); 170 - 171 - test('wraps long results', async () => { 172 - output.columns = 40; 173 - 174 - const result = prompts.select({ 175 - message: 'foo', 176 - options: [ 177 - { 178 - value: 'opt0', 179 - label: 'foo '.repeat(30).trim(), 180 - }, 181 - { value: 'opt1', label: 'Option 1' }, 182 - ], 183 - input, 184 - output, 185 - }); 186 - 187 - input.emit('keypress', '', { name: 'return' }); 188 - 189 - await result; 190 - 191 - expect(output.buffer).toMatchSnapshot(); 192 - }); 193 - 194 - test('wraps long cancelled message', async () => { 195 - output.columns = 40; 196 - 197 - const result = prompts.select({ 198 - message: 'foo', 199 - options: [ 200 - { 201 - value: 'opt0', 202 - label: 'foo '.repeat(30).trim(), 203 - }, 204 - { value: 'opt1', label: 'Option 1' }, 205 - ], 206 - input, 207 - output, 208 - }); 209 - 210 - input.emit('keypress', 'escape', { name: 'escape' }); 211 - 212 - await result; 213 - 214 - expect(output.buffer).toMatchSnapshot(); 215 - }); 216 - 217 - test('wraps long messages', async () => { 218 - output.columns = 40; 219 - 220 - const result = prompts.select({ 221 - message: 'foo '.repeat(20).trim(), 222 - options: [{ value: 'opt0' }, { value: 'opt1' }], 223 - input, 224 - output, 225 - }); 226 - 227 - input.emit('keypress', '', { name: 'return' }); 228 - 229 - const value = await result; 230 - 231 - expect(value).toEqual('opt0'); 232 - expect(output.buffer).toMatchSnapshot(); 233 - }); 234 - 235 - test('renders multi-line option labels', async () => { 236 - const result = prompts.select({ 237 - message: 'foo', 238 - options: [ 239 - { value: 'opt0', label: 'Option 0\nwith multiple lines' }, 240 - { value: 'opt1', label: 'Option 1' }, 241 - ], 242 - input, 243 - output, 244 - }); 245 - 246 - input.emit('keypress', '', { name: 'down' }); 247 - input.emit('keypress', '', { name: 'return' }); 248 - 249 - await result; 250 - 251 - expect(output.buffer).toMatchSnapshot(); 252 - }); 253 - 254 - test('handles mixed size re-renders', async () => { 255 - output.rows = 10; 256 - 257 - const result = prompts.select({ 258 - message: 'Whatever', 259 - options: [ 260 - { 261 - value: 'longopt', 262 - label: Array.from({ length: 8 }, () => 'Long Option').join('\n'), 263 - }, 264 - ...Array.from({ length: 4 }, (_, i) => ({ 265 - value: `opt${i}`, 266 - label: `Option ${i}`, 267 - })), 268 - ], 269 - input, 270 - output, 271 - }); 272 - 273 - input.emit('keypress', '', { name: 'up' }); 274 - input.emit('keypress', '', { name: 'return' }); 275 - 276 - await result; 277 - 278 - expect(output.buffer).toMatchSnapshot(); 279 - }); 280 - 281 - test('correctly limits options when message wraps to multiple lines', async () => { 282 - // Simulate a narrow terminal that forces the message to wrap 283 - output.columns = 30; 284 - output.rows = 12; 285 - 286 - const result = prompts.select({ 287 - // Long message that will wrap to multiple lines in a 30-column terminal 288 - message: 'This is a very long message that will wrap to multiple lines', 289 - options: Array.from({ length: 10 }, (_, i) => ({ 290 - value: `opt${i}`, 291 - label: `Option ${i}`, 292 - })), 293 - input, 294 - output, 295 - }); 296 - 297 - // Scroll down through options to trigger the bug scenario 298 - input.emit('keypress', '', { name: 'down' }); 299 - input.emit('keypress', '', { name: 'down' }); 300 - input.emit('keypress', '', { name: 'down' }); 301 - input.emit('keypress', '', { name: 'down' }); 302 - input.emit('keypress', '', { name: 'return' }); 303 - 304 - const value = await result; 305 - 306 - expect(value).toBe('opt4'); 307 - expect(output.buffer).toMatchSnapshot(); 308 - }); 309 - 310 - test('withGuide: false removes guide', async () => { 311 - const result = prompts.select({ 312 - message: 'foo', 313 - options: [{ value: 'opt0' }, { value: 'opt1' }], 314 - withGuide: false, 315 - input, 316 - output, 317 - }); 318 - 319 - input.emit('keypress', '', { name: 'return' }); 320 - 321 - await result; 322 - 323 - expect(output.buffer).toMatchSnapshot(); 324 - }); 325 - 326 - test('global withGuide: false removes guide', async () => { 327 - updateSettings({ withGuide: false }); 328 - 329 - const result = prompts.select({ 330 - message: 'foo', 331 - options: [{ value: 'opt0' }, { value: 'opt1' }], 332 - input, 333 - output, 334 - }); 335 - 336 - input.emit('keypress', '', { name: 'return' }); 337 - 338 - await result; 339 - 340 - expect(output.buffer).toMatchSnapshot(); 341 - }); 342 - 343 - test('correctly limits options with explicit multiline message', async () => { 344 - output.rows = 12; 345 - 346 - const result = prompts.select({ 347 - // Explicit multiline message 348 - message: 'Choose an option:\nLine 2 of the message\nLine 3 of the message', 349 - options: Array.from({ length: 10 }, (_, i) => ({ 350 - value: `opt${i}`, 351 - label: `Option ${i}`, 352 - })), 353 - input, 354 - output, 355 - }); 356 - 357 - // Scroll down to test that options don't overflow 358 - input.emit('keypress', '', { name: 'down' }); 359 - input.emit('keypress', '', { name: 'down' }); 360 - input.emit('keypress', '', { name: 'down' }); 361 - input.emit('keypress', '', { name: 'return' }); 362 - 363 - const value = await result; 364 - 365 - expect(value).toBe('opt3'); 366 - expect(output.buffer).toMatchSnapshot(); 367 - }); 368 - });
+64 -75
packages/prompts/test/spinner.test.ts packages/prompts/src/spinner.test.ts
··· 1 1 import { EventEmitter } from 'node:stream'; 2 2 import { styleText } from 'node:util'; 3 3 import { getColumns, updateSettings } from '@clack/core'; 4 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 5 - import * as prompts from '../src/index.js'; 6 - import { MockWritable } from './test-utils.js'; 4 + import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; 5 + import * as prompts from './index.js'; 6 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 7 7 8 8 describe.each(['true', 'false'])('spinner (isCI = %s)', (isCI) => { 9 - let originalCI: string | undefined; 10 - let output: MockWritable; 11 - 12 - beforeAll(() => { 13 - originalCI = process.env.CI; 14 - process.env.CI = isCI; 15 - }); 16 - 17 - afterAll(() => { 18 - process.env.CI = originalCI; 19 - }); 9 + let mocks: Mocks<{ output: true }>; 20 10 21 11 beforeEach(() => { 22 - output = new MockWritable(); 12 + mocks = createMocks({ output: true, env: { CI: isCI } }); 23 13 vi.useFakeTimers(); 24 14 }); 25 15 26 16 afterEach(() => { 27 17 vi.useRealTimers(); 28 - vi.restoreAllMocks(); 29 18 updateSettings({ withGuide: true }); 30 19 }); 31 20 32 21 test('returns spinner API', () => { 33 - const api = prompts.spinner({ output }); 22 + const api = prompts.spinner({ output: mocks.output }); 34 23 35 24 expect(api.stop).toBeTypeOf('function'); 36 25 expect(api.start).toBeTypeOf('function'); ··· 39 28 40 29 describe('start', () => { 41 30 test('renders frames at interval', () => { 42 - const result = prompts.spinner({ output }); 31 + const result = prompts.spinner({ output: mocks.output }); 43 32 44 33 result.start(); 45 34 ··· 50 39 51 40 result.stop(); 52 41 53 - expect(output.buffer).toMatchSnapshot(); 42 + expect(mocks.output.buffer).toMatchSnapshot(); 54 43 }); 55 44 56 45 test('renders message', () => { 57 - const result = prompts.spinner({ output }); 46 + const result = prompts.spinner({ output: mocks.output }); 58 47 59 48 result.start('foo'); 60 49 ··· 62 51 63 52 result.stop(); 64 53 65 - expect(output.buffer).toMatchSnapshot(); 54 + expect(mocks.output.buffer).toMatchSnapshot(); 66 55 }); 67 56 68 57 test('renders timer when indicator is "timer"', () => { 69 - const result = prompts.spinner({ output, indicator: 'timer' }); 58 + const result = prompts.spinner({ output: mocks.output, indicator: 'timer' }); 70 59 71 60 result.start(); 72 61 ··· 74 63 75 64 result.stop(); 76 65 77 - expect(output.buffer).toMatchSnapshot(); 66 + expect(mocks.output.buffer).toMatchSnapshot(); 78 67 }); 79 68 80 69 test('handles wrapping', () => { 81 - const columns = getColumns(output); 82 - const result = prompts.spinner({ output }); 70 + const columns = getColumns(mocks.output); 71 + const result = prompts.spinner({ output: mocks.output }); 83 72 84 73 result.start('x'.repeat(columns + 10)); 85 74 ··· 87 76 88 77 result.stop('stopped'); 89 78 90 - expect(output.buffer).toMatchSnapshot(); 79 + expect(mocks.output.buffer).toMatchSnapshot(); 91 80 }); 92 81 93 82 test('handles multi-line messages', () => { 94 - const result = prompts.spinner({ output }); 83 + const result = prompts.spinner({ output: mocks.output }); 95 84 96 85 result.start('foo\nbar\nbaz'); 97 86 ··· 99 88 100 89 result.stop(); 101 90 102 - expect(output.buffer).toMatchSnapshot(); 91 + expect(mocks.output.buffer).toMatchSnapshot(); 103 92 }); 104 93 }); 105 94 106 95 describe('stop', () => { 107 96 test('renders submit symbol and stops spinner', () => { 108 - const result = prompts.spinner({ output }); 97 + const result = prompts.spinner({ output: mocks.output }); 109 98 110 99 result.start(); 111 100 ··· 115 104 116 105 vi.advanceTimersByTime(80); 117 106 118 - expect(output.buffer).toMatchSnapshot(); 107 + expect(mocks.output.buffer).toMatchSnapshot(); 119 108 }); 120 109 121 110 test('renders cancel symbol when calling cancel()', () => { 122 - const result = prompts.spinner({ output }); 111 + const result = prompts.spinner({ output: mocks.output }); 123 112 124 113 result.start(); 125 114 ··· 127 116 128 117 result.cancel(); 129 118 130 - expect(output.buffer).toMatchSnapshot(); 119 + expect(mocks.output.buffer).toMatchSnapshot(); 131 120 }); 132 121 133 122 test('renders error symbol when calling error()', () => { 134 - const result = prompts.spinner({ output }); 123 + const result = prompts.spinner({ output: mocks.output }); 135 124 136 125 result.start(); 137 126 ··· 139 128 140 129 result.error(); 141 130 142 - expect(output.buffer).toMatchSnapshot(); 131 + expect(mocks.output.buffer).toMatchSnapshot(); 143 132 }); 144 133 145 134 test('renders message', () => { 146 - const result = prompts.spinner({ output }); 135 + const result = prompts.spinner({ output: mocks.output }); 147 136 148 137 result.start(); 149 138 ··· 151 140 152 141 result.stop('foo'); 153 142 154 - expect(output.buffer).toMatchSnapshot(); 143 + expect(mocks.output.buffer).toMatchSnapshot(); 155 144 }); 156 145 157 146 test('renders message without removing dots', () => { 158 - const result = prompts.spinner({ output }); 147 + const result = prompts.spinner({ output: mocks.output }); 159 148 160 149 result.start(); 161 150 ··· 163 152 164 153 result.stop('foo.'); 165 154 166 - expect(output.buffer).toMatchSnapshot(); 155 + expect(mocks.output.buffer).toMatchSnapshot(); 167 156 }); 168 157 169 158 test('renders message when cancelling', () => { 170 - const result = prompts.spinner({ output }); 159 + const result = prompts.spinner({ output: mocks.output }); 171 160 172 161 result.start(); 173 162 ··· 175 164 176 165 result.cancel('too dizzy — spinning cancelled'); 177 166 178 - expect(output.buffer).toMatchSnapshot(); 167 + expect(mocks.output.buffer).toMatchSnapshot(); 179 168 }); 180 169 181 170 test('renders message when erroring', () => { 182 - const result = prompts.spinner({ output }); 171 + const result = prompts.spinner({ output: mocks.output }); 183 172 184 173 result.start(); 185 174 ··· 187 176 188 177 result.error('error: spun too fast!'); 189 178 190 - expect(output.buffer).toMatchSnapshot(); 179 + expect(mocks.output.buffer).toMatchSnapshot(); 191 180 }); 192 181 193 182 test('does not throw if called before start', () => { 194 - const result = prompts.spinner({ output }); 183 + const result = prompts.spinner({ output: mocks.output }); 195 184 196 185 expect(() => result.stop()).not.toThrow(); 197 186 }); ··· 199 188 200 189 describe('message', () => { 201 190 test('sets message for next frame', () => { 202 - const result = prompts.spinner({ output }); 191 + const result = prompts.spinner({ output: mocks.output }); 203 192 204 193 result.start(); 205 194 ··· 211 200 212 201 result.stop(); 213 202 214 - expect(output.buffer).toMatchSnapshot(); 203 + expect(mocks.output.buffer).toMatchSnapshot(); 215 204 }); 216 205 }); 217 206 218 207 describe('indicator customization', () => { 219 208 test('custom frames', () => { 220 - const result = prompts.spinner({ output, frames: ['🐴', '🦋', '🐙', '🐶'] }); 209 + const result = prompts.spinner({ output: mocks.output, frames: ['🐴', '🦋', '🐙', '🐶'] }); 221 210 222 211 result.start(); 223 212 ··· 228 217 229 218 result.stop(); 230 219 231 - expect(output.buffer).toMatchSnapshot(); 220 + expect(mocks.output.buffer).toMatchSnapshot(); 232 221 }); 233 222 234 223 test('custom frames with lots of frame have consistent ellipsis display', () => { 235 - const result = prompts.spinner({ output, frames: Object.keys(Array(10).fill(0)) }); 224 + const result = prompts.spinner({ output: mocks.output, frames: Object.keys(Array(10).fill(0)) }); 236 225 237 226 result.start(); 238 227 ··· 242 231 243 232 result.stop(); 244 233 245 - expect(output.buffer).toMatchSnapshot(); 234 + expect(mocks.output.buffer).toMatchSnapshot(); 246 235 }); 247 236 248 237 test('custom delay', () => { 249 - const result = prompts.spinner({ output, delay: 200 }); 238 + const result = prompts.spinner({ output: mocks.output, delay: 200 }); 250 239 251 240 result.start(); 252 241 ··· 257 246 258 247 result.stop(); 259 248 260 - expect(output.buffer).toMatchSnapshot(); 249 + expect(mocks.output.buffer).toMatchSnapshot(); 261 250 }); 262 251 263 252 test('custom frame style', () => { 264 - const result = prompts.spinner({ output, styleFrame: (text) => styleText('red', text) }); 253 + const result = prompts.spinner({ output: mocks.output, styleFrame: (text) => styleText('red', text) }); 265 254 266 255 result.start(); 267 256 ··· 271 260 272 261 result.stop(); 273 262 274 - expect(output.buffer).toMatchSnapshot(); 263 + expect(mocks.output.buffer).toMatchSnapshot(); 275 264 }); 276 265 }); 277 266 ··· 297 286 }); 298 287 299 288 test('uses default cancel message', () => { 300 - const result = prompts.spinner({ output }); 289 + const result = prompts.spinner({ output: mocks.output }); 301 290 result.start('Test operation'); 302 291 303 292 processEmitter.emit('SIGINT'); 304 293 305 - expect(output.buffer).toMatchSnapshot(); 294 + expect(mocks.output.buffer).toMatchSnapshot(); 306 295 }); 307 296 308 297 test('uses custom cancel message when provided directly', () => { 309 298 const result = prompts.spinner({ 310 - output, 299 + output: mocks.output, 311 300 cancelMessage: 'Custom cancel message', 312 301 }); 313 302 result.start('Test operation'); 314 303 315 304 processEmitter.emit('SIGINT'); 316 305 317 - expect(output.buffer).toMatchSnapshot(); 306 + expect(mocks.output.buffer).toMatchSnapshot(); 318 307 }); 319 308 320 309 test('uses custom error message when provided directly', () => { 321 310 const result = prompts.spinner({ 322 - output, 311 + output: mocks.output, 323 312 errorMessage: 'Custom error message', 324 313 }); 325 314 result.start('Test operation'); 326 315 327 316 processEmitter.emit('exit', 2); 328 317 329 - expect(output.buffer).toMatchSnapshot(); 318 + expect(mocks.output.buffer).toMatchSnapshot(); 330 319 }); 331 320 332 321 test('uses global custom cancel message from settings', () => { ··· 336 325 // Set custom message 337 326 prompts.settings.messages.cancel = 'Global cancel message'; 338 327 339 - const result = prompts.spinner({ output }); 328 + const result = prompts.spinner({ output: mocks.output }); 340 329 result.start('Test operation'); 341 330 342 331 processEmitter.emit('SIGINT'); 343 332 344 - expect(output.buffer).toMatchSnapshot(); 333 + expect(mocks.output.buffer).toMatchSnapshot(); 345 334 } finally { 346 335 // Reset to original 347 336 prompts.settings.messages.cancel = originalCancelMessage; ··· 356 345 // Set custom message 357 346 prompts.settings.messages.error = 'Global error message'; 358 347 359 - const result = prompts.spinner({ output }); 348 + const result = prompts.spinner({ output: mocks.output }); 360 349 result.start('Test operation'); 361 350 362 351 processEmitter.emit('exit', 2); 363 352 364 - expect(output.buffer).toMatchSnapshot(); 353 + expect(mocks.output.buffer).toMatchSnapshot(); 365 354 } finally { 366 355 // Reset to original 367 356 prompts.settings.messages.error = originalErrorMessage; ··· 377 366 prompts.settings.messages.error = 'Global error message'; 378 367 379 368 const result = prompts.spinner({ 380 - output, 369 + output: mocks.output, 381 370 errorMessage: 'Spinner error message', 382 371 }); 383 372 result.start('Test operation'); 384 373 385 374 processEmitter.emit('exit', 2); 386 - expect(output.buffer).toMatchSnapshot(); 375 + expect(mocks.output.buffer).toMatchSnapshot(); 387 376 } finally { 388 377 // Reset to original values 389 378 prompts.settings.messages.error = originalErrorMessage; ··· 399 388 prompts.settings.messages.cancel = 'Global cancel message'; 400 389 401 390 const result = prompts.spinner({ 402 - output, 391 + output: mocks.output, 403 392 cancelMessage: 'Spinner cancel message', 404 393 }); 405 394 result.start('Test operation'); 406 395 407 396 processEmitter.emit('SIGINT'); 408 - expect(output.buffer).toMatchSnapshot(); 397 + expect(mocks.output.buffer).toMatchSnapshot(); 409 398 } finally { 410 399 // Reset to original values 411 400 prompts.settings.messages.cancel = originalCancelMessage; ··· 416 405 test('can be aborted by a signal', async () => { 417 406 const controller = new AbortController(); 418 407 const result = prompts.spinner({ 419 - output, 408 + output: mocks.output, 420 409 signal: controller.signal, 421 410 }); 422 411 ··· 424 413 425 414 controller.abort(); 426 415 427 - expect(output.buffer).toMatchSnapshot(); 416 + expect(mocks.output.buffer).toMatchSnapshot(); 428 417 }); 429 418 430 419 test('withGuide: false removes guide', () => { 431 - const result = prompts.spinner({ output, withGuide: false }); 420 + const result = prompts.spinner({ output: mocks.output, withGuide: false }); 432 421 433 422 result.start('foo'); 434 423 ··· 436 425 437 426 result.stop(); 438 427 439 - expect(output.buffer).toMatchSnapshot(); 428 + expect(mocks.output.buffer).toMatchSnapshot(); 440 429 }); 441 430 442 431 test('global withGuide: false removes guide', () => { 443 432 updateSettings({ withGuide: false }); 444 433 445 - const result = prompts.spinner({ output }); 434 + const result = prompts.spinner({ output: mocks.output }); 446 435 447 436 result.start('foo'); 448 437 ··· 450 439 451 440 result.stop(); 452 441 453 - expect(output.buffer).toMatchSnapshot(); 442 + expect(mocks.output.buffer).toMatchSnapshot(); 454 443 }); 455 444 456 445 describe('clear', () => { 457 446 test('stops and clears the spinner from the output', () => { 458 - const result = prompts.spinner({ output }); 447 + const result = prompts.spinner({ output: mocks.output }); 459 448 460 449 result.start('Loading'); 461 450 ··· 463 452 464 453 result.clear(); 465 454 466 - expect(output.buffer).toMatchSnapshot(); 455 + expect(mocks.output.buffer).toMatchSnapshot(); 467 456 }); 468 457 }); 469 458 });
+87 -103
packages/prompts/test/task-log.test.ts packages/prompts/src/task-log.test.ts
··· 1 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 2 - import * as prompts from '../src/index.js'; 3 - import { MockReadable, MockWritable } from './test-utils.js'; 1 + import { beforeEach, describe, expect, test } from 'vitest'; 2 + import * as prompts from './index.js'; 3 + import { createMocks, type Mocks } from '@bomb.sh/tools/test-utils'; 4 4 5 5 describe.each(['true', 'false'])('taskLog (isCI = %s)', (isCI) => { 6 - let originalCI: string | undefined; 7 - let output: MockWritable; 8 - let input: MockReadable; 9 - 10 - beforeAll(() => { 11 - originalCI = process.env.CI; 12 - process.env.CI = isCI; 13 - }); 14 - 15 - afterAll(() => { 16 - process.env.CI = originalCI; 17 - }); 6 + let mocks: Mocks<{ input: true; output: true }>; 18 7 19 8 beforeEach(() => { 20 - output = new MockWritable(); 21 - output.isTTY = isCI === 'false'; 22 - input = new MockReadable(); 23 - }); 24 - 25 - afterEach(() => { 26 - vi.restoreAllMocks(); 9 + mocks = createMocks({ input: true, output: true, env: { CI: isCI } }); 10 + mocks.output.isTTY = isCI === 'false'; 27 11 }); 28 12 29 13 test('writes message header', () => { 30 14 prompts.taskLog({ 31 - input, 32 - output, 15 + input: mocks.input, 16 + output: mocks.output, 33 17 title: 'foo', 34 18 }); 35 19 36 - expect(output.buffer).toMatchSnapshot(); 20 + expect(mocks.output.buffer).toMatchSnapshot(); 37 21 }); 38 22 39 23 describe('message', () => { 40 24 test('can write line by line', () => { 41 25 const log = prompts.taskLog({ 42 - input, 43 - output, 26 + input: mocks.input, 27 + output: mocks.output, 44 28 title: 'foo', 45 29 }); 46 30 47 31 log.message('line 0'); 48 32 log.message('line 1'); 49 33 50 - expect(output.buffer).toMatchSnapshot(); 34 + expect(mocks.output.buffer).toMatchSnapshot(); 51 35 }); 52 36 53 37 test('can write multiple lines', () => { 54 38 const log = prompts.taskLog({ 55 - input, 56 - output, 39 + input: mocks.input, 40 + output: mocks.output, 57 41 title: 'foo', 58 42 }); 59 43 60 44 log.message('line 0\nline 1'); 61 45 62 - expect(output.buffer).toMatchSnapshot(); 46 + expect(mocks.output.buffer).toMatchSnapshot(); 63 47 }); 64 48 65 49 test('enforces limit if set', () => { 66 50 const log = prompts.taskLog({ 67 - input, 68 - output, 51 + input: mocks.input, 52 + output: mocks.output, 69 53 title: 'foo', 70 54 limit: 2, 71 55 }); ··· 74 58 log.message('line 1'); 75 59 log.message('line 2'); 76 60 77 - expect(output.buffer).toMatchSnapshot(); 61 + expect(mocks.output.buffer).toMatchSnapshot(); 78 62 }); 79 63 80 64 test('raw = true appends message text until newline', async () => { 81 65 const log = prompts.taskLog({ 82 - input, 83 - output, 66 + input: mocks.input, 67 + output: mocks.output, 84 68 title: 'foo', 85 69 }); 86 70 ··· 88 72 log.message('still line 0', { raw: true }); 89 73 log.message('\nline 1', { raw: true }); 90 74 91 - expect(output.buffer).toMatchSnapshot(); 75 + expect(mocks.output.buffer).toMatchSnapshot(); 92 76 }); 93 77 94 78 test('raw = true works when mixed with non-raw messages', async () => { 95 79 const log = prompts.taskLog({ 96 - input, 97 - output, 80 + input: mocks.input, 81 + output: mocks.output, 98 82 title: 'foo', 99 83 }); 100 84 ··· 102 86 log.message('still line 0', { raw: true }); 103 87 log.message('line 1'); 104 88 105 - expect(output.buffer).toMatchSnapshot(); 89 + expect(mocks.output.buffer).toMatchSnapshot(); 106 90 }); 107 91 108 92 test('raw = true works when started with non-raw messages', async () => { 109 93 const log = prompts.taskLog({ 110 - input, 111 - output, 94 + input: mocks.input, 95 + output: mocks.output, 112 96 title: 'foo', 113 97 }); 114 98 ··· 116 100 log.message('line 1', { raw: true }); 117 101 log.message('still line 1', { raw: true }); 118 102 119 - expect(output.buffer).toMatchSnapshot(); 103 + expect(mocks.output.buffer).toMatchSnapshot(); 120 104 }); 121 105 122 106 test('prints empty lines', async () => { 123 107 const log = prompts.taskLog({ 124 - input, 125 - output, 108 + input: mocks.input, 109 + output: mocks.output, 126 110 title: 'foo', 127 111 }); 128 112 ··· 130 114 log.message(''); 131 115 log.message('line 3'); 132 116 133 - expect(output.buffer).toMatchSnapshot(); 117 + expect(mocks.output.buffer).toMatchSnapshot(); 134 118 }); 135 119 136 120 test('destructive ansi codes are stripped', async () => { 137 121 const log = prompts.taskLog({ 138 - input, 139 - output, 122 + input: mocks.input, 123 + output: mocks.output, 140 124 title: 'foo', 141 125 }); 142 126 ··· 144 128 log.message('line 2\x1b[2K bad ansi!'); 145 129 log.message('line 3'); 146 130 147 - expect(output.buffer).toMatchSnapshot(); 131 + expect(mocks.output.buffer).toMatchSnapshot(); 148 132 }); 149 133 }); 150 134 151 135 describe('error', () => { 152 136 test('renders output with message', () => { 153 137 const log = prompts.taskLog({ 154 - input, 155 - output, 138 + input: mocks.input, 139 + output: mocks.output, 156 140 title: 'foo', 157 141 }); 158 142 ··· 161 145 162 146 log.error('some error!'); 163 147 164 - expect(output.buffer).toMatchSnapshot(); 148 + expect(mocks.output.buffer).toMatchSnapshot(); 165 149 }); 166 150 167 151 test('clears output if showLog = false', () => { 168 152 const log = prompts.taskLog({ 169 - input, 170 - output, 153 + input: mocks.input, 154 + output: mocks.output, 171 155 title: 'foo', 172 156 }); 173 157 ··· 176 160 177 161 log.error('some error!', { showLog: false }); 178 162 179 - expect(output.buffer).toMatchSnapshot(); 163 + expect(mocks.output.buffer).toMatchSnapshot(); 180 164 }); 181 165 }); 182 166 183 167 describe('success', () => { 184 168 test('clears output and renders message', () => { 185 169 const log = prompts.taskLog({ 186 - input, 187 - output, 170 + input: mocks.input, 171 + output: mocks.output, 188 172 title: 'foo', 189 173 }); 190 174 ··· 193 177 194 178 log.success('success!'); 195 179 196 - expect(output.buffer).toMatchSnapshot(); 180 + expect(mocks.output.buffer).toMatchSnapshot(); 197 181 }); 198 182 199 183 test('renders output if showLog = true', () => { 200 184 const log = prompts.taskLog({ 201 - input, 202 - output, 185 + input: mocks.input, 186 + output: mocks.output, 203 187 title: 'foo', 204 188 }); 205 189 ··· 208 192 209 193 log.success('success!', { showLog: true }); 210 194 211 - expect(output.buffer).toMatchSnapshot(); 195 + expect(mocks.output.buffer).toMatchSnapshot(); 212 196 }); 213 197 }); 214 198 ··· 216 200 describe.each(['error', 'success'] as const)('%s', (method) => { 217 201 test('retainLog = true outputs full log', () => { 218 202 const log = prompts.taskLog({ 219 - input, 220 - output, 203 + input: mocks.input, 204 + output: mocks.output, 221 205 title: 'foo', 222 206 retainLog: true, 223 207 }); ··· 228 212 229 213 log[method]('woo!', { showLog: true }); 230 214 231 - expect(output.buffer).toMatchSnapshot(); 215 + expect(mocks.output.buffer).toMatchSnapshot(); 232 216 }); 233 217 234 218 test('retainLog = true outputs full log with limit', () => { 235 219 const log = prompts.taskLog({ 236 - input, 237 - output, 220 + input: mocks.input, 221 + output: mocks.output, 238 222 title: 'foo', 239 223 retainLog: true, 240 224 limit: 2, ··· 246 230 247 231 log[method]('woo!', { showLog: true }); 248 232 249 - expect(output.buffer).toMatchSnapshot(); 233 + expect(mocks.output.buffer).toMatchSnapshot(); 250 234 }); 251 235 252 236 test('retainLog = false outputs full log without limit', () => { 253 237 const log = prompts.taskLog({ 254 - input, 255 - output, 238 + input: mocks.input, 239 + output: mocks.output, 256 240 title: 'foo', 257 241 retainLog: false, 258 242 }); ··· 263 247 264 248 log[method]('woo!', { showLog: true }); 265 249 266 - expect(output.buffer).toMatchSnapshot(); 250 + expect(mocks.output.buffer).toMatchSnapshot(); 267 251 }); 268 252 269 253 test('retainLog = false outputs limited log with limit', () => { 270 254 const log = prompts.taskLog({ 271 - input, 272 - output, 255 + input: mocks.input, 256 + output: mocks.output, 273 257 title: 'foo', 274 258 retainLog: false, 275 259 limit: 2, ··· 281 265 282 266 log[method]('woo!', { showLog: true }); 283 267 284 - expect(output.buffer).toMatchSnapshot(); 268 + expect(mocks.output.buffer).toMatchSnapshot(); 285 269 }); 286 270 287 271 test('outputs limited log with limit by default', () => { 288 272 const log = prompts.taskLog({ 289 - input, 290 - output, 273 + input: mocks.input, 274 + output: mocks.output, 291 275 title: 'foo', 292 276 limit: 2, 293 277 }); ··· 298 282 299 283 log[method]('woo!', { showLog: true }); 300 284 301 - expect(output.buffer).toMatchSnapshot(); 285 + expect(mocks.output.buffer).toMatchSnapshot(); 302 286 }); 303 287 }); 304 288 }); ··· 307 291 test('can render multiple groups of equal size', async () => { 308 292 const log = prompts.taskLog({ 309 293 title: 'Some log', 310 - input, 311 - output, 294 + input: mocks.input, 295 + output: mocks.output, 312 296 }); 313 297 const group0 = log.group('Group 0'); 314 298 const group1 = log.group('Group 1'); ··· 318 302 group1.message(`Group 1 line ${i}`); 319 303 } 320 304 321 - expect(output.buffer).toMatchSnapshot(); 305 + expect(mocks.output.buffer).toMatchSnapshot(); 322 306 }); 323 307 324 308 test('can render multiple groups of different sizes', async () => { 325 309 const log = prompts.taskLog({ 326 310 title: 'Some log', 327 - input, 328 - output, 311 + input: mocks.input, 312 + output: mocks.output, 329 313 }); 330 314 const group0 = log.group('Group 0'); 331 315 const group1 = log.group('Group 1'); ··· 337 321 group1.message(`Group 1 line ${i}`); 338 322 } 339 323 340 - expect(output.buffer).toMatchSnapshot(); 324 + expect(mocks.output.buffer).toMatchSnapshot(); 341 325 }); 342 326 343 327 test('renders success state', async () => { 344 328 const log = prompts.taskLog({ 345 329 title: 'Some log', 346 - input, 347 - output, 330 + input: mocks.input, 331 + output: mocks.output, 348 332 }); 349 333 const group = log.group('Group 0'); 350 334 group.message('Group 0 line 0'); 351 335 group.success('Group success!'); 352 336 353 - expect(output.buffer).toMatchSnapshot(); 337 + expect(mocks.output.buffer).toMatchSnapshot(); 354 338 }); 355 339 356 340 test('renders error state', async () => { 357 341 const log = prompts.taskLog({ 358 342 title: 'Some log', 359 - input, 360 - output, 343 + input: mocks.input, 344 + output: mocks.output, 361 345 }); 362 346 const group = log.group('Group 0'); 363 347 group.message('Group 0 line 0'); 364 348 group.error('Group error!'); 365 349 366 - expect(output.buffer).toMatchSnapshot(); 350 + expect(mocks.output.buffer).toMatchSnapshot(); 367 351 }); 368 352 369 353 test('applies limit per group', async () => { 370 354 const log = prompts.taskLog({ 371 355 title: 'Some log', 372 - input, 373 - output, 356 + input: mocks.input, 357 + output: mocks.output, 374 358 limit: 2, 375 359 }); 376 360 const group0 = log.group('Group 0'); ··· 381 365 group1.message(`Group 1 line ${i}`); 382 366 } 383 367 384 - expect(output.buffer).toMatchSnapshot(); 368 + expect(mocks.output.buffer).toMatchSnapshot(); 385 369 }); 386 370 387 371 test('renders group success state', async () => { 388 372 const log = prompts.taskLog({ 389 373 title: 'Some log', 390 - input, 391 - output, 374 + input: mocks.input, 375 + output: mocks.output, 392 376 }); 393 377 const group = log.group('Group 0'); 394 378 group.message('Group 0 line 0'); 395 379 group.success('Group success!'); 396 380 397 - expect(output.buffer).toMatchSnapshot(); 381 + expect(mocks.output.buffer).toMatchSnapshot(); 398 382 }); 399 383 400 384 test('renders group error state', async () => { 401 385 const log = prompts.taskLog({ 402 386 title: 'Some log', 403 - input, 404 - output, 387 + input: mocks.input, 388 + output: mocks.output, 405 389 }); 406 390 const group = log.group('Group 0'); 407 391 group.message('Group 0 line 0'); 408 392 group.error('Group error!'); 409 393 410 - expect(output.buffer).toMatchSnapshot(); 394 + expect(mocks.output.buffer).toMatchSnapshot(); 411 395 }); 412 396 413 397 test('showLog shows all groups in order', async () => { 414 398 const log = prompts.taskLog({ 415 399 title: 'Some log', 416 - input, 417 - output, 400 + input: mocks.input, 401 + output: mocks.output, 418 402 }); 419 403 const group0 = log.group('Group 0'); 420 404 const group1 = log.group('Group 1'); ··· 431 415 432 416 log.error('overall error', { showLog: true }); 433 417 434 - expect(output.buffer).toMatchSnapshot(); 418 + expect(mocks.output.buffer).toMatchSnapshot(); 435 419 }); 436 420 437 421 test('handles empty groups', async () => { 438 422 const log = prompts.taskLog({ 439 423 title: 'Some log', 440 - input, 441 - output, 424 + input: mocks.input, 425 + output: mocks.output, 442 426 }); 443 427 const group = log.group('Group 0'); 444 428 445 429 group.success('Group success!'); 446 430 447 - expect(output.buffer).toMatchSnapshot(); 431 + expect(mocks.output.buffer).toMatchSnapshot(); 448 432 }); 449 433 }); 450 434 });
-42
packages/prompts/test/test-utils.ts
··· 1 - import { Readable, Writable } from 'node:stream'; 2 - 3 - export class MockWritable extends Writable { 4 - public buffer: string[] = []; 5 - public isTTY = false; 6 - public columns = 80; 7 - public rows = 20; 8 - 9 - _write( 10 - chunk: any, 11 - _encoding: BufferEncoding, 12 - callback: (error?: Error | null | undefined) => void 13 - ): void { 14 - this.buffer.push(chunk.toString()); 15 - callback(); 16 - } 17 - } 18 - 19 - export class MockReadable extends Readable { 20 - protected _buffer: unknown[] | null = []; 21 - 22 - _read() { 23 - if (this._buffer === null) { 24 - this.push(null); 25 - return; 26 - } 27 - 28 - for (const val of this._buffer) { 29 - this.push(val); 30 - } 31 - 32 - this._buffer = []; 33 - } 34 - 35 - pushValue(val: unknown): void { 36 - this._buffer?.push(val); 37 - } 38 - 39 - close(): void { 40 - this._buffer = null; 41 - } 42 - }
-241
packages/prompts/test/text.test.ts
··· 1 - import { updateSettings } from '@clack/core'; 2 - import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; 3 - import * as prompts from '../src/index.js'; 4 - import { MockReadable, MockWritable } from './test-utils.js'; 5 - 6 - describe.each(['true', 'false'])('text (isCI = %s)', (isCI) => { 7 - let originalCI: string | undefined; 8 - let output: MockWritable; 9 - let input: MockReadable; 10 - 11 - beforeAll(() => { 12 - originalCI = process.env.CI; 13 - process.env.CI = isCI; 14 - }); 15 - 16 - afterAll(() => { 17 - process.env.CI = originalCI; 18 - }); 19 - 20 - beforeEach(() => { 21 - output = new MockWritable(); 22 - input = new MockReadable(); 23 - }); 24 - 25 - afterEach(() => { 26 - vi.restoreAllMocks(); 27 - updateSettings({ withGuide: true }); 28 - }); 29 - 30 - test('renders message', async () => { 31 - const result = prompts.text({ 32 - message: 'foo', 33 - input, 34 - output, 35 - }); 36 - 37 - input.emit('keypress', '', { name: 'return' }); 38 - 39 - await result; 40 - 41 - expect(output.buffer).toMatchSnapshot(); 42 - }); 43 - 44 - test('renders placeholder if set', async () => { 45 - const result = prompts.text({ 46 - message: 'foo', 47 - placeholder: 'bar', 48 - input, 49 - output, 50 - }); 51 - 52 - input.emit('keypress', '', { name: 'return' }); 53 - 54 - const value = await result; 55 - 56 - expect(output.buffer).toMatchSnapshot(); 57 - expect(value).toBe(''); 58 - }); 59 - 60 - test('can cancel', async () => { 61 - const result = prompts.text({ 62 - message: 'foo', 63 - input, 64 - output, 65 - }); 66 - 67 - input.emit('keypress', 'escape', { name: 'escape' }); 68 - 69 - const value = await result; 70 - 71 - expect(prompts.isCancel(value)).toBe(true); 72 - expect(output.buffer).toMatchSnapshot(); 73 - }); 74 - 75 - test('renders cancelled value if one set', async () => { 76 - const result = prompts.text({ 77 - message: 'foo', 78 - input, 79 - output, 80 - }); 81 - 82 - input.emit('keypress', 'x', { name: 'x' }); 83 - input.emit('keypress', 'y', { name: 'y' }); 84 - input.emit('keypress', '', { name: 'escape' }); 85 - 86 - const value = await result; 87 - 88 - expect(prompts.isCancel(value)).toBe(true); 89 - expect(output.buffer).toMatchSnapshot(); 90 - }); 91 - 92 - test('renders submitted value', async () => { 93 - const result = prompts.text({ 94 - message: 'foo', 95 - input, 96 - output, 97 - }); 98 - 99 - input.emit('keypress', 'x', { name: 'x' }); 100 - input.emit('keypress', 'y', { name: 'y' }); 101 - input.emit('keypress', '', { name: 'return' }); 102 - 103 - const value = await result; 104 - 105 - expect(value).toBe('xy'); 106 - expect(output.buffer).toMatchSnapshot(); 107 - }); 108 - 109 - test('defaultValue sets the value but does not render', async () => { 110 - const result = prompts.text({ 111 - message: 'foo', 112 - defaultValue: 'bar', 113 - input, 114 - output, 115 - }); 116 - 117 - input.emit('keypress', '', { name: 'return' }); 118 - 119 - const value = await result; 120 - 121 - expect(value).toBe('bar'); 122 - expect(output.buffer).toMatchSnapshot(); 123 - }); 124 - 125 - test('validation errors render and clear', async () => { 126 - const result = prompts.text({ 127 - message: 'foo', 128 - validate: (val) => (val !== 'xy' ? 'should be xy' : undefined), 129 - input, 130 - output, 131 - }); 132 - 133 - input.emit('keypress', 'x', { name: 'x' }); 134 - input.emit('keypress', '', { name: 'return' }); 135 - input.emit('keypress', 'y', { name: 'y' }); 136 - input.emit('keypress', '', { name: 'return' }); 137 - 138 - const value = await result; 139 - 140 - expect(value).toBe('xy'); 141 - expect(output.buffer).toMatchSnapshot(); 142 - }); 143 - 144 - test('validation errors render and clear (using Error)', async () => { 145 - const result = prompts.text({ 146 - message: 'foo', 147 - validate: (val) => (val !== 'xy' ? new Error('should be xy') : undefined), 148 - input, 149 - output, 150 - }); 151 - 152 - input.emit('keypress', 'x', { name: 'x' }); 153 - input.emit('keypress', '', { name: 'return' }); 154 - input.emit('keypress', 'y', { name: 'y' }); 155 - input.emit('keypress', '', { name: 'return' }); 156 - 157 - const value = await result; 158 - 159 - expect(value).toBe('xy'); 160 - expect(output.buffer).toMatchSnapshot(); 161 - }); 162 - 163 - test('placeholder is not used as value when pressing enter', async () => { 164 - const result = prompts.text({ 165 - message: 'foo', 166 - placeholder: ' (hit Enter to use default)', 167 - defaultValue: 'default-value', 168 - input, 169 - output, 170 - }); 171 - 172 - input.emit('keypress', '', { name: 'return' }); 173 - 174 - const value = await result; 175 - 176 - expect(value).toBe('default-value'); 177 - expect(output.buffer).toMatchSnapshot(); 178 - }); 179 - 180 - test('empty string when no value and no default', async () => { 181 - const result = prompts.text({ 182 - message: 'foo', 183 - placeholder: ' (hit Enter to use default)', 184 - input, 185 - output, 186 - }); 187 - 188 - input.emit('keypress', '', { name: 'return' }); 189 - 190 - const value = await result; 191 - 192 - expect(value).toBe(''); 193 - expect(output.buffer).toMatchSnapshot(); 194 - }); 195 - 196 - test('can be aborted by a signal', async () => { 197 - const controller = new AbortController(); 198 - const result = prompts.text({ 199 - message: 'foo', 200 - input, 201 - output, 202 - signal: controller.signal, 203 - }); 204 - 205 - controller.abort(); 206 - const value = await result; 207 - expect(prompts.isCancel(value)).toBe(true); 208 - expect(output.buffer).toMatchSnapshot(); 209 - }); 210 - 211 - test('withGuide: false removes guide', async () => { 212 - const result = prompts.text({ 213 - message: 'foo', 214 - withGuide: false, 215 - input, 216 - output, 217 - }); 218 - 219 - input.emit('keypress', '', { name: 'return' }); 220 - 221 - await result; 222 - 223 - expect(output.buffer).toMatchSnapshot(); 224 - }); 225 - 226 - test('global withGuide: false removes guide', async () => { 227 - updateSettings({ withGuide: false }); 228 - 229 - const result = prompts.text({ 230 - message: 'foo', 231 - input, 232 - output, 233 - }); 234 - 235 - input.emit('keypress', '', { name: 'return' }); 236 - 237 - await result; 238 - 239 - expect(output.buffer).toMatchSnapshot(); 240 - }); 241 - });