Files
Genarrative/src/components/npcVisualEditorPersistence.test.ts
高物 c49c64896a
Some checks failed
CI / verify (push) Has been cancelled
初始仓库迁移
2026-04-04 23:57:06 +08:00

108 lines
3.0 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest';
import type { MedievalNpcVisualOverride } from '../data/medievalNpcVisuals';
import type { EditableNpcVisualState } from './npcVisualEditorModel';
import {
NPC_LAYOUT_CONFIG_API_PATH,
NPC_VISUAL_OVERRIDES_API_PATH,
persistNpcLayoutConfig,
persistNpcVisualOverrides,
} from './npcVisualEditorPersistence';
import type { NpcLayoutConfig } from './npcVisualShared';
function createEditorState(): EditableNpcVisualState {
return {
race: 'human',
bodyColor: 'black',
headIndex: 1,
hairColorIndex: 1,
hairStyleFrame: 0,
facialHairEnabled: false,
facialHairColorIndex: 1,
facialHairStyleFrame: 0,
headgearType: 'none',
headgearFile: '',
headgearFrame: 0,
mainHandType: 'none',
mainHandFile: '',
mainHandFrame: 0,
offHandType: 'none',
offHandFile: '',
offHandFrame: 0,
};
}
function createExistingOverride(): MedievalNpcVisualOverride {
return {
race: 'elf',
bodySrc: '/body.png',
headSrc: '/head.png',
hairSrc: '/hair.png',
handSrc: '/hand.png',
bodyFrames: [0, 1, 2, 3],
headFrame: 0,
hairFrame: 1,
handFrame: 0,
};
}
function createLayoutDraft(): NpcLayoutConfig {
return {
body: { x: 0, y: 0 },
head: { x: 1, y: 2 },
facialHair: { x: 3, y: 4 },
hair: { x: 5, y: 6 },
headgear: { x: 7, y: 8 },
hand: { x: 9, y: 10 },
mainHand: { x: 11, y: 12 },
offHand: { x: 13, y: 14 },
};
}
describe('npcVisualEditorPersistence', () => {
it('persists merged npc visual overrides and returns the writeback payload', async () => {
const saveJson = vi.fn(async () => undefined);
const result = await persistNpcVisualOverrides({
overrideMap: {
existing: createExistingOverride(),
},
npcId: 'npc-1',
editorState: createEditorState(),
saveJson,
});
expect(saveJson).toHaveBeenCalledWith(
NPC_VISUAL_OVERRIDES_API_PATH,
expect.objectContaining({
existing: createExistingOverride(),
'npc-1': expect.objectContaining({
race: 'human',
bodyFrames: [0, 1, 2, 3],
}),
}),
'保存角色形象覆盖配置失败',
);
expect(result.nextOverrideMap.existing).toEqual(createExistingOverride());
expect(result.nextOverrideMap['npc-1']).toEqual(expect.objectContaining({ race: 'human' }));
expect(result.saveMessage).toContain('npcVisualOverrides.json');
});
it('persists layout config with a cloned payload for local writeback', async () => {
const saveJson = vi.fn(async () => undefined);
const layoutDraft = createLayoutDraft();
const result = await persistNpcLayoutConfig({
layoutDraft,
saveJson,
});
expect(saveJson).toHaveBeenCalledWith(
NPC_LAYOUT_CONFIG_API_PATH,
expect.objectContaining(layoutDraft),
'保存角色布局配置失败',
);
expect(result.nextLayout).toEqual(layoutDraft);
expect(result.nextLayout).not.toBe(layoutDraft);
expect(result.saveMessage).toContain('角色布局');
});
});