This commit is contained in:
202
src/services/customWorldCreatorIntent.test.ts
Normal file
202
src/services/customWorldCreatorIntent.test.ts
Normal file
@@ -0,0 +1,202 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import {
|
||||
buildCustomWorldAnchorPackFromIntent,
|
||||
buildCustomWorldCreatorIntentDisplayText,
|
||||
buildCustomWorldCreatorIntentFoundationText,
|
||||
buildPendingClarifications,
|
||||
createEmptyCustomWorldCreatorIntent,
|
||||
evaluateCustomWorldCreatorIntentReadiness,
|
||||
mergeCustomWorldCreatorIntent,
|
||||
normalizeCustomWorldCreatorIntent,
|
||||
} from './customWorldCreatorIntent';
|
||||
|
||||
describe('customWorldCreatorIntent', () => {
|
||||
it('builds a readable summary from creator intent cards', () => {
|
||||
const intent = {
|
||||
...createEmptyCustomWorldCreatorIntent('card'),
|
||||
worldHook: '一个会被灵潮反复改写地形的边境世界。',
|
||||
themeKeywords: ['边境', '灵潮'],
|
||||
toneDirectives: ['紧张', '潮湿'],
|
||||
playerPremise: '玩家是带着旧名单回来的前巡夜人。',
|
||||
coreConflicts: ['旧案名单再次出现'],
|
||||
keyCharacters: [
|
||||
{
|
||||
id: 'character-1',
|
||||
name: '沈砺',
|
||||
role: '灰炬向导',
|
||||
publicMask: '看起来只是熟路的带路人',
|
||||
hiddenHook: '他一直在追查撤离线失控真相',
|
||||
relationToPlayer: '会先怀疑玩家身份',
|
||||
notes: '',
|
||||
locked: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const summary = buildCustomWorldCreatorIntentDisplayText(intent);
|
||||
|
||||
expect(summary).toContain(
|
||||
'世界一句话:一个会被灵潮反复改写地形的边境世界。',
|
||||
);
|
||||
expect(summary).toContain('主题关键词:边境、灵潮');
|
||||
expect(summary).toContain('关键角色:沈砺 / 灰炬向导');
|
||||
});
|
||||
|
||||
it('builds six-anchor foundation text from structured creator intent', () => {
|
||||
const intent = {
|
||||
...createEmptyCustomWorldCreatorIntent('card'),
|
||||
worldHook: '一个会被灵潮反复改写地形的边境世界。',
|
||||
themeKeywords: ['边境', '灵潮'],
|
||||
toneDirectives: ['紧张', '潮湿'],
|
||||
playerPremise: '玩家是带着旧名单回来的前巡夜人。',
|
||||
openingSituation: '返乡第一夜,封锁线外出现了本不该存在的灯火。',
|
||||
coreConflicts: ['旧案名单再次出现'],
|
||||
keyCharacters: [
|
||||
{
|
||||
id: 'character-1',
|
||||
name: '沈砺',
|
||||
role: '灰炬向导',
|
||||
publicMask: '看起来只是熟路的带路人',
|
||||
hiddenHook: '他一直在追查撤离线失控真相',
|
||||
relationToPlayer: '会先怀疑玩家身份',
|
||||
notes: '',
|
||||
locked: true,
|
||||
},
|
||||
],
|
||||
iconicElements: ['会逆向蔓延的潮雾'],
|
||||
};
|
||||
|
||||
const foundationText = buildCustomWorldCreatorIntentFoundationText(intent);
|
||||
|
||||
expect(foundationText).toContain(
|
||||
'世界一句话:一个会被灵潮反复改写地形的边境世界。',
|
||||
);
|
||||
expect(foundationText).toContain('玩家开局:玩家是带着旧名单回来的前巡夜人。');
|
||||
expect(foundationText).toContain('主题气质:边境、灵潮 / 紧张、潮湿');
|
||||
expect(foundationText).toContain('关键关系:沈砺 · 灰炬向导');
|
||||
expect(foundationText).toContain('标志元素:会逆向蔓延的潮雾');
|
||||
});
|
||||
|
||||
it('builds anchor pack from creator intent and keeps locked ids', () => {
|
||||
const intent = {
|
||||
...createEmptyCustomWorldCreatorIntent('card'),
|
||||
worldHook: '边境世界',
|
||||
coreConflicts: ['裂潮失控'],
|
||||
keyFactions: [
|
||||
{
|
||||
id: 'faction-1',
|
||||
name: '巡边司',
|
||||
publicGoal: '维持边境秩序',
|
||||
tension: '正在被旧案拖入裂潮',
|
||||
notes: '',
|
||||
locked: true,
|
||||
},
|
||||
],
|
||||
keyLandmarks: [
|
||||
{
|
||||
id: 'landmark-1',
|
||||
name: '断桥旧哨',
|
||||
purpose: '边境咽喉',
|
||||
mood: '压迫',
|
||||
secret: '封桥旧令来源不明',
|
||||
locked: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const anchorPack = buildCustomWorldAnchorPackFromIntent(intent);
|
||||
|
||||
expect(anchorPack?.keyConflictSummaries).toEqual(['裂潮失控']);
|
||||
expect(anchorPack?.keyFactionSummaries[0]).toContain('巡边司');
|
||||
expect(anchorPack?.lockedAnchorIds).toEqual(
|
||||
expect.arrayContaining(['faction-1', 'landmark-1']),
|
||||
);
|
||||
});
|
||||
|
||||
it('normalizes sparse creator intent payloads', () => {
|
||||
const intent = normalizeCustomWorldCreatorIntent({
|
||||
sourceMode: 'card',
|
||||
worldHook: '雾海边城',
|
||||
themeKeywords: ['雾海', '旧案'],
|
||||
keyCharacters: [
|
||||
{
|
||||
name: '梁砺',
|
||||
role: '断桥巡守',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(intent?.sourceMode).toBe('card');
|
||||
expect(intent?.keyCharacters[0]?.name).toBe('梁砺');
|
||||
expect(intent?.keyCharacters[0]?.id).toBeTruthy();
|
||||
});
|
||||
|
||||
it('merges creator intent patches without dropping unrelated anchors', () => {
|
||||
const baseIntent = {
|
||||
...createEmptyCustomWorldCreatorIntent('freeform'),
|
||||
worldHook: '潮雾会改写地形的列岛世界。',
|
||||
playerPremise: '玩家是失职返乡的守灯人。',
|
||||
};
|
||||
|
||||
const merged = mergeCustomWorldCreatorIntent(baseIntent, {
|
||||
coreConflicts: ['守灯会与沉船商盟争夺航道解释权'],
|
||||
toneDirectives: ['冷峻'],
|
||||
});
|
||||
if (!merged) {
|
||||
throw new Error('expected merged creator intent');
|
||||
}
|
||||
|
||||
expect(merged.worldHook).toBe('潮雾会改写地形的列岛世界。');
|
||||
expect(merged.playerPremise).toBe('玩家是失职返乡的守灯人。');
|
||||
expect(merged.coreConflicts).toEqual(['守灯会与沉船商盟争夺航道解释权']);
|
||||
expect(merged.toneDirectives).toEqual(['冷峻']);
|
||||
});
|
||||
|
||||
it('replaces array anchors when a patch marks explicit rewrite fields', () => {
|
||||
const merged = mergeCustomWorldCreatorIntent(
|
||||
{
|
||||
...createEmptyCustomWorldCreatorIntent('freeform'),
|
||||
themeKeywords: ['海岛', '旧案'],
|
||||
coreConflicts: ['守灯会与沉船商盟争夺航道解释权'],
|
||||
},
|
||||
{
|
||||
themeKeywords: ['宫廷', '悬疑'],
|
||||
coreConflicts: ['王庭继承人与旧灯塔盟约对抗'],
|
||||
replaceFields: ['themeKeywords', 'coreConflicts'],
|
||||
},
|
||||
);
|
||||
if (!merged) {
|
||||
throw new Error('expected merged creator intent');
|
||||
}
|
||||
|
||||
expect(merged.themeKeywords).toEqual(['宫廷', '悬疑']);
|
||||
expect(merged.coreConflicts).toEqual(['王庭继承人与旧灯塔盟约对抗']);
|
||||
});
|
||||
|
||||
it('evaluates readiness and limits clarifications to top gaps', () => {
|
||||
const readiness = evaluateCustomWorldCreatorIntentReadiness({
|
||||
...createEmptyCustomWorldCreatorIntent('freeform'),
|
||||
worldHook: '一个被潮雾切开的列岛世界。',
|
||||
themeKeywords: ['海岛'],
|
||||
toneDirectives: ['冷峻'],
|
||||
coreConflicts: ['旧灯塔正在被沉船商盟接管'],
|
||||
});
|
||||
const clarifications = buildPendingClarifications(
|
||||
{
|
||||
...createEmptyCustomWorldCreatorIntent('freeform'),
|
||||
worldHook: '一个被潮雾切开的列岛世界。',
|
||||
themeKeywords: ['海岛'],
|
||||
toneDirectives: ['冷峻'],
|
||||
coreConflicts: ['旧灯塔正在被沉船商盟接管'],
|
||||
},
|
||||
readiness,
|
||||
);
|
||||
|
||||
expect(readiness.isReady).toBe(false);
|
||||
expect(readiness.completedKeys).toContain('world_hook');
|
||||
expect(readiness.missingKeys).toContain('player_premise');
|
||||
expect(clarifications).toHaveLength(3);
|
||||
expect(clarifications[0]?.targetKey).toBe('player_premise');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user