refactor: 收口 RPG 结果预览门禁
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
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(
|
||||
'服务端预览',
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user