169 lines
4.7 KiB
TypeScript
169 lines
4.7 KiB
TypeScript
import { describe, expect, test } from 'vitest';
|
|
|
|
import { createRpgCreationPublishedProfileFixture } from '../../../packages/shared/src/contracts/rpgCreationFixtures';
|
|
import type { CustomWorldProfile } from '../../types';
|
|
import {
|
|
buildPlatformRpgAgentResultPublishGateView,
|
|
type PlatformRpgAgentResultBlockerView,
|
|
resolvePlatformRpgAgentResultPreviewSourceLabel,
|
|
} from './platformRpgAgentResultPreviewModel';
|
|
|
|
function buildProfile(
|
|
overrides: Record<string, unknown> = {},
|
|
): CustomWorldProfile {
|
|
return {
|
|
...createRpgCreationPublishedProfileFixture(),
|
|
worldHook: '潮雾列岛旧灯塔重新点亮。',
|
|
playerPremise: '玩家从回潮旧灯塔切入沉船旧案。',
|
|
coreConflicts: ['守灯会与沉船旧案的冲突'],
|
|
sceneChapterBlueprints: [
|
|
{
|
|
id: 'chapter-1',
|
|
acts: [
|
|
{
|
|
id: 'act-1',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
...overrides,
|
|
} as unknown as CustomWorldProfile;
|
|
}
|
|
|
|
const missingWorldHookBlocker: PlatformRpgAgentResultBlockerView = {
|
|
code: 'publish_missing_world_hook',
|
|
message: '缺少世界钩子',
|
|
};
|
|
const missingPlayerPremiseBlocker: PlatformRpgAgentResultBlockerView = {
|
|
code: 'publish_missing_player_premise',
|
|
message: '缺少玩家前提',
|
|
};
|
|
const missingCoreConflictBlocker: PlatformRpgAgentResultBlockerView = {
|
|
code: 'publish_missing_core_conflict',
|
|
message: '缺少核心冲突',
|
|
};
|
|
const missingMainChapterBlocker: PlatformRpgAgentResultBlockerView = {
|
|
code: 'publish_missing_main_chapter',
|
|
message: '缺少主章节',
|
|
};
|
|
const missingFirstActBlocker: PlatformRpgAgentResultBlockerView = {
|
|
code: 'publish_missing_first_act',
|
|
message: '缺少首幕',
|
|
};
|
|
const structuralBlockers: PlatformRpgAgentResultBlockerView[] = [
|
|
missingWorldHookBlocker,
|
|
missingPlayerPremiseBlocker,
|
|
missingCoreConflictBlocker,
|
|
missingMainChapterBlocker,
|
|
missingFirstActBlocker,
|
|
];
|
|
|
|
describe('platformRpgAgentResultPreviewModel', () => {
|
|
test('uses fallback blockers and publish readiness without a profile', () => {
|
|
expect(
|
|
buildPlatformRpgAgentResultPublishGateView(
|
|
null,
|
|
structuralBlockers.slice(0, 2),
|
|
false,
|
|
),
|
|
).toEqual({
|
|
blockers: ['缺少世界钩子', '缺少玩家前提'],
|
|
publishReady: false,
|
|
});
|
|
});
|
|
|
|
test('filters structural blockers already satisfied by the profile', () => {
|
|
expect(
|
|
buildPlatformRpgAgentResultPublishGateView(
|
|
buildProfile(),
|
|
[
|
|
...structuralBlockers,
|
|
{
|
|
code: 'future_blocker',
|
|
message: '未知服务端阻断',
|
|
},
|
|
],
|
|
false,
|
|
),
|
|
).toEqual({
|
|
blockers: ['未知服务端阻断'],
|
|
publishReady: false,
|
|
});
|
|
});
|
|
|
|
test('keeps unresolved structural blockers when profile fields are empty', () => {
|
|
expect(
|
|
buildPlatformRpgAgentResultPublishGateView(
|
|
buildProfile({
|
|
worldHook: '',
|
|
playerPremise: '',
|
|
settingText: '',
|
|
creatorIntent: null,
|
|
anchorContent: null,
|
|
coreConflicts: [],
|
|
chapters: [],
|
|
sceneChapterBlueprints: [],
|
|
sceneChapters: [],
|
|
}),
|
|
structuralBlockers,
|
|
true,
|
|
),
|
|
).toEqual({
|
|
blockers: structuralBlockers.map((entry) => entry.message),
|
|
publishReady: false,
|
|
});
|
|
});
|
|
|
|
test('resolves structural blockers from nested profile compatibility fields', () => {
|
|
expect(
|
|
buildPlatformRpgAgentResultPublishGateView(
|
|
buildProfile({
|
|
worldHook: '',
|
|
playerPremise: '',
|
|
settingText: '',
|
|
creatorIntent: {
|
|
worldHook: '旧灯塔潮路重新开启。',
|
|
},
|
|
anchorContent: {
|
|
playerEntryPoint: {
|
|
openingProblem: '玩家被卷入沉船旧案。',
|
|
},
|
|
},
|
|
coreConflicts: [''],
|
|
chapters: [],
|
|
sceneChapterBlueprints: null,
|
|
sceneChapters: [
|
|
{
|
|
acts: [{}],
|
|
},
|
|
],
|
|
}),
|
|
[
|
|
missingWorldHookBlocker,
|
|
missingPlayerPremiseBlocker,
|
|
missingFirstActBlocker,
|
|
],
|
|
false,
|
|
),
|
|
).toEqual({
|
|
blockers: [],
|
|
publishReady: true,
|
|
});
|
|
});
|
|
|
|
test('maps preview source to result label', () => {
|
|
expect(resolvePlatformRpgAgentResultPreviewSourceLabel(null)).toBeNull();
|
|
expect(
|
|
resolvePlatformRpgAgentResultPreviewSourceLabel('published_profile'),
|
|
).toBe('已发布世界');
|
|
expect(
|
|
resolvePlatformRpgAgentResultPreviewSourceLabel('session_preview'),
|
|
).toBe('会话预览');
|
|
expect(
|
|
resolvePlatformRpgAgentResultPreviewSourceLabel('future_source'),
|
|
).toBe(
|
|
'服务端预览',
|
|
);
|
|
});
|
|
});
|