import { describe, expect, it } from 'vitest'; import { collectReferencedJsxNames, extractBabelScriptSrcs, findHtmlEntriesReferencing, htmlLoadsJsxModule, isJsxModule, } from '../../src/runtime/jsx-module-refs'; const MULTI_FILE_HTML = ` Backups Panel
`; describe('extractBabelScriptSrcs', () => { it('returns [] for empty / nullish input', () => { expect(extractBabelScriptSrcs('')).toEqual([]); expect(extractBabelScriptSrcs(null)).toEqual([]); expect(extractBabelScriptSrcs(undefined)).toEqual([]); }); it('lists only text/babel module srcs, in document order', () => { expect(extractBabelScriptSrcs(MULTI_FILE_HTML)).toEqual([ 'tweaks-panel.jsx', 'icons.jsx', 'chrome.jsx', 'app.jsx', ]); }); it('ignores CDN/library '; expect(extractBabelScriptSrcs(html)).toEqual([]); }); it('handles src-before-type attribute order', () => { const html = ''; expect(extractBabelScriptSrcs(html)).toEqual(['app.jsx']); }); it('normalizes a leading ./ and strips query/hash', () => { const html = '' + ''; expect(extractBabelScriptSrcs(html)).toEqual(['icons.jsx', 'chrome.jsx']); }); it('ignores babel scripts commented out in HTML', () => { const html = '' + ''; expect(extractBabelScriptSrcs(html)).toEqual(['app.jsx']); expect(extractBabelScriptSrcs(html)).not.toContain('legacy.jsx'); }); }); describe('htmlLoadsJsxModule', () => { it('matches an exact src reference', () => { expect(htmlLoadsJsxModule(MULTI_FILE_HTML, 'icons.jsx')).toBe(true); }); it('matches by basename when the project name has no slash', () => { const html = ''; expect(htmlLoadsJsxModule(html, 'icons.jsx')).toBe(true); }); it('is false when the module is not referenced', () => { expect(htmlLoadsJsxModule(MULTI_FILE_HTML, 'unused.jsx')).toBe(false); }); it('is false for an empty module name', () => { expect(htmlLoadsJsxModule(MULTI_FILE_HTML, '')).toBe(false); }); }); describe('findHtmlEntriesReferencing', () => { it('returns every HTML entry that loads the module, in map order', () => { const sources = new Map([ ['Backups Panel.html', MULTI_FILE_HTML], ['Overview Panel.html', ''], ['Unrelated.html', ''], ]); expect(findHtmlEntriesReferencing('icons.jsx', sources)).toEqual([ 'Backups Panel.html', 'Overview Panel.html', ]); }); it('returns [] when no HTML references the module (standalone artifact)', () => { const sources = new Map([['Page.html', '
no scripts
']]); expect(findHtmlEntriesReferencing('icons.jsx', sources)).toEqual([]); }); }); describe('isJsxModule', () => { it('is true when at least one HTML entry loads the file', () => { const sources = new Map([['Backups Panel.html', MULTI_FILE_HTML]]); expect(isJsxModule('app.jsx', sources)).toBe(true); }); it('is false when nothing references the file', () => { const sources = new Map([['Backups Panel.html', MULTI_FILE_HTML]]); expect(isJsxModule('standalone-component.jsx', sources)).toBe(false); }); }); describe('collectReferencedJsxNames', () => { const files = [ { name: 'Backups Panel.html' }, { name: 'tweaks-panel.jsx' }, { name: 'icons.jsx' }, { name: 'chrome.jsx' }, { name: 'app.jsx' }, { name: 'standalone.jsx' }, { name: 'styles.css' }, ]; it('returns project file names loaded by an HTML entry, excluding unreferenced ones', async () => { const read = async (name: string) => name === 'Backups Panel.html' ? MULTI_FILE_HTML : null; const result = await collectReferencedJsxNames(files, read); expect(result).toEqual(new Set(['tweaks-panel.jsx', 'icons.jsx', 'chrome.jsx', 'app.jsx'])); // A .jsx that no HTML loads stays a normal standalone artifact. expect(result.has('standalone.jsx')).toBe(false); }); it('ignores '; const result = await collectReferencedJsxNames(files, read); expect(result.size).toBe(0); }); it('returns an empty set when no HTML entries exist', async () => { const read = async () => null; const result = await collectReferencedJsxNames([{ name: 'only.jsx' }], read); expect(result).toEqual(new Set()); }); });