open-design/apps/web/tests/runtime/react-component.test.ts
PerishFire bbdd4e84b5
chore: enforce test directory conventions (#496)
* chore: enforce test directory conventions

Move package, app, and tool tests out of src and add guard enforcement so source directories stay source-only.

* ci: use guard and package-scoped tests

Run the new repository guard in CI and keep test execution aligned with package-scoped commands after removing root aliases.

* ci: align stable release guard check

Use the new repository guard in stable release verification after replacing the residual-JS-only script.

* chore: tighten test layout enforcement

Enforce sibling tests directories, typecheck moved test suites with dedicated configs, and refresh remaining guidance that pointed at src-based tests.

* chore: clarify no-emit test tsconfigs

Explicitly disable declaration-only emit in test tsconfigs so review tooling sees they are no-emit typecheck configs.
2026-05-05 15:34:22 +08:00

61 lines
2.3 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { buildReactComponentSrcdoc, prepareReactComponentSource } from '../../src/runtime/react-component';
describe('prepareReactComponentSource', () => {
it('adapts a default function export for iframe rendering', () => {
const out = prepareReactComponentSource(`
import React from 'react';
export default function Card() {
return <div>Card</div>;
}
`);
expect(out).not.toContain('import React');
expect(out).toContain('function Card()');
expect(out).toContain('window.__OpenDesignComponent');
expect(out).toContain("typeof Card !== 'undefined' ? Card : null");
});
it('adapts a named component export for iframe rendering', () => {
const out = prepareReactComponentSource('export const Preview = () => <main />;');
expect(out).toContain('const Preview =');
expect(out).toContain("typeof Preview !== 'undefined' ? Preview : null");
});
it('preserves React hook imports as runtime bindings', () => {
const out = prepareReactComponentSource(`
import { useState, useEffect as useReactEffect } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
useReactEffect(() => setCount(1), []);
return <button>{count}</button>;
}
`);
expect(out).not.toContain("import { useState");
expect(out).toContain('const { useState, useEffect: useReactEffect } = window.React;');
expect(out).toContain('function Counter()');
});
it('detects default re-exports before removing export specifiers', () => {
const out = prepareReactComponentSource(`
const Foo = () => <main />;
export { Foo as default };
`);
expect(out).not.toContain('export { Foo as default }');
expect(out).toContain("typeof Foo !== 'undefined' ? Foo : null");
});
});
describe('buildReactComponentSrcdoc', () => {
it('builds a standalone sandbox document with React runtime scripts', () => {
const doc = buildReactComponentSrcdoc('export default function App(){ return <div /> }', {
title: 'App',
});
expect(doc).toContain('<!doctype html>');
expect(doc).toContain('react@18/umd/react.development.js');
expect(doc).toContain('@babel/standalone');
expect(doc).toContain('artifact.tsx');
expect(doc).toContain('sandboxed iframe');
expect(doc).toContain('(0, eval)(compiled)');
});
});