/** * Module-registry planner test — Phase 4 is the slimmest publish * phase (revision selection lives inside `celilo module publish`), * so the planner is a thin wrap around `listModuleDirs`. We test * the pure inner `mapModuleDirsToItems` directly so the test surface * doesn't need to mock `./helpers` — mocking that path leaks to * unrelated tests via bun:test's process-global mock.module. */ import { describe, expect, test } from 'bun:test'; import { applyModuleSkips, mapModuleDirsToItems } from './module-registry'; describe('mapModuleDirsToItems', () => { test('empty input → empty plan', () => { expect(mapModuleDirsToItems([])).toEqual([]); }); test('wraps each discovered module dir in a ModuleItem', () => { expect( mapModuleDirsToItems([ '/repo/modules/caddy', '/repo/modules/homebridge', '/repo/modules/dns-external', ]), ).toEqual([ { moduleDir: '/repo/modules/caddy' }, { moduleDir: '/repo/modules/homebridge' }, { moduleDir: '/repo/modules/dns-external' }, ]); }); test('preserves input order', () => { const result = mapModuleDirsToItems(['/repo/modules/z', '/repo/modules/a', '/repo/modules/m']); expect(result.map((m) => m.moduleDir)).toEqual([ '/repo/modules/z', '/repo/modules/a', '/repo/modules/m', ]); }); }); describe('applyModuleSkips', () => { const items = mapModuleDirsToItems([ '/repo/modules/caddy', '/repo/modules/burner', '/repo/modules/homebridge', ]); test('no skips leaves the plan unchanged', () => { expect(applyModuleSkips(items, [])).toEqual(items); }); test('drops each named module and keeps the order of the rest', () => { expect(applyModuleSkips(items, ['burner']).map((m) => m.moduleDir)).toEqual([ '/repo/modules/caddy', '/repo/modules/homebridge', ]); }); test('a name that matches no module directory throws and names it', () => { expect(() => applyModuleSkips(items, ['burnr'])).toThrow('burnr'); }); });