补齐图片改造提交闭环测试

覆盖未知 legacy 图片回退普通生成的请求、配方、落图和面板终态
覆盖已知角色素材恢复原工具并提交角色规范引用的完整链路
同步图片画布架构文档中的定向测试门禁
This commit is contained in:
2026-08-11 11:30:21 +08:00
parent 3b1652721f
commit 49abc064e8
2 changed files with 130 additions and 5 deletions
File diff suppressed because one or more lines are too long
@@ -500,6 +500,14 @@ function GenerationWorkflowHarness({
)
.join('|')}
</span>
<span data-testid="layer-placements">
{layers
.map(
(layer) =>
`${layer.id}:${layer.x}:${layer.y}:${layer.width}:${layer.height}`,
)
.join('|')}
</span>
<span data-testid="dialog">
{activeDialog
? `${activeDialog.mode}:${activeDialog.status}:${activeDialog.composerOpen !== false ? 'open' : 'closed'}:${activeDialog.generatedLayerId ?? '-'}:${activeDialog.placeholder ? 'placeholder' : '-'}`
@@ -1592,10 +1600,26 @@ describe('useImageCanvasGenerationWorkflow', () => {
);
});
it('opens image remodel without an origin action in the default image tool', () => {
render(<GenerationWorkflowHarness />);
it('submits legacy image remodel without an origin action through the default image tool', async () => {
generateEditorImageMock.mockResolvedValueOnce(
createGenerated({ prompt: '旧版森林场景' }),
);
render(
<GenerationWorkflowHarness
initialLayers={[
createLayer({
sourceType: 'generated',
prompt: '【系统内置】旧版森林场景完整提示词',
model: IMAGE_MODEL_GPT_IMAGE_2,
generationInputs: {
fields: [{ title: '生成提示词', value: '旧版森林场景' }],
references: [],
},
}),
]}
/>,
);
fireEvent.click(screen.getByRole('button', { name: '打开生成' }));
fireEvent.click(screen.getByRole('button', { name: '打开图片改造' }));
expect(screen.getByTestId('dialog').textContent).toBe(
@@ -1603,8 +1627,109 @@ describe('useImageCanvasGenerationWorkflow', () => {
);
expect(screen.getByTestId('quick-edit').textContent).toBe('-');
expect(screen.getByTestId('placeholder').textContent).toContain('1024:768');
const expectedResultPlacement =
screen.getByTestId('placeholder').textContent;
fireEvent.click(screen.getByRole('button', { name: '提交生成' }));
await waitFor(() => {
expect(generateEditorImageMock).toHaveBeenCalledWith(
expect.objectContaining({
prompt: '旧版森林场景',
model: IMAGE_MODEL_GPT_IMAGE_2,
generationInputs: expect.objectContaining({
version: 2,
action: 'image.generate',
references: [],
}),
}),
);
});
const request = generateEditorImageMock.mock.calls[0]?.[0];
expect(request).not.toHaveProperty('referenceImageSrcs');
expect(request).not.toHaveProperty('sourceResourceId');
await waitFor(() => {
expect(screen.getByTestId('layers').textContent).toContain(
'layer-generated-1:生成图片 1:-:-',
);
});
expect(screen.getByTestId('layer-placements').textContent).toContain(
`layer-generated-1:${expectedResultPlacement}`,
);
expect(screen.getByTestId('dialog').textContent).toBe(
'generate:idle:open:layer-generated-1:placeholder',
);
expect(screen.getByTestId('generation-dialogs').textContent).toBe(
'generation-dialog-1:generate:closed|generation-dialog-2:generate:open',
'generation-dialog-1:generate:open',
);
});
it('submits legacy character remodel through the character tool selected by asset kind', async () => {
generateEditorImageMock.mockResolvedValueOnce(
createGenerated({ prompt: '红发骑士' }),
);
render(
<GenerationWorkflowHarness
initialLayers={[
createLayer({
title: '角色形象',
sourceType: 'generated',
assetKind: 'character',
prompt: '【系统内置】红发骑士完整提示词',
model: IMAGE_MODEL_GPT_IMAGE_2,
generationInputs: {
fields: [{ title: '角色设定', value: '红发骑士' }],
references: [],
},
}),
]}
/>,
);
fireEvent.click(screen.getByRole('button', { name: '打开图片改造' }));
expect(screen.getByTestId('dialog').textContent).toBe(
'character:idle:open:-:placeholder',
);
expect(screen.getByTestId('dialog-prompt').textContent).toBe('红发骑士');
const expectedResultPlacement =
screen.getByTestId('placeholder').textContent;
fireEvent.click(screen.getByRole('button', { name: '选择角色规范' }));
fireEvent.click(screen.getByRole('button', { name: '提交生成' }));
await waitFor(() => {
expect(generateEditorImageMock).toHaveBeenCalledWith(
expect.objectContaining({
prompt: '红发骑士',
kind: 'character',
model: IMAGE_MODEL_GPT_IMAGE_2,
referenceImageSrcs: ['resource-character-spec'],
generationInputs: expect.objectContaining({
version: 2,
action: 'character.generate',
references: [
expect.objectContaining({
id: 'specReference',
refType: 'project-resource',
refId: 'resource-character-spec',
}),
],
}),
}),
);
});
await waitFor(() => {
expect(screen.getByTestId('layers').textContent).toContain(
'layer-generated-1:角色形象 1:-:character',
);
});
expect(screen.getByTestId('layer-placements').textContent).toContain(
`layer-generated-1:${expectedResultPlacement}`,
);
expect(screen.getByTestId('dialog').textContent).toBe(
'character:idle:open:layer-generated-1:placeholder',
);
expect(screen.getByTestId('generation-dialogs').textContent).toBe(
'generation-dialog-1:character:open',
);
});