import { readFileSync } from 'node:fs' import { join, resolve } from 'node:path' import { describe, expect, it } from 'vitest' import { visualStates } from '../states' import { localizationSizeLabel, parseLocalizationScreen, parseSelector, parseSizes, } from '../localizationScreen' const designRoot = resolve(import.meta.dirname, '..', '..', '..', 'docs', 'design') const screen = parseLocalizationScreen( readFileSync(join(designRoot, 'screens', 'localization-site-languages.md'), 'utf8'), ) function ids(label: string) { return screen.groups .find((group) => group.label.startsWith(`${label} `))! .states.map((s) => s.id) } describe('Localization groups are discovered from the screen file', () => { it('reads the board named by the reference line', () => { expect(screen.board).toBe('RenewCMS Screens Localization.dc.html') }) it('finds the groups L1, L1b and L2 with 25, 9 and 7 states', () => { expect(screen.groups.map((group) => group.label)).toEqual([ 'L1 Site languages', 'L1b Public URL pattern (owner setting)', 'L2 First-time setup for existing articles', ]) expect(screen.groups.map((group) => group.states.length)).toEqual([25, 9, 7]) }) it('lists the states by their loc ids', () => { expect(ids('L1').slice(0, 3)).toEqual(['loc.l1.single', 'loc.l1.multi', 'loc.l1.loading']) expect(ids('L1b')[0]).toBe('loc.l1b.set') expect(ids('L2').at(-1)).toBe('loc.l2.fail') expect(ids('L1')).toContain('loc.lang.disableDefault') }) it('has no duplicate id', () => { const every = screen.groups.flatMap((group) => group.states.map((state) => state.id)) expect(new Set(every).size).toBe(41) }) }) describe('Capture sizes', () => { it.each([ ['1440, 390', [1440, 390]], ['1440, 1024, 390', [1440, 1024, 390]], ])('parses %s', (cell, expected) => { expect(parseSizes(cell)).toEqual(expected) }) it('gives a 1024 capture to loc.l1.multi and loc.l1.social only', () => { const wide = screen.groups .flatMap((group) => group.states) .filter((state) => state.sizes.includes(1024)) .map((state) => state.id) expect(wide).toEqual(['loc.l1.multi', 'loc.l1.social']) }) it('names the viewports', () => { expect([1440, 1024, 390].map(localizationSizeLabel)).toEqual([ 'desktop', 'tablet', 'mobile', ]) }) }) describe('Selecting frames', () => { it('maps an id to its LocaleFrame selector and fixture', () => { const multi = screen.groups[0]!.states.find((state) => state.id === 'loc.l1.multi')! expect(multi.selector).toEqual({ v: 'sl', x: 'multi' }) expect(multi.fixture).toBe('Journal') expect(multi.name).toBe('Multilingual') const setup = screen.groups[2]!.states.find((state) => state.id === 'loc.l2.ready')! expect(setup.selector).toEqual({ v: 'su', x: 'ready' }) expect(setup.fixture).toBe('Journal, Notes, Archive') }) it('refuses a cell that is not a LocaleFrame selector', () => { expect(() => parseSelector('Frame{x}')).toThrow() }) }) describe('Every state has a setup', () => { const setups = visualStates['localization-site-languages'] ?? {} it('covers the 41 ids and nothing else', () => { const every = screen.groups.flatMap((group) => group.states.map((state) => state.id)) expect(Object.keys(setups).sort()).toEqual([...every].sort()) }) it('skips no state and grants no exception', () => { for (const setup of Object.values(setups)) { expect(setup.skip).toBeUndefined() expect(setup.exception).toBeUndefined() } }) }) describe('Existing screens are unaffected', () => { it('reports the parser as the only discovery for localization screens', () => { const names = Object.keys(visualStates).filter((name) => name.startsWith('localization-')) expect(names).toEqual(['localization-site-languages']) }) })