test(ui-user-questions): 覆盖多选预选的计时与回看卡片
This commit is contained in:
1 parent
bf8d8494ba
commit
07c3c10d2c
4 files changed
+56
-12
No files matched your search
@@ -15,8 +15,8 @@
|
||||
en: d152484eb41ac6b4
|
||||
zh: 09388d293f9be9cb
|
||||
/deepseek-ai-dsh-client-ui-user-questions/use-this-package:
|
||||
en: 56368ea7909468c0
|
||||
zh: b212ffa1f0fda6a5
|
||||
en: f63c46f9fc2edb1f
|
||||
zh: 82ad1b2e56a61a52
|
||||
/deepseek-ai-dsh-client-ui-user-questions/use-this-package/answering:
|
||||
en: 8900fbf9cbd72083
|
||||
zh: 67a951d58a029a58
|
||||
|
||||
@@ -25,7 +25,7 @@ The Web client shows an agent's question beside the chat input. Users choose opt
|
||||
<a id="use-this-package"></a>
|
||||
## Use this package
|
||||
|
||||
When the agent asks a question, the attached card temporarily occupies the composer seat: answer each question, navigate with the pager, or skip it. A single-select question’s first choice marked “Recommended” starts selected, as does every marked choice of a multi-select question; but remains an unsubmitted draft and does not pause a timed countdown. Clicking a single-select choice advances immediately. Enter on a focused option attempts to submit the batch without selecting that option; missing answers return to the first incomplete question. Enter in a text answer continues the flow, while Shift+Enter breaks a line instead (during IME composition Enter only confirms the input candidate without advancing).
|
||||
When the agent asks a question, the attached card temporarily occupies the composer seat: answer each question, navigate with the pager, or skip it. When a single-select question’s first choice is marked “Recommended”, it starts selected; in a multi-select question, every marked choice starts selected. These preselections remain unsubmitted drafts and do not pause a timed countdown. Clicking a single-select choice advances immediately. Enter on a focused option attempts to submit the batch without selecting that option; missing answers return to the first incomplete question. Enter in a text answer continues the flow, while Shift+Enter breaks a line instead (during IME composition Enter only confirms the input candidate without advancing).
|
||||
|
||||
### Answering
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Web 客户端在聊天输入框旁显示 agent(智能体)的提问。用户
|
||||
<a id="use-this-package"></a>
|
||||
## 使用本包
|
||||
|
||||
当 agent 提问时,附着式卡片会暂时占用编辑器位置:回答每个问题、用翻页器导航,或跳过它。单选题中首个带推荐标记的选项、多选题中所有带推荐标记的选项会预先选中,但仍只是未提交的草稿,不会暂停计时倒计时。点击单选选项会立即前进。聚焦选项时按 Enter 会尝试提交整组答案,不会选中该选项;若有缺失答案,则回到第一道未完成的问题。文本答案中的 Enter 会继续流程,Shift+Enter 则换行(IME 组合输入期间按 Enter 只会确认输入候选,不会前进)。
|
||||
当 agent 提问时,附着式卡片会暂时占用编辑器位置:回答每个问题、用翻页器导航,或跳过它。单选题的第一个选项带推荐标记时会预先选中;多选题中所有带推荐标记的选项都会预先选中。这些预选仍只是未提交的草稿,不会暂停计时倒计时。点击单选选项会立即前进。聚焦选项时按 Enter 会尝试提交整组答案,不会选中该选项;若有缺失答案,则回到第一道未完成的问题。文本答案中的 Enter 会继续流程,Shift+Enter 则换行(IME 组合输入期间按 Enter 只会确认输入候选,不会前进)。
|
||||
|
||||
### 作答
|
||||
|
||||
|
||||
@@ -246,28 +246,50 @@ describe('QuestionComposer', () => {
|
||||
options: [{ label: 'Unit (Recommended)' }, { label: 'Lint' }, { label: 'Types(推荐)' }],
|
||||
}])
|
||||
render(<QuestionComposer matched={carrier} {...kit} />)
|
||||
expect(screen.getByRole('checkbox', { name: /Unit/ }).getAttribute('aria-checked')).toBe('true')
|
||||
expect(screen.getByRole('checkbox', { name: /Lint/ }).getAttribute('aria-checked')).toBe('false')
|
||||
expect(screen.getByRole('checkbox', { name: /Types/ }).getAttribute('aria-checked')).toBe('true')
|
||||
expect(screen.getByRole('checkbox', { name: 'Unit' }).getAttribute('aria-checked')).toBe('true')
|
||||
expect(screen.getByRole('checkbox', { name: 'Lint' }).getAttribute('aria-checked')).toBe('false')
|
||||
expect(screen.getByRole('checkbox', { name: 'Types' }).getAttribute('aria-checked')).toBe('true')
|
||||
|
||||
fireEvent.keyDown(screen.getByRole('checkbox', { name: /Lint/ }), { key: 'Enter' })
|
||||
fireEvent.keyDown(screen.getByRole('checkbox', { name: 'Lint' }), { key: 'Enter' })
|
||||
expect(answer).toHaveBeenCalledWith(answerBatch([
|
||||
{ id: 'checks', selected: ['Unit (Recommended)', 'Types(推荐)'] },
|
||||
]))
|
||||
})
|
||||
|
||||
it('keeps several recommended multi-select defaults without pausing a timed wait', () => {
|
||||
const { carrier } = wait([
|
||||
{
|
||||
id: 'checks', question: 'Which checks?', multiSelect: true,
|
||||
options: [{ label: 'Unit (Recommended)' }, { label: 'Lint' }, { label: 'Types (Recommended)' }],
|
||||
},
|
||||
{ id: 'note', question: 'Anything else?' },
|
||||
], Date.now() + 30_000)
|
||||
try {
|
||||
const view = render(<QuestionComposer matched={carrier} {...kit} />)
|
||||
fireEvent.click(screen.getByLabelText('下一题'))
|
||||
view.unmount()
|
||||
render(<QuestionComposer matched={carrier} {...kit} />)
|
||||
expect(carrier.snapshot().countdown?.running).toBe(true)
|
||||
fireEvent.click(screen.getByLabelText('上一题'))
|
||||
expect(screen.getByRole('checkbox', { name: 'Unit' }).getAttribute('aria-checked')).toBe('true')
|
||||
expect(screen.getByRole('checkbox', { name: 'Types' }).getAttribute('aria-checked')).toBe('true')
|
||||
} finally {
|
||||
carrier.timeout()
|
||||
}
|
||||
})
|
||||
|
||||
it('starts only a recommended first choice of a single-select question selected', () => {
|
||||
const { carrier } = wait([
|
||||
{ id: 'first', question: 'First?', options: [{ label: 'A (Recommended)' }, { label: 'B (Recommended)' }] },
|
||||
{ id: 'later', question: 'Later?', options: [{ label: 'C' }, { label: 'D (Recommended)' }] },
|
||||
])
|
||||
render(<QuestionComposer matched={carrier} {...kit} />)
|
||||
expect(screen.getByRole('radio', { name: /A/ }).getAttribute('aria-checked')).toBe('true')
|
||||
expect(screen.getByRole('radio', { name: /B/ }).getAttribute('aria-checked')).toBe('false')
|
||||
expect(screen.getByRole('radio', { name: 'A' }).getAttribute('aria-checked')).toBe('true')
|
||||
expect(screen.getByRole('radio', { name: 'B' }).getAttribute('aria-checked')).toBe('false')
|
||||
|
||||
fireEvent.click(screen.getByLabelText('下一题'))
|
||||
expect(screen.getByRole('radio', { name: /C/ }).getAttribute('aria-checked')).toBe('false')
|
||||
expect(screen.getByRole('radio', { name: /D/ }).getAttribute('aria-checked')).toBe('false')
|
||||
expect(screen.getByRole('radio', { name: 'C' }).getAttribute('aria-checked')).toBe('false')
|
||||
expect(screen.getByRole('radio', { name: 'D' }).getAttribute('aria-checked')).toBe('false')
|
||||
})
|
||||
|
||||
it('treats Enter on an unselected option as submit, without selecting it', () => {
|
||||
@@ -1023,6 +1045,28 @@ describe('review card', () => {
|
||||
expect(screen.queryByPlaceholderText('输入你的答案')).toBeNull()
|
||||
})
|
||||
|
||||
it('shows recorded multi-select answers without restoring recommended defaults', () => {
|
||||
const questions: PendingQuestion['questions'] = [
|
||||
{
|
||||
id: 'checks', question: 'Which checks?', multiSelect: true,
|
||||
options: [{ label: 'Unit (Recommended)' }, { label: 'Lint' }, { label: 'Types (Recommended)' }],
|
||||
},
|
||||
{
|
||||
id: 'unrecorded', question: 'Which targets?', multiSelect: true,
|
||||
options: [{ label: 'Web (Recommended)' }, { label: 'Desktop' }],
|
||||
},
|
||||
]
|
||||
const carrier = new PendingQuestion(SID, questions, ToolCallId(REVIEWED_CALL), undefined, [{ id: 'checks', selected: ['Lint'] }])
|
||||
carrier.attachSeat({ hide: vi.fn() })
|
||||
render(<QuestionComposer matched={carrier} {...kit} />)
|
||||
|
||||
expect(screen.getByRole('checkbox', { name: 'Unit' }).getAttribute('aria-checked')).toBe('false')
|
||||
expect(screen.getByRole('checkbox', { name: 'Lint' }).getAttribute('aria-checked')).toBe('true')
|
||||
expect(screen.getByRole('checkbox', { name: 'Types' }).getAttribute('aria-checked')).toBe('false')
|
||||
fireEvent.click(screen.getByLabelText('下一题'))
|
||||
expect(screen.getByRole('checkbox', { name: 'Web' }).getAttribute('aria-checked')).toBe('false')
|
||||
})
|
||||
|
||||
it('reads the record back instead of a draft the live card left under the same key', () => {
|
||||
kit.actions.replace(PendingQuestion.keyOf(SID, REVIEWED_CALL), {
|
||||
index: 2,
|
||||
|
||||
Reference in new issue
Block a user