feat(design): render assistant activity progress
This commit is contained in:
1 parent
da29294979
commit
81b524a02c
9 files changed
+2066
-80
No files matched your search
@@ -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,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user