Switch to VectorEngine gpt-image-2 and edits
Replace uses of the legacy `gpt-image-2-all` model with `gpt-image-2` and standardize image workflows: no-reference generation uses POST /v1/images/generations, any-reference flows use POST /v1/images/edits with multipart `image` parts. Update SKILLs, generation scripts, decision logs, and docs to reflect the contract change and edits-vs-generations guidance. Apply corresponding changes across backend (api-server match3d/puzzle modules, openai image adapter, mappers, telemetry, spacetime client/module), frontend components and services (Match3D, Puzzle, CreativeImageInputPanel, runtime shells), and add new spritesheet/parser files and tests. Also add media/logo.png. These changes align repository code and documentation with the VectorEngine image API contract and update generation/upload handling (green-screen -> alpha processing, spritesheet handling, and related tests).
This commit is contained in:
@@ -14,6 +14,10 @@ import * as match3dWorksService from '../../services/match3d-works';
|
||||
import { clearMatch3DGeneratedModelBytesCache } from '../../services/match3dGeneratedModelCache';
|
||||
import { Match3DResultView } from './Match3DResultView';
|
||||
|
||||
const match3dSpritesheetParser = vi.hoisted(() => ({
|
||||
loadMatch3DSpritesheetAssetRegions: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('../ResolvedAssetImage', () => ({
|
||||
ResolvedAssetImage: ({
|
||||
src,
|
||||
@@ -45,9 +49,20 @@ vi.mock('../../services/match3d-works', () => ({
|
||||
updateMatch3DWork: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('../../services/match3dSpritesheetParser', async (importOriginal) => {
|
||||
const actual =
|
||||
await importOriginal<typeof import('../../services/match3dSpritesheetParser')>();
|
||||
return {
|
||||
...actual,
|
||||
loadMatch3DSpritesheetAssetRegions:
|
||||
match3dSpritesheetParser.loadMatch3DSpritesheetAssetRegions,
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
clearMatch3DGeneratedModelBytesCache();
|
||||
vi.clearAllMocks();
|
||||
match3dSpritesheetParser.loadMatch3DSpritesheetAssetRegions.mockReset();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
@@ -687,8 +702,10 @@ describe('Match3DResultView', () => {
|
||||
expect(screen.queryByRole('button', { name: '音乐' })).toBeNull();
|
||||
fireEvent.click(screen.getByRole('button', { name: '素材配置' }));
|
||||
expect(screen.getByRole('button', { name: '物品' })).toBeTruthy();
|
||||
expect(screen.getByRole('button', { name: 'UI' })).toBeTruthy();
|
||||
expect(screen.getByRole('button', { name: 'UI素材' })).toBeTruthy();
|
||||
expect(screen.queryByRole('button', { name: '背景音乐' })).toBeNull();
|
||||
expect(screen.getAllByRole('button', { name: /打开.+物品素材/u }))
|
||||
.toHaveLength(20);
|
||||
|
||||
fireEvent.click(
|
||||
screen.getByRole('button', { name: '打开水果核心物件物品素材' }),
|
||||
@@ -1075,7 +1092,7 @@ describe('Match3DResultView', () => {
|
||||
);
|
||||
});
|
||||
expect(screen.getByText('63 件')).toBeTruthy();
|
||||
expect(screen.getAllByText('21 种').length).toBeGreaterThan(0);
|
||||
expect(screen.getAllByText('20 种').length).toBeGreaterThan(0);
|
||||
expect(onSaved).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
clearCount: 21,
|
||||
@@ -1323,13 +1340,32 @@ describe('Match3DResultView', () => {
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
test('素材配置 UI 子 Tab 展示默认提示词并支持预览UI页面', () => {
|
||||
test('素材配置 UI素材子 Tab 仅预览背景图和UI spritesheet', () => {
|
||||
render(
|
||||
<Match3DResultView
|
||||
profile={createProfile({
|
||||
backgroundPrompt: '果园主题抓大鹅竖屏背景',
|
||||
backgroundImageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/background.png',
|
||||
generatedBackgroundAsset: {
|
||||
prompt: '果园主题抓大鹅竖屏背景',
|
||||
levelScenePrompt: '果园完整关卡画面',
|
||||
levelSceneImageSrc:
|
||||
'/generated-match3d-assets/session/profile/level-scene/scene.png',
|
||||
levelSceneImageObjectKey: null,
|
||||
imageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/background.png',
|
||||
imageObjectKey: null,
|
||||
uiSpritesheetPrompt: 'UI spritesheet',
|
||||
uiSpritesheetImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-spritesheet/ui.png',
|
||||
uiSpritesheetImageObjectKey: null,
|
||||
containerPrompt: null,
|
||||
containerImageSrc: null,
|
||||
containerImageObjectKey: null,
|
||||
status: 'image_ready',
|
||||
error: null,
|
||||
},
|
||||
})}
|
||||
onBack={() => {}}
|
||||
onStartTestRun={() => {}}
|
||||
@@ -1337,15 +1373,18 @@ describe('Match3DResultView', () => {
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '素材配置' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'UI' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'UI素材' }));
|
||||
|
||||
expect(screen.getByAltText('游戏背景图').getAttribute('src')).toBe(
|
||||
'/generated-match3d-assets/session/profile/background/background.png',
|
||||
);
|
||||
expect(screen.getByLabelText('UI背景图画面描述提示词')).toHaveProperty(
|
||||
'value',
|
||||
'果园主题抓大鹅竖屏背景',
|
||||
expect(screen.getByAltText('UI素材图').getAttribute('src')).toBe(
|
||||
'/generated-match3d-assets/session/profile/ui-spritesheet/ui.png',
|
||||
);
|
||||
expect(
|
||||
screen.queryByLabelText('UI背景图画面描述提示词'),
|
||||
).toBeNull();
|
||||
expect(screen.queryByRole('button', { name: /重新生成/u })).toBeNull();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '预览UI页面' }));
|
||||
expect(screen.getByRole('dialog', { name: 'UI预览' })).toBeTruthy();
|
||||
@@ -1359,7 +1398,7 @@ describe('Match3DResultView', () => {
|
||||
'img[src="/match3d-background-references/pot-fused-reference.png"]',
|
||||
);
|
||||
expect(containerImage).toBeTruthy();
|
||||
expect(containerImage?.className).toContain('w-[min(108vw,38rem)]');
|
||||
expect(containerImage?.className).toContain('w-[min(116vw,42rem)]');
|
||||
expect(containerImage?.className).toContain('-translate-x-1/2');
|
||||
expect(
|
||||
document.querySelector('.animate-spin, [class*="border-l-transparent"]'),
|
||||
@@ -1371,7 +1410,7 @@ describe('Match3DResultView', () => {
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
test('素材配置 UI 子 Tab 从物品挂载资产展示生成背景和容器', async () => {
|
||||
test('素材配置 UI素材子 Tab 从物品挂载资产展示生成背景和UI spritesheet', async () => {
|
||||
const onStartTestRun = vi.fn();
|
||||
const profile = createProfile({
|
||||
backgroundPrompt: null,
|
||||
@@ -1388,11 +1427,14 @@ describe('Match3DResultView', () => {
|
||||
'/generated-match3d-assets/session/profile/background/background.png',
|
||||
imageObjectKey:
|
||||
'generated-match3d-assets/session/profile/background/background.png',
|
||||
containerPrompt: '果园容器',
|
||||
containerImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-container/container.png',
|
||||
containerImageObjectKey:
|
||||
'generated-match3d-assets/session/profile/ui-container/container.png',
|
||||
uiSpritesheetPrompt: '果园UI素材',
|
||||
uiSpritesheetImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-spritesheet/ui.png',
|
||||
uiSpritesheetImageObjectKey:
|
||||
'generated-match3d-assets/session/profile/ui-spritesheet/ui.png',
|
||||
containerPrompt: null,
|
||||
containerImageSrc: null,
|
||||
containerImageObjectKey: null,
|
||||
status: 'image_ready',
|
||||
error: null,
|
||||
},
|
||||
@@ -1417,15 +1459,16 @@ describe('Match3DResultView', () => {
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '素材配置' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'UI' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'UI素材' }));
|
||||
|
||||
expect(screen.getByAltText('游戏背景图').getAttribute('src')).toBe(
|
||||
'/generated-match3d-assets/session/profile/background/background.png',
|
||||
);
|
||||
expect(screen.getByLabelText('UI背景图画面描述提示词')).toHaveProperty(
|
||||
'value',
|
||||
'果园背景',
|
||||
expect(screen.getByAltText('UI素材图').getAttribute('src')).toBe(
|
||||
'/generated-match3d-assets/session/profile/ui-spritesheet/ui.png',
|
||||
);
|
||||
expect(screen.queryByLabelText('UI背景图画面描述提示词')).toBeNull();
|
||||
expect(screen.queryByRole('button', { name: /重新生成/u })).toBeNull();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '预览UI页面' }));
|
||||
expect(
|
||||
@@ -1435,14 +1478,14 @@ describe('Match3DResultView', () => {
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
document.querySelector(
|
||||
'img[src="/generated-match3d-assets/session/profile/ui-container/container.png"]',
|
||||
'img[src="/generated-match3d-assets/session/profile/ui-spritesheet/ui.png"]',
|
||||
),
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
document.querySelector(
|
||||
'img[src="/match3d-background-references/pot-fused-reference.png"]',
|
||||
),
|
||||
).toBeNull();
|
||||
).toBeTruthy();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '试玩' }));
|
||||
|
||||
@@ -1455,8 +1498,8 @@ describe('Match3DResultView', () => {
|
||||
generatedBackgroundAsset: expect.objectContaining({
|
||||
imageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/background.png',
|
||||
containerImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-container/container.png',
|
||||
uiSpritesheetImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-spritesheet/ui.png',
|
||||
}),
|
||||
}),
|
||||
{
|
||||
@@ -1466,7 +1509,81 @@ describe('Match3DResultView', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('素材配置 UI 子 Tab 修改提示词后调用背景图生成接口并刷新素材', async () => {
|
||||
test('素材配置 UI素材子 Tab 预览物品spritesheet解析结果', async () => {
|
||||
match3dSpritesheetParser.loadMatch3DSpritesheetAssetRegions.mockResolvedValue(
|
||||
Array.from({ length: 100 }, (_, index) => ({
|
||||
label: `素材${index + 1}`,
|
||||
x: index * 2,
|
||||
y: 0,
|
||||
width: 2,
|
||||
height: 2,
|
||||
sheetWidth: 200,
|
||||
sheetHeight: 2,
|
||||
imageSrc: `data:image/png;base64,item-${index + 1}`,
|
||||
})),
|
||||
);
|
||||
|
||||
render(
|
||||
<Match3DResultView
|
||||
profile={createProfile({
|
||||
generatedItemAssets: [
|
||||
{ ...createReadyGeneratedItemAsset(1), itemName: '草莓' },
|
||||
{ ...createReadyGeneratedItemAsset(2), itemName: '苹果' },
|
||||
],
|
||||
generatedBackgroundAsset: {
|
||||
prompt: '果园主题抓大鹅竖屏背景',
|
||||
imageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/background.png',
|
||||
imageObjectKey: null,
|
||||
uiSpritesheetPrompt: 'UI spritesheet',
|
||||
uiSpritesheetImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-spritesheet/ui.png',
|
||||
uiSpritesheetImageObjectKey: null,
|
||||
itemSpritesheetPrompt: '物品 spritesheet',
|
||||
itemSpritesheetImageSrc:
|
||||
'/generated-match3d-assets/session/profile/item-spritesheet/items.png',
|
||||
itemSpritesheetImageObjectKey: null,
|
||||
status: 'image_ready',
|
||||
error: null,
|
||||
},
|
||||
})}
|
||||
onBack={() => {}}
|
||||
onStartTestRun={() => {}}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '素材配置' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'UI素材' }));
|
||||
|
||||
expect(screen.getByAltText('物品素材图').getAttribute('src')).toBe(
|
||||
'/generated-match3d-assets/session/profile/item-spritesheet/items.png',
|
||||
);
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen
|
||||
.getByTestId('match3d-item-spritesheet-preview-0-0')
|
||||
.getAttribute('src'),
|
||||
).toBe('data:image/png;base64,item-1');
|
||||
expect(
|
||||
screen
|
||||
.getByTestId('match3d-item-spritesheet-preview-1-4')
|
||||
.getAttribute('src'),
|
||||
).toBe('data:image/png;base64,item-10');
|
||||
});
|
||||
expect(screen.getByText('草莓')).toBeTruthy();
|
||||
expect(screen.getByText('苹果')).toBeTruthy();
|
||||
expect(
|
||||
match3dSpritesheetParser.loadMatch3DSpritesheetAssetRegions,
|
||||
).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
maxRegions: 100,
|
||||
source:
|
||||
'/generated-match3d-assets/session/profile/item-spritesheet/items.png',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('素材配置 UI素材子 Tab 不提供背景或容器重新生成入口', () => {
|
||||
const profile = createProfile({
|
||||
generatedItemAssets: [
|
||||
{
|
||||
@@ -1500,267 +1617,24 @@ describe('Match3DResultView', () => {
|
||||
error: null,
|
||||
},
|
||||
});
|
||||
const nextProfile = createProfile({
|
||||
...profile,
|
||||
backgroundPrompt: '新背景提示词',
|
||||
backgroundImageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/new/background.png',
|
||||
generatedItemAssets: [
|
||||
{
|
||||
...profile.generatedItemAssets![0]!,
|
||||
backgroundAsset: {
|
||||
prompt: '新背景提示词',
|
||||
imageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/new/background.png',
|
||||
imageObjectKey:
|
||||
'generated-match3d-assets/session/profile/background/new/background.png',
|
||||
containerPrompt: '新容器提示词',
|
||||
containerImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-container/new/container.png',
|
||||
containerImageObjectKey:
|
||||
'generated-match3d-assets/session/profile/ui-container/new/container.png',
|
||||
status: 'image_ready',
|
||||
error: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
generatedBackgroundAsset: {
|
||||
prompt: '新背景提示词',
|
||||
imageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/new/background.png',
|
||||
imageObjectKey:
|
||||
'generated-match3d-assets/session/profile/background/new/background.png',
|
||||
containerPrompt: '新容器提示词',
|
||||
containerImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-container/new/container.png',
|
||||
containerImageObjectKey:
|
||||
'generated-match3d-assets/session/profile/ui-container/new/container.png',
|
||||
status: 'image_ready',
|
||||
error: null,
|
||||
},
|
||||
});
|
||||
const onSaved = vi.fn();
|
||||
vi.mocked(
|
||||
match3dWorksService.generateMatch3DBackgroundImage,
|
||||
).mockResolvedValue({
|
||||
item: nextProfile,
|
||||
backgroundImageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/new/background.png',
|
||||
backgroundImageObjectKey:
|
||||
'generated-match3d-assets/session/profile/background/new/background.png',
|
||||
generatedBackgroundAsset: nextProfile.generatedBackgroundAsset!,
|
||||
prompt: '新背景提示词',
|
||||
});
|
||||
|
||||
render(
|
||||
<Match3DResultView
|
||||
profile={profile}
|
||||
onBack={() => {}}
|
||||
onSaved={onSaved}
|
||||
onStartTestRun={() => {}}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '素材配置' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'UI' }));
|
||||
fireEvent.change(screen.getByLabelText('UI背景图画面描述提示词'), {
|
||||
target: { value: '新背景提示词' },
|
||||
});
|
||||
expect(
|
||||
screen.getByRole('button', { name: /重新生成 · 2泥点/u }),
|
||||
).toBeTruthy();
|
||||
fireEvent.click(screen.getByRole('button', { name: /重新生成/u }));
|
||||
expect(screen.getByRole('dialog', { name: '确认消耗泥点' })).toBeTruthy();
|
||||
confirmPointCost();
|
||||
fireEvent.click(screen.getByRole('button', { name: 'UI素材' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
match3dWorksService.generateMatch3DBackgroundImage,
|
||||
).toHaveBeenCalledWith(profile.profileId, {
|
||||
prompt: '新背景提示词',
|
||||
});
|
||||
expect(onSaved).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
generatedItemAssets: [
|
||||
expect.objectContaining({
|
||||
itemId: 'match3d-item-1',
|
||||
backgroundAsset: expect.objectContaining({
|
||||
prompt: '新背景提示词',
|
||||
imageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/new/background.png',
|
||||
containerImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-container/new/container.png',
|
||||
}),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('素材配置 UI 子 Tab 重新生成后显示90秒倒计时进度', async () => {
|
||||
const deferred =
|
||||
createDeferred<
|
||||
Awaited<
|
||||
ReturnType<typeof match3dWorksService.generateMatch3DBackgroundImage>
|
||||
>
|
||||
>();
|
||||
vi.mocked(
|
||||
match3dWorksService.generateMatch3DBackgroundImage,
|
||||
).mockReturnValue(deferred.promise);
|
||||
|
||||
render(
|
||||
<Match3DResultView
|
||||
profile={createProfile({
|
||||
generatedBackgroundAsset: {
|
||||
prompt: '旧背景提示词',
|
||||
imageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/old/background.png',
|
||||
imageObjectKey:
|
||||
'generated-match3d-assets/session/profile/background/old/background.png',
|
||||
containerPrompt: '旧容器提示词',
|
||||
containerImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-container/old/container.png',
|
||||
containerImageObjectKey:
|
||||
'generated-match3d-assets/session/profile/ui-container/old/container.png',
|
||||
status: 'image_ready',
|
||||
error: null,
|
||||
},
|
||||
})}
|
||||
onBack={() => {}}
|
||||
onStartTestRun={() => {}}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '素材配置' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: 'UI' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: /重新生成/u }));
|
||||
confirmPointCost();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
screen.getByRole('progressbar', { name: 'UI背景图生成进度' }),
|
||||
).toBeTruthy();
|
||||
expect(screen.getByText('预计剩余 90 秒')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
test('素材配置容器形象子 Tab 单独调用容器图生成接口并刷新素材', async () => {
|
||||
const profile = createProfile({
|
||||
generatedBackgroundAsset: {
|
||||
prompt: '旧背景提示词',
|
||||
imageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/old/background.png',
|
||||
imageObjectKey:
|
||||
'generated-match3d-assets/session/profile/background/old/background.png',
|
||||
containerPrompt: '旧容器提示词',
|
||||
containerImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-container/old/container.png',
|
||||
containerImageObjectKey:
|
||||
'generated-match3d-assets/session/profile/ui-container/old/container.png',
|
||||
status: 'image_ready',
|
||||
error: null,
|
||||
},
|
||||
generatedItemAssets: [
|
||||
{
|
||||
...createReadyGeneratedItemAsset(1),
|
||||
backgroundAsset: {
|
||||
prompt: '旧背景提示词',
|
||||
imageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/old/background.png',
|
||||
imageObjectKey:
|
||||
'generated-match3d-assets/session/profile/background/old/background.png',
|
||||
containerPrompt: '旧容器提示词',
|
||||
containerImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-container/old/container.png',
|
||||
containerImageObjectKey:
|
||||
'generated-match3d-assets/session/profile/ui-container/old/container.png',
|
||||
status: 'image_ready',
|
||||
error: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const nextBackgroundAsset = {
|
||||
prompt: '旧背景提示词',
|
||||
imageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/old/background.png',
|
||||
imageObjectKey:
|
||||
'generated-match3d-assets/session/profile/background/old/background.png',
|
||||
containerPrompt: '新容器提示词',
|
||||
containerImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-container/new/container.png',
|
||||
containerImageObjectKey:
|
||||
'generated-match3d-assets/session/profile/ui-container/new/container.png',
|
||||
status: 'image_ready',
|
||||
error: null,
|
||||
};
|
||||
const nextProfile = createProfile({
|
||||
...profile,
|
||||
generatedBackgroundAsset: nextBackgroundAsset,
|
||||
generatedItemAssets: [
|
||||
{
|
||||
...profile.generatedItemAssets![0]!,
|
||||
backgroundAsset: nextBackgroundAsset,
|
||||
},
|
||||
],
|
||||
});
|
||||
const onSaved = vi.fn();
|
||||
vi.mocked(
|
||||
match3dWorksService.generateMatch3DContainerImage,
|
||||
).mockResolvedValue({
|
||||
item: nextProfile,
|
||||
containerImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-container/new/container.png',
|
||||
containerImageObjectKey:
|
||||
'generated-match3d-assets/session/profile/ui-container/new/container.png',
|
||||
generatedBackgroundAsset: nextBackgroundAsset,
|
||||
prompt: '新容器提示词',
|
||||
});
|
||||
|
||||
render(
|
||||
<Match3DResultView
|
||||
profile={profile}
|
||||
onBack={() => {}}
|
||||
onSaved={onSaved}
|
||||
onStartTestRun={() => {}}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '素材配置' }));
|
||||
fireEvent.click(screen.getByRole('button', { name: '容器形象' }));
|
||||
fireEvent.change(screen.getByLabelText('容器形象画面描述提示词'), {
|
||||
target: { value: '新容器提示词' },
|
||||
});
|
||||
fireEvent.click(screen.getByRole('button', { name: /重新生成/u }));
|
||||
confirmPointCost();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
match3dWorksService.generateMatch3DContainerImage,
|
||||
).toHaveBeenCalledWith(profile.profileId, {
|
||||
prompt: '新容器提示词',
|
||||
});
|
||||
expect(
|
||||
match3dWorksService.generateMatch3DBackgroundImage,
|
||||
).not.toHaveBeenCalled();
|
||||
expect(onSaved).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
generatedItemAssets: [
|
||||
expect.objectContaining({
|
||||
itemId: 'match3d-item-1',
|
||||
backgroundAsset: expect.objectContaining({
|
||||
prompt: '旧背景提示词',
|
||||
imageSrc:
|
||||
'/generated-match3d-assets/session/profile/background/old/background.png',
|
||||
containerImageSrc:
|
||||
'/generated-match3d-assets/session/profile/ui-container/new/container.png',
|
||||
}),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
);
|
||||
});
|
||||
expect(screen.queryByLabelText('UI背景图画面描述提示词')).toBeNull();
|
||||
expect(screen.queryByLabelText('容器形象画面描述提示词')).toBeNull();
|
||||
expect(screen.queryByRole('button', { name: '容器形象' })).toBeNull();
|
||||
expect(screen.queryByRole('button', { name: /重新生成/u })).toBeNull();
|
||||
expect(match3dWorksService.generateMatch3DBackgroundImage).not.toHaveBeenCalled();
|
||||
expect(match3dWorksService.generateMatch3DContainerImage).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('历史草稿同时带旧 draft 和 profile 素材时以 profile 多视角素材补齐试玩资产', async () => {
|
||||
|
||||
Reference in New Issue
Block a user