@nan0web/ui-cli 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +2 -11
  2. package/package.json +17 -7
  3. package/src/CLI.js +141 -0
  4. package/src/Command.js +210 -0
  5. package/src/CommandError.js +35 -0
  6. package/src/CommandHelp.js +204 -0
  7. package/src/CommandMessage.js +181 -0
  8. package/src/CommandParser.js +217 -0
  9. package/src/InputAdapter.js +78 -149
  10. package/src/README.md.js +7 -6
  11. package/src/index.js +36 -14
  12. package/src/ui/index.js +3 -3
  13. package/src/ui/input.js +68 -11
  14. package/src/ui/next.js +30 -26
  15. package/src/ui/select.js +41 -31
  16. package/src/utils/parse.js +41 -0
  17. package/types/CLI.d.ts +44 -0
  18. package/types/Command.d.ts +72 -0
  19. package/types/CommandError.d.ts +19 -0
  20. package/types/CommandHelp.d.ts +85 -0
  21. package/types/CommandMessage.d.ts +65 -0
  22. package/types/CommandParser.d.ts +28 -0
  23. package/types/InputAdapter.d.ts +28 -85
  24. package/types/index.d.ts +12 -9
  25. package/types/ui/index.d.ts +2 -3
  26. package/types/ui/input.d.ts +50 -6
  27. package/types/ui/next.d.ts +11 -8
  28. package/types/ui/select.d.ts +50 -20
  29. package/types/utils/parse.d.ts +13 -0
  30. package/.editorconfig +0 -20
  31. package/CONTRIBUTING.md +0 -42
  32. package/docs/uk/README.md +0 -294
  33. package/playground/forms/addressForm.js +0 -37
  34. package/playground/forms/ageForm.js +0 -26
  35. package/playground/forms/profileForm.js +0 -33
  36. package/playground/forms/userForm.js +0 -36
  37. package/playground/main.js +0 -81
  38. package/playground/vocabs/en.js +0 -25
  39. package/playground/vocabs/index.js +0 -12
  40. package/playground/vocabs/uk.js +0 -25
  41. package/src/InputAdapter.test.js +0 -117
  42. package/src/ui/input.test.js +0 -27
  43. package/src/ui/select.test.js +0 -34
  44. package/system.md +0 -99
  45. package/tsconfig.json +0 -23
  46. package/types/test/ReadLine.d.ts +0 -1
  47. package/types/ui/errors.d.ts +0 -3
