import { describe, it, expect } from 'vitest'; import { PAGE_IDS, ROUTES, pathFor, pageIdFromPath, localeFromPath, twinPath, allRoutes, } from '@i18n/slugMap'; import { LOCALES } from '@i18n/locales'; describe('slug map contract (ROUTING_SPEC §1, ARCHITECTURE A5)', () => { it('every pageId has a path in both locales', () => { for (const id of PAGE_IDS) { for (const locale of LOCALES) { const p = ROUTES[id][locale]; expect(p, `${id}.${locale}`).toMatch(/^\/.*\/$|^\/$/); // trailing slash canonical } } }); it('all paths are unique (bijection — no two routes collide)', () => { const paths = allRoutes().map((r) => r.path); expect(new Set(paths).size).toBe(paths.length); }); it('NO paths are prefixed with /no and use localised slugs', () => { for (const id of PAGE_IDS) { expect(ROUTES[id].no.startsWith('/no/') || ROUTES[id].no === '/no/').toBe(true); } expect(ROUTES.projects.no).toBe('/no/prosjekter/'); expect(ROUTES.homelab.no).toBe('/no/prosjekter/hjemmelab/'); expect(ROUTES.about.no).toBe('/no/om-meg/'); }); it('pageIdFromPath round-trips for every route', () => { for (const id of PAGE_IDS) { for (const locale of LOCALES) { expect(pageIdFromPath(pathFor(id, locale))).toBe(id); } } }); it('localeFromPath detects the locale', () => { expect(localeFromPath('/projects/jobtrack/')).toBe('en'); expect(localeFromPath('/no/prosjekter/jobtrack/')).toBe('no'); expect(localeFromPath('/')).toBe('en'); expect(localeFromPath('/no/')).toBe('no'); }); it('twinPath maps a page to its twin locale and back', () => { for (const id of PAGE_IDS) { const en = pathFor(id, 'en'); const no = pathFor(id, 'no'); expect(twinPath(en, 'no')).toBe(no); expect(twinPath(no, 'en')).toBe(en); } }); it('twinPath falls back to the target home for unmapped paths', () => { expect(twinPath('/nonsense/', 'no')).toBe('/no/'); expect(twinPath('/no/tull/', 'en')).toBe('/'); }); });