Skip to content

Commit 18ced10

Browse files
committed
refactor(cli): extract ask-user sub-components and rename Other to Custom
Extract QuestionHeader, OptionsList, and CustomAnswerInput sub-components from AccordionQuestion. Rename all 'Other' terminology to 'Custom' for UI consistency (isOther -> isCustom, otherText -> customText, etc).
1 parent 4c7ead2 commit 18ced10

File tree

7 files changed

+408
-249
lines changed

7 files changed

+408
-249
lines changed

cli/src/components/ask-user/__tests__/multiple-choice-form.test.ts

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import { describe, it, expect } from 'bun:test'
1010

11-
import { getOptionLabel, OTHER_OPTION_INDEX } from '../constants'
11+
import { getOptionLabel, CUSTOM_OPTION_INDEX } from '../constants'
1212

1313
import type { AccordionAnswer } from '../components/accordion-question'
1414
import type { AskUserOption } from '../constants'
@@ -40,8 +40,8 @@ function formatAnswer(
4040
: []
4141

4242
const customText =
43-
answer.isOther && (answer.otherText?.trim().length ?? 0) > 0
44-
? (answer.otherText ?? '').trim()
43+
answer.isCustom && (answer.customText?.trim().length ?? 0) > 0
44+
? (answer.customText ?? '').trim()
4545
: ''
4646

4747
const parts = customText ? [...selectedOptions, customText] : selectedOptions
@@ -132,10 +132,10 @@ describe('formatAnswer', () => {
132132
})
133133
})
134134

