refactor: 收口剩余草稿打开 intent

This commit is contained in:
2026-06-04 06:12:26 +08:00
parent e570d50e9f
commit c93b8fb570
6 changed files with 422 additions and 41 deletions
@@ -3,6 +3,8 @@ import { describe, expect, test } from 'vitest';
import type { BigFishWorkSummary } from '../../../packages/shared/src/contracts/bigFishWorkSummary';
import type { Match3DWorkSummary } from '../../../packages/shared/src/contracts/match3dWorks';
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
import type { SquareHoleWorkSummary } from '../../../packages/shared/src/contracts/squareHoleWorks';
import type { VisualNovelWorkSummary } from '../../../packages/shared/src/contracts/visualNovel';
import { buildCreationWorkShelfItems } from '../custom-world-home/creationWorkShelf';
import {
buildCreationWorkShelfRuntimeState,
@@ -16,8 +18,11 @@ import {
hasUnreadDraftGenerationUpdates,
mergeBigFishWorkSummary,
mergePuzzleWorkSummary,
resolveBigFishDraftOpenIntent,
resolveMatch3DDraftOpenIntent,
resolvePuzzleDraftOpenIntent,
resolveSquareHoleDraftOpenIntent,
resolveVisualNovelDraftOpenIntent,
} from './platformDraftGenerationShelfModel';
describe('platformDraftGenerationShelfModel', () => {
@@ -150,6 +155,131 @@ describe('platformDraftGenerationShelfModel', () => {
});
});
test('resolveBigFishDraftOpenIntent reopens active generating session before restoring draft', () => {
expect(
resolveBigFishDraftOpenIntent({
item: buildBigFishWork(),
activeSessionId: 'big-fish-session-base',
hasActiveGenerationRunning: true,
}),
).toMatchObject({
type: 'active-generation',
sourceSessionId: 'big-fish-session-base',
});
expect(
resolveBigFishDraftOpenIntent({
item: buildBigFishWork(),
activeSessionId: 'other-session',
hasActiveGenerationRunning: true,
}),
).toMatchObject({
type: 'restore-draft',
sourceSessionId: 'big-fish-session-base',
});
});
test('resolveSquareHoleDraftOpenIntent handles published, missing, active and restore states', () => {
expect(
resolveSquareHoleDraftOpenIntent({
item: buildSquareHoleWork({ publicationStatus: 'published' }),
activeSessionId: null,
hasActiveGenerationRunning: false,
isGenerationReady: false,
}),
).toMatchObject({
type: 'open-published-detail',
});
expect(
resolveSquareHoleDraftOpenIntent({
item: buildSquareHoleWork({ sourceSessionId: null }),
forceDraft: true,
activeSessionId: null,
hasActiveGenerationRunning: false,
isGenerationReady: false,
}),
).toMatchObject({
type: 'missing-session',
});
expect(
resolveSquareHoleDraftOpenIntent({
item: buildSquareHoleWork(),
activeSessionId: 'square-hole-session-base',
hasActiveGenerationRunning: true,
isGenerationReady: false,
}),
).toMatchObject({
type: 'active-generation',
sourceSessionId: 'square-hole-session-base',
});
expect(
resolveSquareHoleDraftOpenIntent({
item: buildSquareHoleWork(),
activeSessionId: 'other-session',
hasActiveGenerationRunning: false,
isGenerationReady: false,
}),
).toMatchObject({
type: 'restore-draft',
shouldClearGenerationState: true,
});
});
test('resolveVisualNovelDraftOpenIntent handles published, active, current result and load detail states', () => {
expect(
resolveVisualNovelDraftOpenIntent({
item: buildVisualNovelWork({ publishStatus: 'published' }),
activeSessionId: null,
hasActiveGenerationRunning: false,
hasActiveSessionDraft: false,
}),
).toMatchObject({
type: 'open-published-detail',
});
expect(
resolveVisualNovelDraftOpenIntent({
item: buildVisualNovelWork(),
forceDraft: true,
activeSessionId: 'visual-novel-profile-base',
hasActiveGenerationRunning: true,
hasActiveSessionDraft: false,
}),
).toMatchObject({
type: 'active-generation',
profileId: 'visual-novel-profile-base',
});
expect(
resolveVisualNovelDraftOpenIntent({
item: buildVisualNovelWork(),
forceDraft: true,
activeSessionId: 'visual-novel-profile-base',
hasActiveGenerationRunning: false,
hasActiveSessionDraft: true,
}),
).toMatchObject({
type: 'current-result',
profileId: 'visual-novel-profile-base',
});
expect(
resolveVisualNovelDraftOpenIntent({
item: buildVisualNovelWork(),
forceDraft: true,
activeSessionId: 'other-profile',
hasActiveGenerationRunning: false,
hasActiveSessionDraft: false,
}),
).toMatchObject({
type: 'load-detail',
profileId: 'visual-novel-profile-base',
});
});
test('buildPendingPuzzleWorks creates failed puzzle placeholder with stable ids and fallback title', () => {
const pending = buildPendingPuzzleWorks(
{
@@ -425,3 +555,52 @@ function buildBigFishWork(
...overrides,
};
}
function buildSquareHoleWork(
overrides: Partial<SquareHoleWorkSummary> = {},
): SquareHoleWorkSummary {
return {
workId: 'square-hole-work-base',
profileId: 'square-hole-profile-base',
ownerUserId: 'user-1',
sourceSessionId: 'square-hole-session-base',
gameName: '潮雾方洞',
themeText: '潮雾港口',
twistRule: '避开雾门',
summary: '潮雾港口方洞挑战。',
tags: [],
coverImageSrc: null,
backgroundPrompt: '潮雾港口',
backgroundImageSrc: null,
shapeOptions: [],
holeOptions: [],
shapeCount: 1,
difficulty: 1,
publicationStatus: 'draft',
playCount: 0,
updatedAt: '2026-06-03T08:00:00.000Z',
publishedAt: null,
publishReady: false,
...overrides,
};
}
function buildVisualNovelWork(
overrides: Partial<VisualNovelWorkSummary> = {},
): VisualNovelWorkSummary {
return {
runtimeKind: 'visual-novel',
profileId: 'visual-novel-profile-base',
ownerUserId: 'user-1',
title: '潮雾视觉小说',
description: '潮雾港口视觉小说。',
coverImageSrc: null,
tags: [],
publishStatus: 'draft',
publishReady: false,
playCount: 0,
updatedAt: '2026-06-03T08:00:00.000Z',
publishedAt: null,
...overrides,
};
}