Files
maestro/ui/ui-source-plugin.test.ts
oss-sync 57702b4f34
CI / build-and-test (push) Canceled after 0s
sync: update from private repo (2336949a)
2026-09-17 11:29:31 +00:00

59 lines
3.4 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { annotateUiSource, uiSourcePlugin } from './ui-source-plugin';
const root = '/private/work/project/ui';
const id = `${root}/src/screens/Panel.tsx`;
const annotate = (code: string, filename = id) => annotateUiSource(code, filename, root);
describe('UI source annotation', () => {
it('records original one-based locations and preserves the original TSX', () => {
const input = 'export function Panel() {\n return <section title="secret"><input value={token} /></section>;\n}\n';
const output = annotate(input)!;
expect(output).toContain('<section data-ui-source="ui/src/screens/Panel.tsx:2:10" data-ui-component="Panel" title="secret">');
expect(output).toContain('<input data-ui-source="ui/src/screens/Panel.tsx:2:34" data-ui-component="Panel" value={token} />');
expect(output.replace(/ data-ui-(?:source|component)="[^"]*"/g, '')).toBe(input);
const metadata = output.match(/ data-ui-(?:source|component)="[^"]*"/g)!.join('');
expect(metadata).not.toMatch(/private|secret|token/);
});
it('handles fragments, nested callbacks, arrows and wrapped components', () => {
const output = annotate('const Panel = memo(() => <><div>{items.map(item => <span />)}</div><Child /></>);')!;
expect(output.match(/data-ui-component="Panel"/g)).toHaveLength(2);
expect(output).toContain('<Child />');
expect(output).not.toContain('<> data');
});
it('respects manually supplied attributes individually', () => {
const output = annotate('function Panel() { return <div data-ui-source="manual" data-ui-component="Custom" />; }')!;
expect(output.match(/data-ui-source=/g)).toHaveLength(1);
expect(output.match(/data-ui-component=/g)).toHaveLength(1);
expect(output).toContain('data-ui-source="manual" data-ui-component="Custom"');
});
it.each(['src/Panel.test.tsx', 'src/Panel.spec.tsx', 'src/test/Panel.tsx', 'src/__tests__/Panel.tsx', 'src/vendor/Panel.tsx', 'node_modules/Panel.tsx', 'src/Panel.ts', '../outside.tsx', 'src/Panel.tsx?raw'])('excludes %s', (file) => {
expect(annotate('const Panel = () => <div />', `${root}/${file}`)).toBeNull();
});
it('omits missing component names and escapes metadata paths', () => {
expect(annotate('<div />')!).not.toContain('data-ui-component');
expect(annotate('<div />', `${root}/src/a"b.tsx`)).toContain('a&quot;b.tsx:1:1');
});
it('marks raw HTML hosts without collecting their HTML or annotating custom components', () => {
const input = 'function Preview() { return <><div dangerouslySetInnerHTML={{ __html: secretHtml }} /><section dangerouslySetInnerHTML={{ __html: secretHtml }}></section><Child dangerouslySetInnerHTML={{ __html: secretHtml }} /><span /></>; }';
const output = annotate(input)!;
expect(output.match(/data-ui-content-boundary="true"/g)).toHaveLength(2);
expect(output).toContain('<Child dangerouslySetInnerHTML={{ __html: secretHtml }} />');
expect(output.replace(/ data-ui-(?:source|component|content-boundary)="[^"]*"/g, '')).toBe(input);
});
it('does not duplicate an explicit raw HTML boundary marker', () => {
const output = annotate('<div data-ui-content-boundary="true" dangerouslySetInnerHTML={{ __html: html }} />')!;
expect(output.match(/data-ui-content-boundary=/g)).toHaveLength(1);
});
it('runs before React transforms', () => {
expect(uiSourcePlugin(root).enforce).toBe('pre');
});
});