This commit is contained in:
2026-04-28 19:36:39 +08:00
parent a9febe7678
commit f0471a4f8d
206 changed files with 18456 additions and 10133 deletions

View File

@@ -5,9 +5,11 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
import type { CustomWorldAgentSessionSnapshot } from '../../../packages/shared/src/contracts/customWorldAgent';
import type { CustomWorldWorkSummary } from '../../../packages/shared/src/contracts/customWorldWorkSummary';
import type { RpgCreationResultView } from '../../../packages/shared/src/contracts/rpgCreationResultView';
import { WorldType, type CustomWorldProfile } from '../../types';
import {
executeRpgCreationAction,
getRpgCreationOperation,
upsertRpgWorldProfile,
} from '../../services/rpg-creation';
import { useRpgCreationResultAutosave } from './useRpgCreationResultAutosave';
@@ -109,16 +111,42 @@ function buildSession(
};
}
function buildResultView(
overrides: Partial<RpgCreationResultView> = {},
): RpgCreationResultView {
const session = overrides.session ?? buildSession();
return {
session,
profile: null,
profileSource: 'none',
targetStage: 'agent-workspace',
generationViewSource: null,
resultViewSource: null,
canAutosaveLibrary: false,
canSyncResultProfile: false,
publishReady: false,
canEnterWorld: false,
blockerCount: 0,
recoveryAction: 'continue_agent',
recoveryReason: null,
...overrides,
};
}
describe('RPG Agent 草稿恢复', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('作品摘要已有对象数量但 session 没有 draftProfile 时恢复 Agent 页面', async () => {
const syncAgentSessionSnapshot = vi.fn(async () =>
buildSession({
stage: 'clarifying',
draftProfile: null,
const syncAgentCreationResultView = vi.fn(async () =>
buildResultView({
session: buildSession({
stage: 'clarifying',
draftProfile: null,
}),
targetStage: 'agent-workspace',
recoveryAction: 'continue_agent',
}),
);
const setSelectionStage = vi.fn();
@@ -150,9 +178,9 @@ describe('RPG Agent 草稿恢复', () => {
refreshCustomWorldWorks: vi.fn(async () => []),
refreshPublishedGallery: vi.fn(async () => []),
persistAgentUiState,
syncAgentSessionSnapshot,
buildDraftResultProfile: (session) =>
(session?.draftProfile as CustomWorldProfile | null) ?? null,
syncAgentCreationResultView,
buildDraftResultProfile: (view) =>
(view?.profile as CustomWorldProfile | null) ?? null,
suppressAgentDraftResultAutoOpen,
releaseAgentDraftResultAutoOpenSuppression: vi.fn(),
resetAutoSaveTrackingToIdle: vi.fn(),
@@ -183,7 +211,7 @@ describe('RPG Agent 草稿恢复', () => {
});
});
expect(syncAgentSessionSnapshot).toHaveBeenCalledWith('agent-session-1');
expect(syncAgentCreationResultView).toHaveBeenCalledWith('agent-session-1');
expect(suppressAgentDraftResultAutoOpen).toHaveBeenCalled();
expect(persistAgentUiState).toHaveBeenCalledWith('agent-session-1', null);
expect(setGeneratedCustomWorldProfile).toHaveBeenLastCalledWith(null);
@@ -192,7 +220,7 @@ describe('RPG Agent 草稿恢复', () => {
expect(setSelectionStage).not.toHaveBeenCalledWith('custom-world-result');
});
it('Agent 结果页自动保存只刷新 session draftProfile不触发 sync_result_profile', async () => {
it('Agent 结果页自动保存先回写 session,再保存后端 result-view profile', async () => {
const oldProfile = buildProfile('旧前端快照');
const latestProfile = {
...buildProfile('服务端草稿快照'),
@@ -203,6 +231,36 @@ describe('RPG Agent 草稿恢复', () => {
draftProfile: latestProfile as unknown as Record<string, unknown>,
});
const syncAgentSessionSnapshot = vi.fn(async () => latestSession);
const syncAgentCreationResultView = vi.fn(async () =>
buildResultView({
session: latestSession,
profile: latestProfile,
profileSource: 'result_preview',
targetStage: 'custom-world-result',
resultViewSource: 'agent-draft',
canAutosaveLibrary: true,
canSyncResultProfile: true,
recoveryAction: 'open_result',
}),
);
vi.mocked(executeRpgCreationAction).mockResolvedValue({
operation: {
operationId: 'operation-sync-result',
type: 'sync_result_profile',
status: 'running',
phaseLabel: '结果页同步中',
phaseDetail: '正在同步结果页。',
progress: 50,
},
});
vi.mocked(getRpgCreationOperation).mockResolvedValue({
operationId: 'operation-sync-result',
type: 'sync_result_profile',
status: 'completed',
phaseLabel: '结果页已同步',
phaseDetail: '结果页已同步。',
progress: 100,
});
vi.mocked(upsertRpgWorldProfile).mockResolvedValue({
entry: {
@@ -230,16 +288,6 @@ describe('RPG Agent 草稿恢复', () => {
useRpgCreationResultAutosave({
selectionStage: 'custom-world-result',
activeAgentSessionId: 'agent-session-1',
agentSession: buildSession({
stage: 'object_refining',
draftProfile: oldProfile as unknown as Record<string, unknown>,
resultPreview: {
publishReady: false,
blockers: [],
qualityFindings: [],
sourceLabel: '旧预览',
} as never,
}),
generatedCustomWorldProfile: oldProfile,
isAgentDraftResultView: true,
userId: 'user-1',
@@ -250,8 +298,9 @@ describe('RPG Agent 草稿恢复', () => {
refreshCustomWorldWorks: vi.fn(async () => []),
persistAgentUiState: vi.fn(),
syncAgentSessionSnapshot,
buildDraftResultProfile: (session) =>
(session?.draftProfile as CustomWorldProfile | null) ?? null,
syncAgentCreationResultView,
buildDraftResultProfile: (view) =>
(view?.profile as CustomWorldProfile | null) ?? null,
});
return null;
@@ -266,13 +315,23 @@ describe('RPG Agent 草稿恢复', () => {
vi.useRealTimers();
expect(syncAgentSessionSnapshot).toHaveBeenCalledWith('agent-session-1');
expect(upsertRpgWorldProfile).toHaveBeenCalledWith(latestProfile, {
sourceAgentSessionId: 'agent-session-1',
expect(syncAgentCreationResultView).toHaveBeenCalledWith('agent-session-1');
expect(executeRpgCreationAction).toHaveBeenCalledWith('agent-session-1', {
action: 'sync_result_profile',
profile: expect.objectContaining({
id: oldProfile.id,
name: oldProfile.name,
}),
});
expect(
vi.mocked(executeRpgCreationAction).mock.calls.some(
([, payload]) => payload?.action === 'sync_result_profile',
),
).toBe(false);
expect(upsertRpgWorldProfile).toHaveBeenCalledWith(
expect.objectContaining({
id: latestProfile.id,
name: latestProfile.name,
summary: latestProfile.summary,
}),
{
sourceAgentSessionId: 'agent-session-1',
},
);
});
});