215 lines
6.6 KiB
TypeScript
215 lines
6.6 KiB
TypeScript
import { renderToStaticMarkup } from 'react-dom/server';
|
|
import { expect, test } from 'vitest';
|
|
|
|
import { derivePlatformCreationTypes } from '../platform-entry/platformEntryCreationTypes';
|
|
import type { CreationEntryConfig } from '../../services/creationEntryConfigService';
|
|
import { CustomWorldCreationHub } from './CustomWorldCreationHub';
|
|
|
|
const noopCreateType = () => {};
|
|
|
|
const testEntryConfig = {
|
|
startCard: {
|
|
title: '新建作品',
|
|
description: '选择模板后进入对应的创作表单。',
|
|
idleBadge: '模板 Tab',
|
|
busyBadge: '正在开启',
|
|
},
|
|
typeModal: {
|
|
title: '选择创作类型',
|
|
description: '先选玩法类型,再进入对应创作工作台。',
|
|
},
|
|
creationTypes: [
|
|
{
|
|
id: 'puzzle',
|
|
title: '拼图',
|
|
subtitle: '拼图关卡创作',
|
|
badge: '可创建',
|
|
imageSrc: '/creation-type-references/puzzle.webp',
|
|
visible: true,
|
|
open: true,
|
|
sortOrder: 30,
|
|
updatedAtMicros: 1,
|
|
},
|
|
{
|
|
id: 'match3d',
|
|
title: '抓大鹅',
|
|
subtitle: '3D 消除关卡',
|
|
badge: '可创建',
|
|
imageSrc: '/creation-type-references/match3d.webp',
|
|
visible: true,
|
|
open: true,
|
|
sortOrder: 40,
|
|
updatedAtMicros: 1,
|
|
},
|
|
{
|
|
id: 'square-hole',
|
|
title: '方洞',
|
|
subtitle: '形状投放挑战',
|
|
badge: '可创建',
|
|
imageSrc: '/creation-type-references/square-hole.webp',
|
|
visible: true,
|
|
open: true,
|
|
sortOrder: 50,
|
|
updatedAtMicros: 1,
|
|
},
|
|
{
|
|
id: 'visual-novel',
|
|
title: '视觉小说',
|
|
subtitle: '分支叙事体验',
|
|
badge: '可创建',
|
|
imageSrc: '/creation-type-references/visual-novel.webp',
|
|
visible: true,
|
|
open: true,
|
|
sortOrder: 60,
|
|
updatedAtMicros: 1,
|
|
},
|
|
{
|
|
id: 'airp',
|
|
title: 'AI RPG',
|
|
subtitle: '原生角色扮演',
|
|
badge: '即将开放',
|
|
imageSrc: '/creation-type-references/airp.webp',
|
|
visible: true,
|
|
open: false,
|
|
sortOrder: 70,
|
|
updatedAtMicros: 1,
|
|
},
|
|
],
|
|
} satisfies CreationEntryConfig;
|
|
|
|
const testCreationTypes = derivePlatformCreationTypes(testEntryConfig.creationTypes);
|
|
|
|
|
|
test('creation hub draft card renders compiled work summary fields', () => {
|
|
const html = renderToStaticMarkup(
|
|
<CustomWorldCreationHub
|
|
items={[
|
|
{
|
|
workId: 'draft:session-1',
|
|
sourceType: 'agent_session',
|
|
status: 'draft',
|
|
title: '一个被潮雾切开的列岛世界',
|
|
subtitle: '补齐关键锚点',
|
|
summary:
|
|
'玩家是失职返乡的守灯人 · 核心冲突:守灯会与沉船商盟争夺航道解释权',
|
|
coverImageSrc: null,
|
|
updatedAt: new Date('2026-04-13T12:00:00.000Z').toISOString(),
|
|
publishedAt: null,
|
|
stage: 'clarifying',
|
|
stageLabel: '补齐关键锚点',
|
|
playableNpcCount: 0,
|
|
landmarkCount: 0,
|
|
sessionId: 'session-1',
|
|
profileId: null,
|
|
canResume: true,
|
|
canEnterWorld: false,
|
|
},
|
|
]}
|
|
loading={false}
|
|
error={null}
|
|
onRetry={() => {}}
|
|
onCreateType={noopCreateType}
|
|
onOpenDraft={() => {}}
|
|
onEnterPublished={() => {}}
|
|
entryConfig={testEntryConfig}
|
|
creationTypes={testCreationTypes}
|
|
/>,
|
|
);
|
|
|
|
expect(html).toContain('一个被潮雾切开的列岛世界');
|
|
expect(html).toContain('玩家是失职返乡的守灯人');
|
|
expect(html).toContain('守灯会与沉船商盟争夺航道解释权');
|
|
expect(html).toContain('拼图');
|
|
expect(html).toContain('创意礼物,生活分享');
|
|
expect(html).toContain('抓大鹅');
|
|
expect(html).toContain('经典消除玩法');
|
|
expect(html).not.toContain('角色扮演');
|
|
expect(html).not.toContain('大鱼吃小鱼');
|
|
});
|
|
|
|
test('creation hub renders puzzle works in the same unified list with puzzle tag', () => {
|
|
const html = renderToStaticMarkup(
|
|
<CustomWorldCreationHub
|
|
items={[]}
|
|
puzzleItems={[
|
|
{
|
|
workId: 'puzzle:work-1',
|
|
profileId: 'puzzle-profile-1',
|
|
ownerUserId: 'user-1',
|
|
authorDisplayName: '测试作者',
|
|
levelName: '潮雾拼图',
|
|
summary: '一张被切成拼图的潮雾港口主视觉。',
|
|
themeTags: ['潮雾', '港口'],
|
|
coverImageSrc: null,
|
|
publicationStatus: 'published',
|
|
updatedAt: new Date('2026-04-22T10:00:00.000Z').toISOString(),
|
|
publishedAt: new Date('2026-04-22T10:05:00.000Z').toISOString(),
|
|
playCount: 12,
|
|
remixCount: 3,
|
|
likeCount: 4,
|
|
publishReady: true,
|
|
},
|
|
]}
|
|
loading={false}
|
|
error={null}
|
|
onRetry={() => {}}
|
|
onCreateType={noopCreateType}
|
|
onOpenDraft={() => {}}
|
|
onEnterPublished={() => {}}
|
|
entryConfig={testEntryConfig}
|
|
creationTypes={testCreationTypes}
|
|
onOpenPuzzleDetail={() => {}}
|
|
/>,
|
|
);
|
|
|
|
expect(html).toContain('潮雾拼图');
|
|
expect(html).toContain('拼图');
|
|
expect(html).toContain('aria-label="游玩 12次"');
|
|
expect(html).toContain('aria-label="改造 3次"');
|
|
expect(html).toContain('aria-label="点赞 4赞"');
|
|
expect(html).not.toContain('作品号');
|
|
expect(html).not.toContain('PZ-PROFILE1');
|
|
expect(html).not.toContain('潮雾</span>');
|
|
expect(html).not.toContain('港口</span>');
|
|
expect(html).not.toContain('我的拼图作品');
|
|
});
|
|
|
|
test('creation hub published work spans full mobile row', () => {
|
|
const html = renderToStaticMarkup(
|
|
<CustomWorldCreationHub
|
|
items={[]}
|
|
puzzleItems={[
|
|
{
|
|
workId: 'puzzle:work-1',
|
|
profileId: 'puzzle-profile-1',
|
|
ownerUserId: 'user-1',
|
|
authorDisplayName: '测试作者',
|
|
levelName: '潮雾拼图',
|
|
summary: '一张被切成拼图的潮雾港口主视觉。',
|
|
themeTags: ['潮雾', '港口'],
|
|
coverImageSrc: null,
|
|
publicationStatus: 'published',
|
|
updatedAt: new Date('2026-04-22T10:00:00.000Z').toISOString(),
|
|
publishedAt: new Date('2026-04-22T10:05:00.000Z').toISOString(),
|
|
playCount: 12,
|
|
likeCount: 0,
|
|
publishReady: true,
|
|
},
|
|
]}
|
|
loading={false}
|
|
error={null}
|
|
onRetry={() => {}}
|
|
onCreateType={noopCreateType}
|
|
onOpenDraft={() => {}}
|
|
onEnterPublished={() => {}}
|
|
entryConfig={testEntryConfig}
|
|
creationTypes={testCreationTypes}
|
|
onOpenPuzzleDetail={() => {}}
|
|
/>,
|
|
);
|
|
|
|
expect(html).toContain('grid-cols-2');
|
|
expect(html).toContain('col-span-2 sm:col-span-1');
|
|
expect(html).not.toContain('grid-cols-1 gap-3 md:grid-cols-2');
|
|
});
|