@@ -220,6 +220,33 @@ const baseProfile = {
|
||||
connections: [],
|
||||
},
|
||||
],
|
||||
sceneChapterBlueprints: [
|
||||
{
|
||||
id: 'scene-chapter-1',
|
||||
sceneId: 'landmark-1',
|
||||
title: '沉钟栈桥章节',
|
||||
summary: '围绕沉钟栈桥推进的三幕结构。',
|
||||
linkedThreadIds: [],
|
||||
linkedLandmarkIds: ['landmark-1'],
|
||||
acts: [
|
||||
{
|
||||
id: 'scene-act-1',
|
||||
sceneId: 'landmark-1',
|
||||
title: '潮声逼近',
|
||||
summary: '第一幕先把潮声与旧钟压上来。',
|
||||
stageCoverage: ['opening'],
|
||||
backgroundImageSrc: '/generated-custom-world-scenes/scene-act-1.png',
|
||||
backgroundAssetId: 'scene-asset-1',
|
||||
encounterNpcIds: ['story-1'],
|
||||
primaryNpcId: 'story-1',
|
||||
linkedThreadIds: [],
|
||||
advanceRule: 'after_primary_contact',
|
||||
actGoal: '接住首幕压力',
|
||||
transitionHook: '继续逼近钟楼深处。',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
creatorIntent: null,
|
||||
anchorPack: null,
|
||||
lockState: null,
|
||||
@@ -278,7 +305,7 @@ test('clicking新增可扮演角色 shows pending item, disables button, and mar
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('云止')).toBeTruthy();
|
||||
expect(screen.getByRole('button', { name: /云止/u })).toBeTruthy();
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
@@ -304,3 +331,70 @@ test('world basic setting renders eight anchor fields and hides legacy parsed/so
|
||||
expect(screen.getByText(/被海雾反复改写航路的群岛世界/u)).toBeTruthy();
|
||||
expect(screen.getByText(/沉钟异动和旧案灭口是同一条线/u)).toBeTruthy();
|
||||
});
|
||||
|
||||
test('playable tab prefers generated portrait over runtime preview placeholder', async () => {
|
||||
const user = userEvent.setup();
|
||||
const profile = {
|
||||
...baseProfile,
|
||||
playableNpcs: [
|
||||
{
|
||||
...createPlayableRole('playable-portrait', '云止'),
|
||||
imageSrc: '/generated-characters/playable-portrait/master.png',
|
||||
generatedVisualAssetId: 'visual-playable-portrait',
|
||||
},
|
||||
],
|
||||
} as CustomWorldProfile;
|
||||
|
||||
render(
|
||||
<CustomWorldResultView
|
||||
profile={profile}
|
||||
previewCharacters={[
|
||||
{
|
||||
id: 'playable-portrait',
|
||||
name: '云止',
|
||||
title: '同行者',
|
||||
description: '预览角色',
|
||||
backstory: '预览背景',
|
||||
personality: '预览性格',
|
||||
portrait: '/template/portrait.png',
|
||||
avatar: '/template/avatar.png',
|
||||
assetFolder: 'test',
|
||||
assetVariant: 'Hero',
|
||||
combatTags: [],
|
||||
skills: [],
|
||||
adventureOpenings: {},
|
||||
} as never,
|
||||
]}
|
||||
isGenerating={false}
|
||||
progress={0}
|
||||
progressLabel=""
|
||||
error={null}
|
||||
onBack={() => {}}
|
||||
onProfileChange={() => {}}
|
||||
/>,
|
||||
);
|
||||
|
||||
await user.click(screen.getByRole('button', { name: /可扮演角色/u }));
|
||||
|
||||
const portrait = screen.getByRole('img', { name: '云止' });
|
||||
expect((portrait as HTMLImageElement).getAttribute('src')).toBe(
|
||||
'/generated-characters/playable-portrait/master.png',
|
||||
);
|
||||
expect(screen.getByText('已生成主图')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('landmark tab uses first act image as scene card preview and keeps chapter details out of list', async () => {
|
||||
const user = userEvent.setup();
|
||||
|
||||
render(<ResultViewHarness />);
|
||||
|
||||
await user.click(screen.getByRole('button', { name: /场景\s*2/u }));
|
||||
|
||||
expect(screen.queryByText('沉钟栈桥章节')).toBeNull();
|
||||
expect(screen.queryByText('潮声逼近')).toBeNull();
|
||||
|
||||
const sceneImage = screen.getByRole('img', { name: '沉钟栈桥' });
|
||||
expect((sceneImage as HTMLImageElement).getAttribute('src')).toBe(
|
||||
'/generated-custom-world-scenes/scene-act-1.png',
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user