import { describe, expect, it } from 'vitest'; import { buildContent } from '../schema'; const validResources = [{ id: 'gold', name: 'Gold' }]; const validActions = [ { id: 'forage', name: 'Forage', durationMs: 3000, yields: [{ resourceId: 'gold', amount: 1 }], }, ]; describe('buildContent()', () => { it('validates definitions and indexes them by id', () => { const content = buildContent({ resources: validResources, actions: validActions }); expect(content.resourcesById.gold.name).toBe('Gold'); expect(content.actionsById.forage.durationMs).toBe(3000); }); it('applies the startAmount default of 0', () => { const content = buildContent({ resources: validResources, actions: validActions }); expect(content.resourcesById.gold.startAmount).toBe(0); }); it('rejects an action that yields an unknown resource', () => { const actions = [ { id: 'forage', name: 'Forage', durationMs: 3000, yields: [{ resourceId: 'ghost', amount: 1 }], }, ]; expect(() => buildContent({ resources: validResources, actions })).toThrow(/unknown resource/i); }); it('rejects duplicate resource ids', () => { const resources = [ { id: 'gold', name: 'Gold' }, { id: 'gold', name: 'Gold Again' }, ]; expect(() => buildContent({ resources, actions: validActions })).toThrow(/duplicate/i); }); it('rejects a structurally invalid definition', () => { const actions = [ { id: 'forage', name: 'Forage', durationMs: -1, yields: [{ resourceId: 'gold', amount: 1 }], }, ]; expect(() => buildContent({ resources: validResources, actions })).toThrow(); }); }); describe('costs and multi-yield', () => { it('accepts optional costs and multiple yields', () => { const resources = [ { id: 'gold', name: 'Gold' }, { id: 'wood', name: 'Wood' }, ]; const actions = [ { id: 'craft', name: 'Craft', durationMs: 1000, costs: [{ resourceId: 'wood', amount: 2 }], yields: [ { resourceId: 'gold', amount: 1 }, { resourceId: 'wood', amount: 1 }, ], }, ]; const content = buildContent({ resources, actions }); expect(content.actionsById.craft.costs).toEqual([{ resourceId: 'wood', amount: 2 }]); expect(content.actionsById.craft.yields).toHaveLength(2); }); it('rejects cost referencing unknown resource', () => { const actions = [ { id: 'craft', name: 'Craft', durationMs: 1000, costs: [{ resourceId: 'ghost', amount: 1 }], yields: [{ resourceId: 'gold', amount: 1 }], }, ]; expect(() => buildContent({ resources: validResources, actions })).toThrow(/unknown resource/i); }); it('defaults costs to empty array', () => { const content = buildContent({ resources: validResources, actions: validActions }); expect(content.actionsById.forage.costs).toEqual([]); }); }); describe('unlock conditions', () => { it('accepts optional minResources and requireStoryFlags', () => { const actions = [ { id: 'forage', name: 'Forage', durationMs: 3000, yields: [{ resourceId: 'gold', amount: 1 }], unlock: { minResources: { gold: 10 }, requireStoryFlags: ['intro_complete'], }, }, ]; const content = buildContent({ resources: validResources, actions }); expect(content.actionsById.forage.unlock).toEqual({ minResources: { gold: 10 }, requireStoryFlags: ['intro_complete'], }); }); it('defaults unlock to undefined when omitted', () => { const content = buildContent({ resources: validResources, actions: validActions }); expect(content.actionsById.forage.unlock).toBeUndefined(); }); }); describe('action narrative fields', () => { it('accepts optional storyHint and storyTooltip', () => { const actions = [ { id: 'forage', name: 'Forage', durationMs: 3000, yields: [{ resourceId: 'gold', amount: 1 }], storyHint: 'Gather what the forest offers.', storyTooltip: 'Your first step into the wild.', }, ]; const content = buildContent({ resources: validResources, actions }); expect(content.actionsById.forage.storyHint).toBe('Gather what the forest offers.'); expect(content.actionsById.forage.storyTooltip).toBe('Your first step into the wild.'); }); it('defaults storyHint and storyTooltip to undefined when omitted', () => { const content = buildContent({ resources: validResources, actions: validActions }); expect(content.actionsById.forage.storyHint).toBeUndefined(); expect(content.actionsById.forage.storyTooltip).toBeUndefined(); }); });