This commit is contained in:
2026-05-05 14:40:41 +08:00
parent e847fcea6f
commit 07e777fef8
76 changed files with 4246 additions and 444 deletions

View File

@@ -15,6 +15,7 @@ vi.mock('../services/rpg-creation/rpgCreationAssetClient', () => {
const generateLandmark = vi.fn();
const generateSceneImage = vi.fn();
const generateSceneNpc = vi.fn();
const generateOpeningCg = vi.fn();
return {
rpgCreationAssetClient: {
@@ -23,6 +24,7 @@ vi.mock('../services/rpg-creation/rpgCreationAssetClient', () => {
generateLandmark,
generateSceneImage,
generateSceneNpc,
generateOpeningCg,
},
generateCustomWorldPlayableNpc: generatePlayableNpc,
generateCustomWorldStoryNpc: generateStoryNpc,
@@ -343,6 +345,46 @@ test('world basic setting renders eight anchor fields and hides legacy parsed/so
expect(screen.getByText(/线/u)).toBeTruthy();
});
test('world tab generates opening cg only after manual click and writes it back to profile', async () => {
const user = userEvent.setup();
mockedRpgCreationAssetClient.generateOpeningCg.mockResolvedValue({
id: 'opening-cg-1',
status: 'ready',
storyboardImageSrc: '/generated-custom-world-scenes/world/opening/storyboard.png',
storyboardAssetId: 'storyboard-1',
videoSrc: '/generated-custom-world-scenes/world/opening/opening.mp4',
videoAssetId: 'video-1',
imageModel: 'gpt-image-2',
videoModel: 'doubao-seedance-2-0-fast-260128',
aspectRatio: '16:9',
imageSize: '2k',
videoResolution: '480p',
durationSeconds: 15,
pointCost: 80,
estimatedWaitMinutes: 10,
updatedAt: '2026-05-03T00:00:00Z',
});
render(<ResultViewHarness />);
expect(mockedRpgCreationAssetClient.generateOpeningCg).not.toHaveBeenCalled();
await user.click(screen.getByRole('button', { name: '生成' }));
await waitFor(() => {
expect(mockedRpgCreationAssetClient.generateOpeningCg).toHaveBeenCalledTimes(
1,
);
});
await waitFor(() => {
expect(
document.querySelector(
'video[src="/generated-custom-world-scenes/world/opening/opening.mp4"]',
),
).toBeTruthy();
});
});
test('playable tab prefers generated portrait over runtime preview placeholder', async () => {
const user = userEvent.setup();
const profile = {