import { describe, it, expect } from 'vitest'; import { parseCharacterImport, CharacterImportError } from './character'; import { characterSchema, characterDefaults, type Character } from '@/lib/schemas'; function sampleCharacter(): Character { return characterSchema.parse({ id: 'orig', campaignId: 'orig-camp', system: '5e', kind: 'pc', name: 'Imported Hero', ancestry: 'Elf', className: 'Ranger', level: 4, abilities: { str: 12, dex: 16, con: 14, int: 10, wis: 13, cha: 8 }, hp: { current: 30, max: 30, temp: 0 }, speed: 30, armorBonus: 2, skillRanks: { stealth: 'expert' }, saveRanks: {}, perceptionRank: 'trained', ...characterDefaults(), notes: 'hi', createdAt: 'x', updatedAt: 'x', }); } describe('parseCharacterImport', () => { it('round-trips a wrapped export, reassigning id + campaign', () => { const c = sampleCharacter(); const file = JSON.stringify({ format: 'ttrpg-manager:character', version: 1, character: c }); const imported = parseCharacterImport(file, 'new-camp'); expect(imported.name).toBe('Imported Hero'); expect(imported.campaignId).toBe('new-camp'); expect(imported.id).not.toBe('orig'); expect(imported.abilities.dex).toBe(16); expect(imported.skillRanks['stealth']).toBe('expert'); }); it('accepts a bare character object too', () => { const c = sampleCharacter(); const imported = parseCharacterImport(JSON.stringify(c), 'camp2'); expect(imported.name).toBe('Imported Hero'); expect(imported.campaignId).toBe('camp2'); }); it('rejects invalid JSON', () => { expect(() => parseCharacterImport('{not json', 'c')).toThrow(CharacterImportError); }); it('rejects a file that is not a character', () => { expect(() => parseCharacterImport(JSON.stringify({ foo: 1 }), 'c')).toThrow(CharacterImportError); }); });