feat(design): render assistant activity progress

This commit is contained in:
brother7 committed 2026-09-07 09:57:21 +08:00
1 parent da29294979
commit 81b524a02c
9 files changed
+2066 -80

No files matched your search

+124
View File
@@ -52,6 +52,7 @@ function prepareWorkspace(overrides = {}) {
pendingOperations: {},
fieldDrafts: {},
chatDraft: '',
assistantActivities: {},
assistantStreams: {},
quoteBlockers: [],
error: null,
@@ -93,6 +94,37 @@ describe('youth AI Design Canvas page', () => {
expect(screen.queryByText(/规格版本|编译器|生成策略|字段决策/)).not.toBeInTheDocument();
});
it('does not disable the current composer for another Workspace command', () => {
prepareWorkspace();
useImageWorkspaceStore.setState({
chatDraft: '当前项目的新想法',
pendingOperations: {
'operation-workspace-2': {
id: 'operation-workspace-2',
label: '发送创作想法',
command: {
kind: 'apply_input',
workspaceId: 'workspace-2',
sessionId: 'session-2',
expectedDirectionRevision: 2,
clientOperationId: 'operation-workspace-2',
input: { kind: 'chat', message: '另一个项目还在处理' },
},
status: 'submitting',
error: null,
clearDraftPaths: [],
clearChatDraft: true,
baseRawTurnSequence: 1,
},
},
});
render(<ImageCanvas />);
expect(screen.getByRole('textbox', { name: '告诉 AI 你想创作什么' })).toBeEnabled();
expect(screen.getByRole('button', { name: '发送消息' })).toBeEnabled();
});
it('shows one unfinished assistant reply incrementally and replaces it with the canonical turn', async () => {
const { workspace } = prepareWorkspace();
const firstChunk = '收到,我们要制作';
@@ -115,6 +147,7 @@ describe('youth AI Design Canvas page', () => {
error: null,
clearDraftPaths: [],
clearChatDraft: true,
baseRawTurnSequence: 1,
},
},
});
@@ -165,6 +198,95 @@ describe('youth AI Design Canvas page', () => {
.toBeInTheDocument();
});
it('shows public AI activity under the submitted message and collapses it beside the final turn', async () => {
const message = '画一只在月球踢球的熊猫';
const { workspace } = prepareWorkspace({ turns: [] });
useImageWorkspaceStore.setState({
pendingOperations: {
'operation-chat-1': {
id: 'operation-chat-1',
label: '发送创作想法',
command: {
kind: 'apply_input',
workspaceId: 'workspace-1',
sessionId: 'session-1',
expectedDirectionRevision: 4,
clientOperationId: 'operation-chat-1',
input: { kind: 'chat', message },
},
status: 'submitting',
error: null,
clearDraftPaths: [],
clearChatDraft: true,
baseRawTurnSequence: 1,
},
},
assistantActivities: {
'operation-chat-1': {
workspaceId: 'workspace-1',
directionId: 'direction-1',
status: 'active',
turnId: null,
steps: [
{ stage: 'understanding', message: '正在听懂你刚补充的内容…' },
{ stage: 'reviewing_context', message: '正在把它和前面的设计想法放在一起看…' },
],
},
},
});
render(<ImageCanvas />);
const conversation = screen.getByTestId('image-workspace-conversation');
const pending = within(conversation).getByTestId('pending-design-chat-operation-chat-1');
const activity = within(conversation).getByTestId('design-assistant-activity-operation-chat-1');
expect(pending.compareDocumentPosition(activity) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
expect(within(activity).getByRole('button', { name: /AI 处理过程/ }))
.toHaveAttribute('aria-expanded', 'true');
expect(within(activity).getByText('正在听懂你刚补充的内容…')).toBeInTheDocument();
expect(within(activity).getAllByText('正在把它和前面的设计想法放在一起看…'))
.not.toHaveLength(0);
expect(within(activity).queryByText(/思考过程|推理内容/)).not.toBeInTheDocument();
act(() => {
useImageWorkspaceStore.setState({
workspace: {
...workspace,
turns: [{
turnId: 'turn-2',
rawTurnSequence: 2,
userMessage: message,
assistantMessage: '这个画面很有趣。你想让它更像漫画还是电影?',
}],
},
pendingOperations: {},
assistantActivities: {
'operation-chat-1': {
workspaceId: 'workspace-1',
directionId: 'direction-1',
status: 'completed',
turnId: 'turn-2',
steps: [
{ stage: 'understanding', message: '正在听懂你刚补充的内容…' },
{ stage: 'reviewing_context', message: '正在把它和前面的设计想法放在一起看…' },
],
},
},
});
});
const completedActivity = within(conversation)
.getByTestId('design-assistant-activity-operation-chat-1');
await waitFor(() => {
expect(within(completedActivity).getByRole('button', { name: /AI 处理过程/ }))
.toHaveAttribute('aria-expanded', 'false');
});
expect(within(completedActivity).queryByText('正在听懂你刚补充的内容…'))
.not.toBeInTheDocument();
fireEvent.click(within(completedActivity).getByRole('button', { name: /AI 处理过程/ }));
expect(within(completedActivity).getByText('正在听懂你刚补充的内容…')).toBeInTheDocument();
});
it('opens the mobile quote confirmation from the ready conversation without starting a paid task', async () => {
const { actions } = prepareWorkspace();
const quotedWorkspace = designWorkspaceFixture({
@@ -208,6 +330,7 @@ describe('youth AI Design Canvas page', () => {
error: null,
clearDraftPaths: [],
clearChatDraft: true,
baseRawTurnSequence: 1,
},
},
});
@@ -390,6 +513,7 @@ describe('youth AI Design Canvas page', () => {
error: '网络已断开',
clearDraftPaths: [],
clearChatDraft: false,
baseRawTurnSequence: null,
},
},
});