import { describe, expect, it } from 'vitest'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { createTemplateStore } from './templates'; // The project root is the parent of server/ (mirrors how server/index.ts and // server/regions.test.ts locate it via import.meta.url). const root = fileURLToPath(new URL('..', import.meta.url)); const templatesDir = path.join(root, 'presets', 'templates'); const store = createTemplateStore(templatesDir); /** A well-formed ISO_A3 country code: exactly three uppercase letters. */ function isIsoA3(code: string): boolean { return /^[A-Z]{3}$/.test(code); } describe('era templates store (v0.31.0, #52)', () => { it('the manifest lists exactly the three era templates', () => { const meta = store.listMeta(); expect(meta).toHaveLength(3); const ids = meta.map((m) => m.id); expect(ids).toEqual(['ww2', 'present', 'near-future']); for (const m of meta) { expect(m.id).toBeTruthy(); expect(m.name).toBeTruthy(); expect(typeof m.year).toBe('number'); expect(m.eraDescription).toBeTruthy(); } }); it('each template file loads and is well-formed', () => { for (const m of store.listMeta()) { const t = store.get(m.id); expect(t, `template ${m.id} should load`).not.toBeNull(); const tpl = t as NonNullable; expect(tpl.id).toBe(m.id); expect(tpl.name).toBe(m.name); expect(tpl.year).toBe(m.year); expect(tpl.eraDescription).toBeTruthy(); // suggested powers: non-empty, each a named power with an ISO_A3 core region + note. expect(tpl.suggestedPowers.length).toBeGreaterThan(0); for (const p of tpl.suggestedPowers) { expect(p.name).toBeTruthy(); expect(isIsoA3(p.region)).toBe(true); expect(p.note).toBeTruthy(); } // tensions: a non-empty list of non-empty strings. expect(tpl.tensions.length).toBeGreaterThan(0); for (const s of tpl.tensions) expect(typeof s).toBe('string'); for (const s of tpl.tensions) expect(s.trim()).not.toBe(''); } }); it('get returns null for an unknown id', () => { expect(store.get('does-not-exist')).toBeNull(); expect(store.get('')).toBeNull(); }); });