171 lines
4.7 KiB
TypeScript
171 lines
4.7 KiB
TypeScript
/** @vitest-environment jsdom */
|
||
|
||
import { act, render } from '@testing-library/react';
|
||
import { describe, expect, it, vi } from 'vitest';
|
||
|
||
import type { CustomWorldAgentSessionSnapshot } from '../../../packages/shared/src/contracts/customWorldAgent';
|
||
import { type CustomWorldProfile, WorldType } from '../../types';
|
||
import { useRpgCreationEnterWorld } from './useRpgCreationEnterWorld';
|
||
|
||
function buildProfile(params: {
|
||
id: string;
|
||
name: string;
|
||
imageSrc: string;
|
||
}): CustomWorldProfile {
|
||
return {
|
||
id: params.id,
|
||
settingText: params.name,
|
||
name: params.name,
|
||
subtitle: params.name,
|
||
summary: params.name,
|
||
tone: '测试',
|
||
playerGoal: '测试',
|
||
templateWorldType: WorldType.WUXIA,
|
||
compatibilityTemplateWorldType: WorldType.WUXIA,
|
||
majorFactions: [],
|
||
coreConflicts: [],
|
||
attributeSchema: {
|
||
id: `${params.id}-attribute-schema`,
|
||
worldId: params.id,
|
||
schemaVersion: 1,
|
||
generatedFrom: {
|
||
worldType: WorldType.CUSTOM,
|
||
worldName: params.name,
|
||
settingSummary: params.name,
|
||
tone: '测试',
|
||
conflictCore: '测试',
|
||
},
|
||
slots: [],
|
||
},
|
||
playableNpcs: [
|
||
{
|
||
id: `${params.id}-role`,
|
||
name: '可扮演角色',
|
||
title: '测试角色',
|
||
role: '主角',
|
||
description: '测试角色',
|
||
backstory: '测试背景',
|
||
personality: '测试性格',
|
||
motivation: '测试动机',
|
||
combatStyle: '测试战斗风格',
|
||
initialAffinity: 18,
|
||
relationshipHooks: [],
|
||
tags: [],
|
||
backstoryReveal: {
|
||
publicSummary: '测试角色',
|
||
privateChatUnlockAffinity: 60,
|
||
chapters: [],
|
||
},
|
||
skills: [],
|
||
initialItems: [],
|
||
imageSrc: params.imageSrc,
|
||
},
|
||
],
|
||
storyNpcs: [],
|
||
items: [],
|
||
landmarks: [],
|
||
generationMode: 'full',
|
||
generationStatus: 'complete',
|
||
};
|
||
}
|
||
|
||
function buildSession(): CustomWorldAgentSessionSnapshot {
|
||
return {
|
||
sessionId: 'session-1',
|
||
currentTurn: 1,
|
||
anchorContent: {
|
||
worldPromise: null,
|
||
playerFantasy: null,
|
||
themeBoundary: null,
|
||
playerEntryPoint: null,
|
||
coreConflict: null,
|
||
keyRelationships: null,
|
||
hiddenLines: null,
|
||
iconicElements: null,
|
||
},
|
||
progressPercent: 100,
|
||
lastAssistantReply: '',
|
||
stage: 'ready_to_publish',
|
||
focusCardId: null,
|
||
creatorIntent: null,
|
||
creatorIntentReadiness: {
|
||
isReady: true,
|
||
completedKeys: [],
|
||
missingKeys: [],
|
||
},
|
||
anchorPack: null,
|
||
lockState: null,
|
||
draftProfile: null,
|
||
messages: [],
|
||
draftCards: [],
|
||
pendingClarifications: [],
|
||
suggestedActions: [],
|
||
recommendedReplies: [],
|
||
qualityFindings: [],
|
||
assetCoverage: {
|
||
roleAssets: [],
|
||
sceneAssets: [],
|
||
allRoleAssetsReady: true,
|
||
allSceneAssetsReady: true,
|
||
},
|
||
resultPreview: null,
|
||
updatedAt: '2026-04-25T00:00:00.000Z',
|
||
};
|
||
}
|
||
|
||
describe('useRpgCreationEnterWorld', () => {
|
||
it('Agent 草稿测试进入游戏时优先使用结果页当前 profile,而不是回退到会话快照', async () => {
|
||
const resultProfile = buildProfile({
|
||
id: 'draft-profile',
|
||
name: '结果页真相源',
|
||
imageSrc: '/generated-characters/draft-role/portrait.png',
|
||
});
|
||
const handleCustomWorldSelect = vi.fn();
|
||
const setGeneratedCustomWorldProfile = vi.fn();
|
||
const executePublishWorld = vi.fn(async () => buildSession());
|
||
const syncAgentCreationResultView = vi.fn();
|
||
const syncAgentDraftResultProfile = vi.fn(async () => ({
|
||
profile: resultProfile,
|
||
view: null,
|
||
}));
|
||
|
||
function Harness() {
|
||
const { enterWorldForTestFromCurrentResult } = useRpgCreationEnterWorld({
|
||
isAgentDraftResultView: true,
|
||
activeAgentSessionId: 'session-1',
|
||
generatedCustomWorldProfile: resultProfile,
|
||
handleCustomWorldSelect,
|
||
syncAgentDraftResultProfile,
|
||
executePublishWorld,
|
||
syncAgentCreationResultView,
|
||
setGeneratedCustomWorldProfile,
|
||
});
|
||
|
||
return (
|
||
<button
|
||
type="button"
|
||
onClick={() => void enterWorldForTestFromCurrentResult()}
|
||
>
|
||
进入
|
||
</button>
|
||
);
|
||
}
|
||
|
||
const { getByText } = render(<Harness />);
|
||
await act(async () => {
|
||
getByText('进入').click();
|
||
});
|
||
|
||
expect(executePublishWorld).not.toHaveBeenCalled();
|
||
expect(handleCustomWorldSelect).toHaveBeenCalledWith(resultProfile, {
|
||
mode: 'play',
|
||
disablePersistence: true,
|
||
returnStage: 'custom-world-result',
|
||
});
|
||
expect(setGeneratedCustomWorldProfile).toHaveBeenCalledWith(resultProfile);
|
||
expect(
|
||
handleCustomWorldSelect.mock.calls[0]?.[0].playableNpcs[0]?.imageSrc,
|
||
).toBe('/generated-characters/draft-role/portrait.png');
|
||
});
|
||
});
|