修复游戏场景队列回读时序
重读未收口的场景权威快照 补充场景队列完成回归测试 同步场景链路与排障约定
This commit is contained in:
@@ -1728,6 +1728,109 @@ describe('useImageCanvasGenerationSubmissionWorkflow', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('reloads the authoritative scene project when the first queued snapshot is unresolved', async () => {
|
||||
vi.useFakeTimers();
|
||||
try {
|
||||
const applyProjectSnapshot = vi.fn();
|
||||
const unresolvedProject = {
|
||||
projectId: 'editor-project-1',
|
||||
title: '场景队列项目',
|
||||
viewport: { x: 0, y: 0, scale: 1 },
|
||||
layers: [
|
||||
{
|
||||
layerId: 'generation-dialog-scene-queued',
|
||||
resourceId: 'generation-dialog-scene-queued',
|
||||
itemType: 'generation-dialog',
|
||||
dialog: {
|
||||
id: 'dialog-scene-queued',
|
||||
mode: 'scene',
|
||||
status: 'generating',
|
||||
},
|
||||
},
|
||||
],
|
||||
resources: [],
|
||||
updatedAt: '2026-08-06T08:00:00.000Z',
|
||||
};
|
||||
const completedProject = {
|
||||
...unresolvedProject,
|
||||
layers: [
|
||||
{
|
||||
layerId: 'layer-scene-result',
|
||||
resourceId: 'resource-scene-result',
|
||||
title: '游戏场景 1',
|
||||
assetKind: 'scene',
|
||||
},
|
||||
{
|
||||
layerId: 'generation-dialog-scene-queued',
|
||||
resourceId: 'generation-dialog-scene-queued',
|
||||
itemType: 'generation-dialog',
|
||||
dialog: {
|
||||
id: 'dialog-scene-queued',
|
||||
mode: 'scene',
|
||||
status: 'idle',
|
||||
generatedLayerId: 'layer-scene-result',
|
||||
},
|
||||
},
|
||||
],
|
||||
updatedAt: '2026-08-06T08:00:01.000Z',
|
||||
};
|
||||
generateEditorSceneMock.mockResolvedValueOnce({
|
||||
...createGenerated({ width: 1024, height: 576 }),
|
||||
queueState: createQueueState(),
|
||||
});
|
||||
loadEditorProjectMock
|
||||
.mockResolvedValueOnce(unresolvedProject)
|
||||
.mockResolvedValueOnce(completedProject);
|
||||
render(
|
||||
<SubmissionWorkflowHarness
|
||||
projectId="editor-project-1"
|
||||
applyProjectSnapshot={applyProjectSnapshot}
|
||||
initialDialog={{
|
||||
id: 'dialog-scene-queued',
|
||||
mode: 'scene',
|
||||
prompt: '雨夜海边车站',
|
||||
status: 'idle',
|
||||
composerOpen: true,
|
||||
sceneStylePreset: 'anime',
|
||||
sceneCustomStyle: '',
|
||||
generationReferences: [],
|
||||
imageModel: 'gemini-3.1-flash-image-preview',
|
||||
aspectRatio: '16:9',
|
||||
imageSize: '1K',
|
||||
placeholder: {
|
||||
x: 100,
|
||||
y: 100,
|
||||
width: 1024,
|
||||
height: 576,
|
||||
originalWidth: 1024,
|
||||
originalHeight: 576,
|
||||
},
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '设置初始对话' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: '提交当前生成' }));
|
||||
await act(async () => {
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
expect(loadEditorProjectMock).toHaveBeenCalledTimes(1);
|
||||
await act(async () => {
|
||||
await vi.advanceTimersByTimeAsync(650);
|
||||
});
|
||||
expect(loadEditorProjectMock).toHaveBeenCalledTimes(2);
|
||||
expect(applyProjectSnapshot).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
unresolvedProject,
|
||||
);
|
||||
expect(applyProjectSnapshot).toHaveBeenNthCalledWith(2, completedProject);
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
|
||||
it('does not add a local scene layer when the backend omits its project snapshot', async () => {
|
||||
generateEditorSceneMock.mockResolvedValueOnce(
|
||||
createGenerated({
|
||||
|
||||
@@ -2091,6 +2091,7 @@ export function useImageCanvasGenerationSubmissionWorkflow({
|
||||
onQueuedGenerationTask,
|
||||
onWalletBalanceMayHaveChanged,
|
||||
onGenerationWarning,
|
||||
canvasDialog?.id,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user