fix(pi): retain ownership for uncertain mutations
This commit is contained in:
@@ -2,6 +2,7 @@ import { act, fireEvent, render, screen, waitFor, within } from '@testing-librar
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { AppError } from '@/lib/error-model';
|
||||
import type { ConversationSnapshot } from '@/types/coding-conversation';
|
||||
import type {
|
||||
CodingConversationMetadata,
|
||||
@@ -596,6 +597,89 @@ describe('CodingChatPanel first Conversation', () => {
|
||||
await waitFor(() => expect(conversationApi.submit).toHaveBeenCalledTimes(2));
|
||||
});
|
||||
|
||||
it('clears a confirmation uncertainty automatically after the authoritative run settles', async () => {
|
||||
projectApi.list.mockResolvedValue({ projects: [project], activeProjectId: project.id });
|
||||
projectApi.config.mockResolvedValue({ project, config });
|
||||
projectApi.conversations.mockResolvedValue([conversation]);
|
||||
conversationApi.events.mockResolvedValue(new FakeEventSource() as unknown as EventSource);
|
||||
conversationApi.recover.mockResolvedValue(undefined);
|
||||
conversationApi.submit.mockRejectedValue(new AppError(
|
||||
'UNKNOWN',
|
||||
'请求确认延迟,可能仍在执行。请等待结果,或中止/恢复后再重试。',
|
||||
undefined,
|
||||
{ backendCode: 'CODING_REQUEST_UNCERTAIN' },
|
||||
));
|
||||
const { CodingChatPanel } = await import('@/pages/Chat/CodingChatPanel');
|
||||
const { createLocalConversationSnapshot } = await import('@/pages/Chat/coding-chat-snapshot');
|
||||
const { codingConversationStore } = await import('@/stores/coding-conversations');
|
||||
conversationApi.snapshot.mockResolvedValue(createLocalConversationSnapshot(project.id, conversation));
|
||||
render(<CodingChatPanel />);
|
||||
|
||||
const textbox = await screen.findByRole('textbox');
|
||||
await waitFor(() => expect(codingConversationStore.getState().selectedConversationId)
|
||||
.toBe(conversation.id));
|
||||
fireEvent.change(textbox, { target: { value: 'Slow prompt' } });
|
||||
fireEvent.click(screen.getByRole('button', { name: '发送' }));
|
||||
|
||||
expect(await screen.findByText(/请求确认延迟,可能仍在执行/)).toBeInTheDocument();
|
||||
expect(textbox).toHaveValue('Slow prompt');
|
||||
act(() => codingConversationStore.getState().applyPatchBatchEvent({
|
||||
type: 'patch-batch',
|
||||
conversationId: conversation.id,
|
||||
workerGeneration: 0,
|
||||
fromSeq: 1,
|
||||
toSeq: 1,
|
||||
items: [{
|
||||
seq: 1,
|
||||
at: 1_000,
|
||||
runId: 'run-uncertain',
|
||||
patch: {
|
||||
op: 'run.state',
|
||||
run: {
|
||||
status: 'running',
|
||||
runId: 'run-uncertain',
|
||||
mode: 'prompt',
|
||||
error: {
|
||||
code: 'CODING_REQUEST_UNCERTAIN',
|
||||
message: '请求确认延迟,可能仍在执行。',
|
||||
recoverable: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}],
|
||||
}));
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: '整理上下文' })).toBeDisabled());
|
||||
|
||||
act(() => codingConversationStore.getState().applyPatchBatchEvent({
|
||||
type: 'patch-batch',
|
||||
conversationId: conversation.id,
|
||||
workerGeneration: 0,
|
||||
fromSeq: 2,
|
||||
toSeq: 2,
|
||||
items: [{
|
||||
seq: 2,
|
||||
at: 12_000,
|
||||
runId: 'run-uncertain',
|
||||
patch: {
|
||||
op: 'run.state',
|
||||
run: {
|
||||
status: 'idle',
|
||||
runId: 'run-uncertain',
|
||||
mode: 'prompt',
|
||||
settledAt: 12_000,
|
||||
terminalReason: 'completed',
|
||||
},
|
||||
},
|
||||
}],
|
||||
}));
|
||||
|
||||
await waitFor(() => expect(screen.queryByText(/请求确认延迟,可能仍在执行/))
|
||||
.not.toBeInTheDocument());
|
||||
expect(screen.queryByText(/本地编程运行时暂时不可用/)).not.toBeInTheDocument();
|
||||
expect(textbox).toHaveValue('Slow prompt');
|
||||
expect(screen.getByRole('button', { name: '发送' })).toBeEnabled();
|
||||
});
|
||||
|
||||
it('caps one message at 16 images and uploads at most four concurrently', async () => {
|
||||
projectApi.list.mockResolvedValue({ projects: [project], activeProjectId: project.id });
|
||||
projectApi.config.mockResolvedValue({ project, config });
|
||||
|
||||
Reference in New Issue
Block a user