refactor: 收口草稿生成作品架模型
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,189 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
|
||||
import { buildCreationWorkShelfItems } from '../custom-world-home/creationWorkShelf';
|
||||
import {
|
||||
buildCreationWorkShelfRuntimeState,
|
||||
buildPendingPuzzleWorks,
|
||||
buildPuzzleResultProfileId,
|
||||
buildPuzzleResultWorkId,
|
||||
collectVisibleDraftNoticeKeys,
|
||||
createPendingDraftShelfState,
|
||||
type DraftGenerationNoticeMap,
|
||||
getGenerationNoticeShelfKeys,
|
||||
hasUnreadDraftGenerationUpdates,
|
||||
} from './platformDraftGenerationShelfModel';
|
||||
|
||||
describe('platformDraftGenerationShelfModel', () => {
|
||||
test('buildPendingPuzzleWorks creates failed puzzle placeholder with stable ids and fallback title', () => {
|
||||
const pending = buildPendingPuzzleWorks(
|
||||
{
|
||||
'puzzle-session-ocean': createPendingDraftShelfState(
|
||||
'failed',
|
||||
false,
|
||||
'2026-06-03T08:00:00.000Z',
|
||||
),
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
expect(pending).toHaveLength(1);
|
||||
expect(pending[0]).toMatchObject({
|
||||
workId: 'puzzle-work-ocean',
|
||||
profileId: 'puzzle-profile-ocean',
|
||||
sourceSessionId: 'puzzle-session-ocean',
|
||||
workTitle: '拼图草稿',
|
||||
summary: '拼图草稿生成失败,可重新打开处理。',
|
||||
generationStatus: 'failed',
|
||||
});
|
||||
});
|
||||
|
||||
test('buildPendingPuzzleWorks skips pending item when backend shelf already has the session', () => {
|
||||
const pending = buildPendingPuzzleWorks(
|
||||
{
|
||||
'puzzle-session-ocean': createPendingDraftShelfState(
|
||||
'generating',
|
||||
false,
|
||||
'2026-06-03T08:00:00.000Z',
|
||||
),
|
||||
},
|
||||
[buildPuzzleWork({ sourceSessionId: 'puzzle-session-ocean' })],
|
||||
);
|
||||
|
||||
expect(pending).toEqual([]);
|
||||
});
|
||||
|
||||
test('buildCreationWorkShelfRuntimeState lets failure notice override persisted generating puzzle copy', () => {
|
||||
const [item] = buildCreationWorkShelfItems({
|
||||
rpgItems: [],
|
||||
bigFishItems: [],
|
||||
puzzleItems: [
|
||||
buildPuzzleWork({
|
||||
workId: 'puzzle-work-empty',
|
||||
profileId: 'puzzle-profile-empty',
|
||||
sourceSessionId: 'puzzle-session-empty',
|
||||
workTitle: '',
|
||||
workDescription: '',
|
||||
levelName: '',
|
||||
summary: '正在生成拼图草稿。',
|
||||
generationStatus: 'generating',
|
||||
}),
|
||||
],
|
||||
});
|
||||
expect(item).toBeTruthy();
|
||||
|
||||
const noticeKeys = getGenerationNoticeShelfKeys(item!);
|
||||
const notices = Object.fromEntries(
|
||||
noticeKeys.map((key) => [
|
||||
key,
|
||||
{ status: 'failed', seen: false },
|
||||
]),
|
||||
) as DraftGenerationNoticeMap;
|
||||
|
||||
const state = buildCreationWorkShelfRuntimeState({
|
||||
item: item!,
|
||||
notices,
|
||||
pendingShelfItems: {
|
||||
puzzle: {
|
||||
'puzzle-session-empty': createPendingDraftShelfState(
|
||||
'failed',
|
||||
false,
|
||||
'2026-06-03T08:00:00.000Z',
|
||||
{ summary: '图片生成超时,可重新打开处理。' },
|
||||
),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(state).toMatchObject({
|
||||
isGenerating: false,
|
||||
hasGenerationFailure: true,
|
||||
generationFailureSummary: '拼图草稿生成失败,可重新打开处理。',
|
||||
hasUnreadUpdate: false,
|
||||
suppressPersistedGenerating: true,
|
||||
titleOverride: '拼图草稿',
|
||||
summaryOverride: '图片生成超时,可重新打开处理。',
|
||||
});
|
||||
});
|
||||
|
||||
test('collectVisibleDraftNoticeKeys and hasUnreadDraftGenerationUpdates share unread dot rule', () => {
|
||||
const puzzle = buildPuzzleWork({
|
||||
workId: 'puzzle-work-ocean',
|
||||
profileId: 'puzzle-profile-ocean',
|
||||
sourceSessionId: 'puzzle-session-ocean',
|
||||
});
|
||||
const visibleKeys = collectVisibleDraftNoticeKeys({
|
||||
rpgItems: [],
|
||||
bigFishItems: [],
|
||||
jumpHopItems: [],
|
||||
woodenFishItems: [],
|
||||
match3dItems: [],
|
||||
squareHoleItems: [],
|
||||
puzzleItems: [puzzle],
|
||||
visualNovelItems: [],
|
||||
barkBattleItems: [],
|
||||
babyObjectMatchItems: [],
|
||||
});
|
||||
|
||||
expect(visibleKeys).toContain('puzzle:puzzle-work-ocean');
|
||||
expect(visibleKeys).toContain('puzzle:puzzle-profile-ocean');
|
||||
expect(visibleKeys).toContain('puzzle:puzzle-session-ocean');
|
||||
expect(buildPuzzleResultWorkId('puzzle-session-ocean')).toBe(
|
||||
'puzzle-work-ocean',
|
||||
);
|
||||
expect(buildPuzzleResultProfileId('puzzle-session-ocean')).toBe(
|
||||
'puzzle-profile-ocean',
|
||||
);
|
||||
|
||||
expect(
|
||||
hasUnreadDraftGenerationUpdates(
|
||||
{
|
||||
'puzzle:puzzle-profile-ocean': {
|
||||
status: 'ready',
|
||||
seen: false,
|
||||
},
|
||||
},
|
||||
visibleKeys,
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
hasUnreadDraftGenerationUpdates(
|
||||
{
|
||||
'puzzle:puzzle-profile-ocean': {
|
||||
status: 'ready',
|
||||
seen: true,
|
||||
},
|
||||
},
|
||||
visibleKeys,
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
function buildPuzzleWork(
|
||||
overrides: Partial<PuzzleWorkSummary> = {},
|
||||
): PuzzleWorkSummary {
|
||||
return {
|
||||
workId: 'puzzle-work-base',
|
||||
profileId: 'puzzle-profile-base',
|
||||
ownerUserId: 'user-1',
|
||||
sourceSessionId: 'puzzle-session-base',
|
||||
authorDisplayName: '测试作者',
|
||||
workTitle: '潮雾拼图',
|
||||
workDescription: '潮雾港口拼图。',
|
||||
levelName: '潮雾拼图',
|
||||
summary: '潮雾港口拼图。',
|
||||
themeTags: [],
|
||||
coverImageSrc: null,
|
||||
coverAssetId: null,
|
||||
publicationStatus: 'draft',
|
||||
updatedAt: '2026-06-03T08:00:00.000Z',
|
||||
publishedAt: null,
|
||||
playCount: 0,
|
||||
remixCount: 0,
|
||||
likeCount: 0,
|
||||
publishReady: false,
|
||||
levels: [],
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user