135-
it('returns custom text when isOther is true', () => {
135+
it('returns custom text when isCustom is true', () => {
136136
const answer: AccordionAnswer = {
137-
isOther: true,
138-
otherText: 'Purple',
137+
isCustom: true,
138+
customText: 'Purple',
139139
}
140140
const result = formatAnswer(singleSelectQuestion, answer)
141141
expect(result).toEqual({
@@ -146,8 +146,8 @@ describe('formatAnswer', () => {
146146

147147
it('trims whitespace from custom text', () => {
148148
const answer: AccordionAnswer = {
149-
isOther: true,
150-
otherText: ' Purple ',
149+
isCustom: true,
150+
customText: ' Purple ',
151151
}
152152
const result = formatAnswer(singleSelectQuestion, answer)
153153
expect(result).toEqual({
@@ -156,10 +156,10 @@ describe('formatAnswer', () => {
156156
})
157157
})
158158

159-
it('returns Skipped when isOther is true but text is empty', () => {
159+
it('returns Skipped when isCustom is true but text is empty', () => {
160160
const answer: AccordionAnswer = {
161-
isOther: true,
162-
otherText: '',
161+
isCustom: true,
162+
customText: '',
163163
}
164164
const result = formatAnswer(singleSelectQuestion, answer)
165165
expect(result).toEqual({
@@ -168,10 +168,10 @@ describe('formatAnswer', () => {
168168
})
169169
})
170170

171-
it('returns Skipped when isOther is true but text is only whitespace', () => {
171+
it('returns Skipped when isCustom is true but text is only whitespace', () => {
172172
const answer: AccordionAnswer = {
173-
isOther: true,
174-
otherText: ' ',
173+
isCustom: true,
174+
customText: ' ',
175175
}
176176
const result = formatAnswer(singleSelectQuestion, answer)
177177
expect(result).toEqual({
@@ -221,8 +221,8 @@ describe('formatAnswer', () => {
221221
it('includes custom text with selections', () => {
222222
const answer: AccordionAnswer = {
223223
selectedIndices: new Set([0]),
224-
isOther: true,
225-
otherText: 'Cooking',
224+
isCustom: true,
225+
customText: 'Cooking',
226226
}
227227
const result = formatAnswer(multiSelectQuestion, answer)
228228
expect(result).toEqual({
@@ -234,8 +234,8 @@ describe('formatAnswer', () => {
234234
it('returns only custom text when no other selections', () => {
235235
const answer: AccordionAnswer = {
236236
selectedIndices: new Set(),
237-
isOther: true,
238-
otherText: 'Cooking',
237+
isCustom: true,
238+
customText: 'Cooking',
239239
}
240240
const result = formatAnswer(multiSelectQuestion, answer)
241241
expect(result).toEqual({
@@ -266,67 +266,67 @@ describe('formatAnswer', () => {
266266
})
267267
})
268268

269-
describe('OTHER_OPTION_INDEX constant', () => {
270-
it('is -1 for identifying custom/other option', () => {
271-
expect(OTHER_OPTION_INDEX).toBe(-1)
269+
describe('CUSTOM_OPTION_INDEX constant', () => {
270+
it('is -1 for identifying custom option', () => {
271+
expect(CUSTOM_OPTION_INDEX).toBe(-1)
272272
})
273273

274274
it('is distinct from valid option indices', () => {
275-
expect(OTHER_OPTION_INDEX).toBeLessThan(0)
275+
expect(CUSTOM_OPTION_INDEX).toBeLessThan(0)
276276
})
277277
})
278278

279279
describe('answer state management patterns', () => {
280280
describe('single-select behavior', () => {
281-
it('selecting an option clears isOther flag', () => {
281+
it('selecting an option clears isCustom flag', () => {
282282
const previousAnswer: AccordionAnswer = {
283-
isOther: true,
284-
otherText: 'Custom text',
283+
isCustom: true,
284+
customText: 'Custom text',
285285
}
286286

287287
const optionIndex: number = 1
288-
const isOtherOption = optionIndex === OTHER_OPTION_INDEX
288+
const isCustomOption = optionIndex === CUSTOM_OPTION_INDEX
289289

290-
const newAnswer: AccordionAnswer = isOtherOption
290+
const newAnswer: AccordionAnswer = isCustomOption
291291
? {
292292
selectedIndex: undefined,
293293
selectedIndices: undefined,
294-
isOther: true,
295-
otherText: previousAnswer.otherText || '',
294+
isCustom: true,
295+
customText: previousAnswer.customText || '',
296296
}
297297
: {
298298
selectedIndex: optionIndex,
299299
selectedIndices: undefined,
300-
isOther: false,
300+
isCustom: false,
301301
}
302302

303303
expect(newAnswer.selectedIndex).toBe(1)
304-
expect(newAnswer.isOther).toBe(false)
304+
expect(newAnswer.isCustom).toBe(false)
305305
})
306306

307-
it('selecting OTHER clears selectedIndex and enables isOther', () => {
307+
it('selecting CUSTOM clears selectedIndex and enables isCustom', () => {
308308
const previousAnswer: AccordionAnswer = {
309309
selectedIndex: 1,
310310
}
311311

312-
const optionIndex = OTHER_OPTION_INDEX
313-
const isOtherOption = optionIndex === OTHER_OPTION_INDEX
312+
const optionIndex = CUSTOM_OPTION_INDEX
313+
const isCustomOption = optionIndex === CUSTOM_OPTION_INDEX
314314

315-
const newAnswer: AccordionAnswer = isOtherOption
315+
const newAnswer: AccordionAnswer = isCustomOption
316316
? {
317317
selectedIndex: undefined,
318318
selectedIndices: undefined,
319-
isOther: true,
320-
otherText: previousAnswer.otherText || '',
319+
isCustom: true,
320+
customText: previousAnswer.customText || '',
321321
}
322322
: {
323323
selectedIndex: optionIndex,
324324
selectedIndices: undefined,
325-
isOther: false,
325+
isCustom: false,
326326
}
327327

328328
expect(newAnswer.selectedIndex).toBeUndefined()
329-
expect(newAnswer.isOther).toBe(true)
329+
expect(newAnswer.isCustom).toBe(true)
330330
})
331331
})
332332

@@ -368,17 +368,17 @@ describe('answer state management patterns', () => {
368368
expect(newIndices.size).toBe(2)
369369
})
370370

371-
it('toggling OTHER toggles isOther flag', () => {
371+
it('toggling CUSTOM toggles isCustom flag', () => {
372372
const currentAnswer: AccordionAnswer = {
373373
selectedIndices: new Set([0]),
374-
isOther: false,
374+
isCustom: false,
375375
}
376376

377-
const optionIndex = OTHER_OPTION_INDEX
378-
const toggledOtherOn =
379-
optionIndex === OTHER_OPTION_INDEX && !currentAnswer.isOther
377+
const optionIndex = CUSTOM_OPTION_INDEX
378+
const toggledCustomOn =
379+
optionIndex === CUSTOM_OPTION_INDEX && !currentAnswer.isCustom
380380

381-
expect(toggledOtherOn).toBe(true)
381+
expect(toggledCustomOn).toBe(true)
382382
})
383383
})
384384
})

0 commit comments

Comments
 (0)