补齐完美像素既有结果对账回归
补充人工重试遇到损坏稳定资源时的 GET-only 对账冲突回归。 同步后端权威契约的稳定结果短路语义。
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -3330,6 +3330,81 @@ describe('useImageCanvasGenerationWorkflow', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('reconciles a retried existing-result marker against its corrupted stable resource as a conflict', async () => {
|
||||
const applyProjectSnapshot = vi.fn();
|
||||
let corruptedProject: EditorProjectSnapshot | undefined;
|
||||
snapImageToPerfectPixelsMock
|
||||
.mockImplementationOnce(async (request: EditorPixelArtSnapInput) =>
|
||||
createMismatchedPerfectPixelResult(request),
|
||||
)
|
||||
.mockImplementationOnce(async (request: EditorPixelArtSnapInput) => {
|
||||
const operationId = request.canvasCompletion.dialogId;
|
||||
corruptedProject = createPerfectPixelProject(
|
||||
operationId,
|
||||
'dialog-missing',
|
||||
);
|
||||
corruptedProject.resources[0] = {
|
||||
...corruptedProject.resources[0]!,
|
||||
taskId: 'pixel-art-snap-corrupted-task',
|
||||
objectKey: null,
|
||||
};
|
||||
throw new ApiClientError({
|
||||
message: '同一完美像素操作已有权威结果,请先读取项目状态对账。',
|
||||
status: 409,
|
||||
code: 'HTTP_409',
|
||||
details: {
|
||||
operationResultAlreadyExists: true,
|
||||
resultResourceId: corruptedProject.resources[0]!.resourceId,
|
||||
},
|
||||
});
|
||||
});
|
||||
loadEditorProjectMock.mockImplementation(async () => {
|
||||
const request = snapImageToPerfectPixelsMock.mock.calls.at(-1)?.[0] as
|
||||
| EditorPixelArtSnapInput
|
||||
| undefined;
|
||||
return snapImageToPerfectPixelsMock.mock.calls.length === 1
|
||||
? createConflictingPerfectPixelProject(
|
||||
request!.canvasCompletion.dialogId,
|
||||
)
|
||||
: corruptedProject!;
|
||||
});
|
||||
|
||||
render(
|
||||
<GenerationWorkflowHarness
|
||||
projectId="project-1"
|
||||
initialLayers={[
|
||||
createLayer({
|
||||
objectKey: 'generated-images/editor/source.png',
|
||||
src: '/generated-images/editor/source.png',
|
||||
}),
|
||||
]}
|
||||
applyProjectSnapshot={applyProjectSnapshot}
|
||||
flushProjectPersistence={vi.fn(async () => {})}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '完美像素' }));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('dialog').textContent).toContain(
|
||||
'pending-confirmation',
|
||||
);
|
||||
});
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '重试完美像素' }));
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('dialog-error').textContent).toContain(
|
||||
'完美像素任务资源记录不完整或不属于当前项目,无法自动确认结果。',
|
||||
);
|
||||
});
|
||||
|
||||
expect(snapImageToPerfectPixelsMock).toHaveBeenCalledTimes(2);
|
||||
expect(loadEditorProjectMock).toHaveBeenCalledTimes(2);
|
||||
expect(applyProjectSnapshot).not.toHaveBeenCalled();
|
||||
expect(screen.getByTestId('dialog').textContent).toContain(
|
||||
'pending-confirmation',
|
||||
);
|
||||
});
|
||||
|
||||
it('anchors the first submission reconciliation window at POST time when the pre-POST flush is slow', async () => {
|
||||
// 中文注释:pre-POST flush 是服务端硬前置(占位未持久化会被 409 拒收),且没有整体
|
||||
// 上限。窗口若锚在 flush 之前,慢保存会让 POST 带着已过期的 reconciliation deadline
|
||||
|
||||
Reference in New Issue
Block a user