package/docs/uk/README.md DELETED
@@ -1,294 +0,0 @@
1
- # @nan0web/ui-cli
2
-
3
- Маленький, беззалежний UI‑адаптер вводу для JavaScript‑проєктів.
4
- Надає CLI‑реалізацію, яку легко інтегрувати у логіку застосунку.
5
-
6
- |[Статус](https://github.com/nan0web/monorepo/blob/main/system.md#написання-сценаріїв)|Документація|Тестове покриття|Фічі|Версія npm|
7
- |---|---|---|---|---|
8
- |🟢 `96.1%`|🧪 [English 🏴󠁧󠁢󠁥󠁮󠁧󠁿](https://github.com/nan0web/ui-cli/blob/main/README.md)<br />[Українською 🇺🇦](https://github.com/nan0web/ui-cli/blob/main/docs/uk/README.md)|🟡 `77.9%`|✅ d.ts 📜 system.md 🕹️ playground|—|
9
-
10
- ## Опис
11
-
12
- Пакет `@nan0web/ui-cli` надає набір інструментів для обробки вводу користувача в CLI через
13
- структуровані форми, вибір варіантів та підказки.
14
- Використовує патерн адаптера для безшовної інтеграції з моделями даних застосунку.
15
-
16
- ### Основні класи
17
-
18
- - **`CLIInputAdapter`** — обробляє запити форм, вводу та вибору в CLI.
19
- - **`Input`** — обгортає введене користувачем значення та статус скасування.
20
- - **`CancelError`** — викидається, коли користувач скасовує операцію.
21
-
22
- Ці класи ідеальні для створення підказок, майстрів, форм та інтерактивних інструментів CLI з мінімальними накладними витратами.
23
-
24
- ## Встановлення
25
-
26
- ### Через npm
27
- ```bash
28
- npm install @nan0web/ui-cli
29
- ```
30
-
31
- ### Через pnpm
32
- ```bash
33
- pnpm add @nan0web/ui-cli
34
- ```
35
-
36
- ### Через yarn
37
- ```bash
38
- yarn add @nan0web/ui-cli
39
- ```
40
-
41
- ## Приклади використання
42
-
43
- ### CLIInputAdapter
44
-
45
- Адаптер містить методи для роботи з формами, ввідними та вибірковими запитами.
46
-
47
- #### `requestForm(form, options)`
48
-
49
- Відображає форму та послідовно збирає ввід полів з валідацією.
50
-
51
- ```js
52
- import { CLIInputAdapter } from '@nan0web/ui-cli'
53
-
54
- const adapter = new CLIInputAdapter()
55
-
56
- const fields = [
57
- { name: "name", label: "Повне ім’я", required: true },
58
- { name: "email", label: "Email", type: "email", required: true },
59
- ]
60
-
61
- const validateValue = (name, value) => {
62
- if (name === "email" && !value.includes("@")) {
63
- return { isValid: false, errors: { email: "Некоректний email" } }
64
- }
65
- return { isValid: true, errors: {} }
66
- }
67
- const setData = (data) => {
68
- const newForm = { ...form }
69
- newForm.state = data
70
- return newForm
71
- }
72
- const form = UIForm.from({
73
- title: "Профіль користувача",
74
- fields,
75
- id: "user-profile-form",
76
- validateValue,
77
- setData,
78
- state: {},
79
- validate: () => ({ isValid: true, errors: {} }),
80
- })
81
-
82
- const result = await adapter.requestForm(form, { silent: true })
83
-
84
- console.info(result.form.state) // ← { name: "John Doe", email: "John.Doe@example.com" }
85
- ```
86
-
87
- #### `requestSelect(config)`
88
-
89
- Показує список варіантів і повертає обраний елемент.
90
-
91
- ```js
92
- import { CLIInputAdapter } from '@nan0web/ui-cli'
93
-
94
- const adapter = new CLIInputAdapter()
95
- const config = {
96
- title: "Виберіть мову:",
97
- prompt: "Мова (1‑2): ",
98
- id: "language-select",
99
- options: new Map([
100
- ["en", "English"],
101
- ["uk", "Ukrainian"],
102
- ]),
103
- }
104
-
105
- const result = await adapter.requestSelect(config)
106
- console.info(result.value) // ← Message { body: "en", head: {} }
107
- ```
108
-
109
- ### Утиліти вводу
110
-
111
- #### Клас `Input`
112
-
113
- Зберігає введене значення і відстежує скасування.
114
-
115
- ```js
116
- import { Input } from '@nan0web/ui-cli'
117
-
118
- const input = new Input({ value: "test", stops: ["quit"] })
119
- console.info(String(input)) // ← test
120
- console.info(input.value) // ← test
121
- console.info(input.cancelled) // ← false
122
-
123
- input.value = "quit"
124
- console.info(input.cancelled) // ← true
125
- ```
126
-
127
- #### `ask(question)`
128
-
129
- Виводить питання та повертає відповідь у вигляді промісу.
130
-
131
- ```js
132
- import { ask } from "@nan0web/ui-cli"
133
-
134
- const result = await ask("Яке ваше ім’я?")
135
- console.info(result)
136
- ```
137
-
138
- #### `createInput(stops)`
139
-
140
- Створює налаштовуваний обробник вводів зі словами‑стопами.
141
-
142
- ```js
143
- import { createInput } from '@nan0web/ui-cli'
144
-
145
- const handler = createInput(["cancel"])
146
- console.info(typeof handler === "function") // ← true
147
- ```
148
-
149
- #### `select(config)`
150
-
151
- Показує список варіантів та повертає обраний елемент.
152
-
153
- ```js
154
- import { select } from '@nan0web/ui-cli'
155
-
156
- const config = {
157
- title: "Оберіть варіант:",
158
- prompt: "Вибір (1‑3): ",
159
- options: ["Варіант A", "Варіант B", "Варіант C"],
160
- console: console,
161
- }
162
-
163
- const result = await select(config)
164
- console.info(result.value)
165
- ```
166
-
167
- #### `next(conf)`
168
-
169
- Чекає натискання клавіші (або послідовності клавіш) для продовження процесу.
170
-
171
- ```js
172
- import { next } from '@nan0web/ui-cli'
173
-
174
- const result = await next()
175
- console.info(typeof result === "string")
176
- ```
177
-
178
- #### `pause(ms)`
179
-
180
- Повертає проміс, який виконується після заданої затримки.
181
-
182
- ```js
183
- import { pause } from '@nan0web/ui-cli'
184
- const before = Date.now()
185
- await pause(10)
186
- const after = Date.now()
187
- console.info(after - before >= 10) // ← true
188
- ```
189
-
190
- ### Помилки
191
-
192
- #### `CancelError`
193
-
194
- Викидається, коли користувач перериває процес.
195
-
196
- ```js
197
- import { CancelError } from '@nan0web/ui-cli'
198
-
199
- try {
200
- // ... код, який може бути скасований
201
- } catch (err) {
202
- if (err instanceof CancelError) {
203
- console.error(err.message) // ← Операція скасована користувачем
204
- }
205
- }
206
- ```
207
-
208
- ## API
209
-
210
- ### `CLIInputAdapter`
211
-
212
- - **Методи**
213
- - `requestForm(form, options)` — асинхронно обробляє запит форми.
214
- - `requestSelect(config)` — асинхронно обробляє запит вибору.
215
- - `requestInput(config)` — асинхронно обробляє запит одиничного вводу.
216
-
217
- ### `Input`
218
-
219
- - **Властивості**
220
- - `value` – (string) поточне введене значення.
221
- - `stops` – (array) ключові слова‑стопи.
222
- - `cancelled` – (boolean) чи було скасовано ввід.
223
- - **Методи**
224
- - `toString()` – повертає поточне значення як рядок.
225
- - `static from(input)` – створює інстанс з об’єкта вводу.
226
-
227
- ### `ask(question)`
228
-
229
- - **Параметри**
230
- - `question` (string) – текст підказки.
231
- - **Повертає**
232
- - `Promise<string>` – відповідь користувача.
233
-
234
- ### `createInput(stops)`
235
-
236
- - **Параметри**
237
- - `stops` (array) – значення, при яких ввід скасовується.
238
- - **Повертає**
239
- - функція‑обробник.
240
-
241
- ### `select(config)`
242
-
243
- - **Параметри**
244
- - `config.title` (string) – заголовок вибору.
245
- - `config.prompt` (string) – підказка.
246
- - `config.options` (array | Map) – варіанти вибору.
247
- - **Повертає**
248
- - `Promise<{ index, value }>` – обраний елемент.
249
-
250
- ### `next([conf])`
251
-
252
- - **Параметри**
253
- - `conf` (string) – приймана послідовність клавіш.
254
- - **Повертає**
255
- - `Promise<string>` – натиснута клавіша.
256
-
257
- ### `pause(ms)`
258
-
259
- - **Параметри**
260
- - `ms` (number) – затримка у мілісекундах.
261
- - **Повертає**
262
- - `Promise<void>`.
263
-
264
- ### `CancelError`
265
-
266
- Розширює `Error`, викидається при скасуванні вводу.
267
-
268
- ## Тестування
269
-
270
- Усі експортовані класи та функції повинні проходити базові тести.
271
-
272
- ## JavaScript
273
-
274
- Для автодоповнення використовується `d.ts` (type‑definition) файли.
275
-
276
- ## Playground
277
-
278
- Як запустити скрипт Playground?
279
-
280
- ```bash
281
- # Клонуємо репозиторій і запускаємо CLI playground
282
- git clone https://github.com/nan0web/ui-cli.git
283
- cd ui-cli
284
- npm install
285
- npm run playground
286
- ```
287
-
288
- ## Спільна розробка
289
-
290
- Як долучитися? – [дивіться тут](./CONTRIBUTING.md)
291
-
292
- ## Ліцензія
293
-
294
- Як задокументовано у файлі ліцензії ISC – [дивіться тут](./LICENSE)
@@ -1,37 +0,0 @@
1
- import { UIForm, FormInput } from '@nan0web/ui'
2
-
3
- /**
4
- * Creates an address information form
5
- * @param {Function} t - Translation function
6
- * @returns {UIForm} Address form
7
- */
8
- export function createAddressForm(t) {
9
- return new UIForm({
10
- title: t('Address information'),
11
- id: 'address-form',
12
- state: {},
13
- fields: [
14
- new FormInput({
15
- name: 'street',
16
- label: t('Street'),
17
- required: true
18
- }),
19
- new FormInput({
20
- name: 'city',
21
- label: t('City'),
22
- required: true
23
- }),
24
- new FormInput({
25
- name: 'postalCode',
26
- label: t('Postal code'),
27
- type: FormInput.TYPES.TEXT,
28
- required: false
29
- }),
30
- new FormInput({
31
- name: 'country',
32
- label: t('Country'),
33
- required: true
34
- })
35
- ]
36
- })
37
- }
@@ -1,26 +0,0 @@
1
- import { UIForm, FormInput } from '@nan0web/ui'
2
-
3
- /**
4
- * Creates an age confirmation form
5
- * @param {Function} t - Translation function
6
- * @returns {UIForm} Age confirmation form
7
- */
8
- export function createAgeForm(t) {
9
- return new UIForm({
10
- title: t('Age confirmation form'),
11
- id: 'age-confirmation',
12
- state: {},
13
- fields: [
14
- new FormInput({
15
- name: 'age',
16
- label: t('Please enter your age'),
17
- type: FormInput.TYPES.NUMBER,
18
- validator: (value) => {
19
- const num = Number(value)
20
- return num >= 18 ? null : t('You must be at least 18 years old')
21
- },
22
- required: true
23
- })
24
- ]
25
- })
26
- }
@@ -1,33 +0,0 @@
1
- import { UIForm, FormInput } from '@nan0web/ui'
2
-
3
- /**
4
- * Creates a profile update form
5
- * @param {Function} t - Translation function
6
- * @returns {UIForm} Profile update form
7
- */
8
- export function createProfileForm(t) {
9
- return new UIForm({
10
- title: t('Profile update form'),
11
- id: 'profile-update',
12
- state: {},
13
- fields: [
14
- new FormInput({
15
- name: 'username',
16
- label: t('Username'),
17
- required: true
18
- }),
19
- new FormInput({
20
- name: 'bio',
21
- label: t('Biography'),
22
- type: FormInput.TYPES.TEXTAREA,
23
- required: false
24
- }),
25
- new FormInput({
26
- name: 'newsletter',
27
- label: t('Subscribe to newsletter'),
28
- type: FormInput.TYPES.CHECKBOX,
29
- required: false
30
- })
31
- ]
32
- })
33
- }
@@ -1,36 +0,0 @@
1
- import { UIForm, FormInput } from '@nan0web/ui'
2
-
3
- /**
4
- * Creates a user registration form
5
- * @param {Function} t - Translation function
6
- * @returns {UIForm} User registration form
7
- */
8
- export function createUserForm(t) {
9
- return new UIForm({
10
- title: t('User Registration Form'),
11
- id: 'user-registration',
12
- state: {},
13
- fields: [
14
- new FormInput({
15
- name: 'name',
16
- label: t('Full name'),
17
- required: true
18
- }),
19
- new FormInput({
20
- name: 'email',
21
- label: t('Email address'),
22
- type: FormInput.TYPES.EMAIL,
23
- required: true
24
- }),
25
- new FormInput({
26
- name: 'phone',
27
- label: t('Phone number'),
28
- type: FormInput.TYPES.TEXT,
29
- validator: (value) => {
30
- return value.length >= 10 && value.length <= 15 ? null : t('Invalid phone number')
31
- },
32
- required: false
33
- })
34
- ]
35
- })
36
- }
@@ -1,81 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import Logger from '@nan0web/log'
4
- import { CLIInputAdapter } from '../src/index.js'
5
- import { createUserForm } from './forms/userForm.js'
6
- import { createAgeForm } from './forms/ageForm.js'
7
- import { createAddressForm } from './forms/addressForm.js'
8
- import { createProfileForm } from './forms/profileForm.js'
9
- import createT, { localesMap } from "./vocabs/index.js"
10
-
11
- console = new Logger()
12
-
13
- const adapter = new CLIInputAdapter()
14
-
15
- console.info(Logger.style(Logger.LOGO, { color: "magenta" }))
16
- console.warn('=== @nan0web/ui CLI Playground ===\n')
17
-
18
- // Language selection
19
- const langResult = await adapter.requestSelect({
20
- title: "Language selection",
21
- prompt: "Choose language (1-2): ",
22
- options: localesMap,
23
- elementId: "language-select"
24
- })
25
-
26
- if (langResult.action === 'select-cancel') {
27
- console.warn('Language selection cancelled')
28
- process.exit(0)
29
- }
30
-
31
- const selectedLang = langResult.value
32
- const t = createT(selectedLang)
33
-
34
- console.success(`${t('Language selection')}: ${t(selectedLang)}`)
35
- console.info()
36
-
37
- // User registration form
38
- const userForm = createUserForm(t)
39
- const userResult = await adapter.requestForm(userForm, { silent: false })
40
-
41
- if (userResult.action === 'form-submit') {
42
- console.success(t('Welcome to our platform!'))
43
- console.info('User data:', userResult.data)
44
- console.info()
45
- } else {
46
- console.warn('User registration cancelled')
47
- }
48
-
49
- // Age confirmation form
50
- const ageForm = createAgeForm(t)
51
- const ageResult = await adapter.requestForm(ageForm, { silent: false })
52
-
53
- if (ageResult.action === 'form-submit') {
54
- console.success(`Confirmed age: ${ageResult.data.age}`)
55
- } else {
56
- console.warn('Age confirmation cancelled')
57
- }
58
-
59
- // Address information form
60
- const addressForm = createAddressForm(t)
61
- const addressResult = await adapter.requestForm(addressForm, { silent: false })
62
-
63
- if (addressResult.action === 'form-submit') {
64
- console.success('Address information collected')
65
- console.info('Address data:', addressResult.data)
66
- console.info()
67
- } else {
68
- console.warn('Address form cancelled')
69
- }
70
-
71
- // Profile update form
72
- const profileForm = createProfileForm(t)
73
- const profileResult = await adapter.requestForm(profileForm, { silent: false })
74
-
75
- if (profileResult.action === 'form-submit') {
76
- console.success('Profile updated')
77
- console.info('Profile data:', profileResult.data)
78
- console.info()
79
- } else {
80
- console.warn('Profile update cancelled')
81
- }
@@ -1,25 +0,0 @@
1
- export default {
2
- "User Registration Form": "User Registration Form",
3
- "Full name": "Full name",
4
- "Email address": "Email address",
5
- "Phone number": "Phone number",
6
- "Age confirmation form": "Age confirmation form",
7
- "Please enter your age": "Please enter your age",
8
- "Language selection": "Language selection",
9
- "Choose language": "Choose language",
10
- "English": "English",
11
- "Ukrainian": "Ukrainian",
12
- "You must be at least 18 years old": "You must be at least 18 years old",
13
- "Invalid phone number": "Invalid phone number",
14
- "Welcome to our platform!": "Welcome to our platform!",
15
- "Address information": "Address information",
16
- "Street": "Street",
17
- "City": "City",
18
- "Postal code": "Postal code",
19
- "Country": "Country",
20
- "Profile update form": "Profile update form",
21
- "Username": "Username",
22
- "Biography": "Biography",
23
- "Newsletter subscription": "Newsletter subscription",
24
- "Subscribe to newsletter": "Subscribe to newsletter"
25
- }
@@ -1,12 +0,0 @@
1
- import i18n, { createT } from "@nan0web/i18n"
2
- import en from "./en.js"
3
- import uk from "./uk.js"
4
-
5
- const getVocab = i18n({ en, uk })
6
-
7
- export const localesMap = new Map([
8
- ["en", "English"],
9
- ["uk", "Українська"],
10
- ])
11
-
12
- export default (locale) => createT(getVocab(locale))
@@ -1,25 +0,0 @@
1
- export default {
2
- "User Registration Form": "Форма реєстрації користувача",
3
- "Full name": "Повне ім'я",
4
- "Email address": "Електронна пошта",
5
- "Phone number": "Номер телефону",
6
- "Age confirmation form": "Форма підтвердження віку",
7
- "Please enter your age": "Будь ласка, введіть ваш вік",
8
- "Language selection": "Вибір мови",
9
- "Choose language": "Виберіть мову",
10
- "English": "Англійська",
11
- "Ukrainian": "Українська",
12
- "You must be at least 18 years old": "Вам має бути не менше 18 років",
13
- "Invalid phone number": "Невірний номер телефону",
14
- "Welcome to our platform!": "Ласкаво просимо на нашу платформу!",
15
- "Address information": "Інформація про адресу",
16
- "Street": "Вулиця",
17
- "City": "Місто",
18
- "Postal code": "Поштовий код",
19
- "Country": "Країна",
20
- "Profile update form": "Форма оновлення профілю",
21
- "Username": "Ім'я користувача",
22
- "Biography": "Біографія",
23
- "Newsletter subscription": "Підписка на розсилку",
24
- "Subscribe to newsletter": "Підписатися на розсилку"
25
- }
@@ -1,117 +0,0 @@
1
- import { describe, it } from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import { UIForm, FormInput, InputMessage } from '@nan0web/ui'
4
- import { CancelError } from '@nan0web/ui/core'
5
- import CLIInputAdapter from './InputAdapter.js'
6
-
7
- // Awaits for the user input.
8
- describe('CLIInputAdapter', () => {
9
- it('should create instance', () => {
10
- const adapter = new CLIInputAdapter()
11
- assert.ok(adapter instanceof CLIInputAdapter)
12
- })
13
-
14
- it('should validate form fields', async () => {
15
- const adapter = new CLIInputAdapter()
16
-
17
- // Mock ask for testing
18
- adapter.ask = () => Promise.resolve('test@example.com')
19
-
20
- const form = new UIForm({
21
- title: 'Test Form',
22
- elementId: 'test-form',
23
- fields: [
24
- new FormInput({
25
- name: 'email',
26
- label: 'Email',
27
- type: 'email',
28
- required: true
29
- })
30
- ]
31
- })
32
-
33
- const result = await adapter.requestForm(form, { silent: true })
34
- assert.equal(result.form.state.email, 'test@example.com')
35
- })
36
-
37
- it('should handle form cancellation', async () => {
38
- const adapter = new CLIInputAdapter()
39
-
40
- // Mock ask for cancellation
41
- adapter.ask = () => Promise.resolve(InputMessage.ESCAPE)
42
-
43
- const form = new UIForm({
44
- title: 'Test Form',
45
- elementId: 'test-form',
46
- fields: [
47
- new FormInput({
48
- name: 'name',
49
- label: 'Name',
50
- required: true
51
- })
52
- ]
53
- })
54
-
55
- const result = await adapter.requestForm(form, { silent: true })
56
- assert.equal(result.escaped, true)
57
- })
58
-
59
- it('should have CancelError static property', () => {
60
- assert.ok(CLIInputAdapter.CancelError)
61
- const error = new CLIInputAdapter.CancelError()
62
- assert.equal(error.name, "CancelError")
63
- assert.equal(error.message, "Operation cancelled by user")
64
- })
65
-
66
- it('should implement ask method', async () => {
67
- const adapter = new CLIInputAdapter()
68
- // Mock internal ask to avoid stdin interaction
69
- const originalAsk = adapter.ask
70
- adapter.ask = () => Promise.resolve('test answer')
71
-
72
- const answer = await adapter.ask('Test question?')
73
- assert.equal(answer, 'test answer')
74
-
75
- // Restore original
76
- adapter.ask = originalAsk
77
- })
78
-
79
- it('should implement select method', async () => {
80
- const adapter = new CLIInputAdapter()
81
- // Mock internal select to avoid stdin interaction
82
- const originalSelect = adapter.select
83
- adapter.select = () => Promise.resolve({ value: 'option1', index: 0 })
84
-
85
- const result = await adapter.select({
86
- title: 'Test Select',
87
- prompt: 'Choose:',
88
- options: ['option1', 'option2']
89
- })
90
- assert.equal(result.value, 'option1')
91
- assert.equal(result.index, 0)
92
-
93
- // Restore original
94
- adapter.select = originalSelect
95
- })
96
-
97
- it('should handle select cancellation', async () => {
98
- const adapter = new CLIInputAdapter()
99
-
100
- // Mock select to throw CancelError
101
- const originalSelect = adapter.select
102
- adapter.select = () => Promise.reject(new CancelError())
103
-
104
- const config = {
105
- title: 'Test Select',
106
- prompt: 'Choose:',
107
- id: 'test-select',
108
- options: ['option1', 'option2']
109
- }
110
-
111
- const result = await adapter.requestSelect(config)
112
- assert.deepStrictEqual(result.value, InputMessage.from({}).value)
113
-
114
- // Restore original
115
- adapter.select = originalSelect
116
- })
117
- })