105 lines
3.5 KiB
TypeScript
105 lines
3.5 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
|
|
import type { General } from '../src/domain/entities.js';
|
|
import {
|
|
consumeEquippedItemCharge,
|
|
createItemInventoryFromSlots,
|
|
equipNewItem,
|
|
getEquippedItemInstance,
|
|
parseItemInventory,
|
|
projectItemSlots,
|
|
serializeItemInventory,
|
|
} from '../src/items/inventory.js';
|
|
import { listEquippedItemKeys } from '../src/items/utils.js';
|
|
|
|
const makeGeneral = (): General => ({
|
|
id: 7,
|
|
name: '테스트',
|
|
nationId: 1,
|
|
cityId: 1,
|
|
troopId: 0,
|
|
stats: { leadership: 70, strength: 70, intelligence: 70 },
|
|
experience: 0,
|
|
dedication: 0,
|
|
officerLevel: 0,
|
|
role: {
|
|
personality: null,
|
|
specialDomestic: null,
|
|
specialWar: null,
|
|
items: { horse: null, weapon: null, book: null, item: null },
|
|
},
|
|
injury: 30,
|
|
gold: 1000,
|
|
rice: 1000,
|
|
crew: 1000,
|
|
crewTypeId: 1100,
|
|
train: 100,
|
|
atmos: 100,
|
|
age: 30,
|
|
npcState: 0,
|
|
triggerState: { flags: {}, counters: {}, modifiers: {}, meta: {} },
|
|
meta: { killturn: 24 },
|
|
});
|
|
|
|
describe('GeneralItemInventory', () => {
|
|
it('upgrades legacy equipped columns into canonical item instances', () => {
|
|
const inventory = createItemInventoryFromSlots({
|
|
horse: 'che_명마_01_노기',
|
|
weapon: null,
|
|
book: 'che_서적_01_효경전',
|
|
item: 'che_치료_환약',
|
|
});
|
|
|
|
expect(projectItemSlots(inventory)).toEqual({
|
|
horse: 'che_명마_01_노기',
|
|
weapon: null,
|
|
book: 'che_서적_01_효경전',
|
|
item: 'che_치료_환약',
|
|
});
|
|
expect(Object.keys(inventory.instances)).toHaveLength(3);
|
|
});
|
|
|
|
it('reads legacy slots without mutating a frozen world snapshot', () => {
|
|
const general = makeGeneral();
|
|
general.role.items.item = 'che_치료_환약';
|
|
const frozen = Object.freeze(general);
|
|
|
|
expect(listEquippedItemKeys(frozen)).toEqual(['che_치료_환약']);
|
|
expect(getEquippedItemInstance(frozen, 'item')?.itemKey).toBe('che_치료_환약');
|
|
expect(frozen.itemInventory).toBeUndefined();
|
|
});
|
|
|
|
it('keeps consumable charges in the equipped item instance', () => {
|
|
const general = makeGeneral();
|
|
equipNewItem(general, 'item', 'che_치료_환약', { charges: 3 });
|
|
|
|
expect(consumeEquippedItemCharge(general, 'item', 'che_치료_환약')).toBe(false);
|
|
expect(getEquippedItemInstance(general, 'item')?.state.charges).toBe(2);
|
|
expect(consumeEquippedItemCharge(general, 'item', 'che_치료_환약')).toBe(false);
|
|
expect(consumeEquippedItemCharge(general, 'item', 'che_치료_환약')).toBe(true);
|
|
expect(general.role.items.item).toBeNull();
|
|
expect(getEquippedItemInstance(general, 'item')).toBeNull();
|
|
});
|
|
|
|
it('round-trips inventory state through the persisted meta representation', () => {
|
|
const general = makeGeneral();
|
|
equipNewItem(general, 'item', 'che_치료_환약', {
|
|
charges: 2,
|
|
values: { source: 'shop' },
|
|
});
|
|
const serialized = serializeItemInventory(general.itemInventory!);
|
|
const parsed = parseItemInventory(serialized, {
|
|
horse: null,
|
|
weapon: null,
|
|
book: null,
|
|
item: null,
|
|
});
|
|
|
|
expect(projectItemSlots(parsed).item).toBe('che_치료_환약');
|
|
expect(Object.values(parsed.instances)[0]?.state).toEqual({
|
|
charges: 2,
|
|
values: { source: 'shop' },
|
|
});
|
|
});
|
|
});
|