/* eslint-disable unicorn/prevent-abbreviations */ import type { dia } from '@joint/core'; import { jsx } from '../jsx-to-markup'; import type { PropsWithChildren } from 'react'; describe('jsx-to-markup', () => { it('should convert div with span', () => { const markup = jsx(
Hello
); const expected: dia.MarkupJSON = [ { tagName: 'div', children: [ { tagName: 'span', children: ['Hello'], attributes: {}, }, ], attributes: { id: '1', }, }, ]; expect(markup).toEqual(expected); }); it('should convert svg', () => { const markup = jsx( ); const expected: dia.MarkupJSON = [ { tagName: 'svg', children: [ { tagName: 'circle', children: [], attributes: { cx: 50, cy: 50, r: 50 }, }, ], attributes: {}, }, ]; expect(markup).toEqual(expected); }); it('should convert with multiple children', () => { const markup = jsx( ); const expected: dia.MarkupJSON = [ { tagName: 'svg', children: [ { tagName: 'circle', children: [], attributes: { cx: 51, cy: 51, r: 51 }, }, { tagName: 'circle', children: [], attributes: { cx: 52, cy: 52, r: 52 }, }, { tagName: 'circle', children: [], attributes: { cx: 53, cy: 53, r: 53 }, }, ], attributes: {}, }, ]; expect(markup).toEqual(expected); }); it('should convert with custom component and html children', () => { function CustomComponent(props: Readonly) { return
{props.children}
; } const markup = jsx( Hello ); const expected: dia.MarkupJSON = [ { tagName: 'div', children: [ { tagName: 'span', children: ['Hello'], attributes: {}, }, ], attributes: {}, }, ]; expect(markup).toEqual(expected); }); it('should convert nested props drilling', () => { function CustomComponent(props: Readonly>) { return (
{props.children} {props.id}
); } const markup = jsx( Hello ); const expected: dia.MarkupJSON = [ { tagName: 'div', children: [ { tagName: 'span', children: ['Hello'], attributes: {}, }, { tagName: 'span', children: ['1'], attributes: { id: '1', }, }, ], attributes: { id: '1', }, }, ]; expect(markup).toEqual(expected); }); it('should convert with fragment', () => { const markup = jsx( <> ); const expected: dia.MarkupJSON = [ { tagName: 'circle', children: [], attributes: { r: 7, fill: '#001DFF', cursor: 'pointer', }, }, { tagName: 'path', children: [], attributes: { d: 'M -2 4 2 4 M 0 3 0 0 M -2 -1 1 -1 M -1 -4 1 -4', fill: 'none', stroke: '#FFFFFF', strokeWidth: 2, pointerEvents: 'none', }, }, ]; expect(markup).toEqual(expected); }); it('should handle non-record props gracefully', () => { const markup = jsx({} as never); expect(markup).toEqual([]); }); it('should handle extractJointAttributes with non-record input (explicit)', () => { // This is covered by jsx({} as never), but let's make it explicit expect(jsx({} as never)).toEqual([]); }); it('should handle non-element input gracefully', () => { expect(jsx(null as never)).toEqual([]); expect(jsx(undefined as never)).toEqual([]); }); it('should skip function type that is not a React component', () => { const markup = jsx( // @ts-expect-error we use internal api here ($$typeof) { type: () =>
, props: {}, $$typeof: Symbol.for('react.element') } ); // The function returns
, so the result is markup for a div expect(markup).toEqual([ { tagName: 'div', children: [], attributes: {}, }, ]); }); it('should handle React component function returning a primitive', () => { // eslint-disable-next-line unicorn/consistent-function-scoping function PrimitiveComponent() { return 'primitive'; } // Should return [] because isValidElement('primitive') is false expect(jsx()).toEqual([]); }); it('should throw on unsupported child type', () => { const BadChild = () =>
{{ foo: 'bar' } as never}
; expect(() => jsx()).toThrow('Unsupported child type: object'); }); it('should handle boolean, number, null children', () => { function NumBoolNull() { return
{[1, true, null]}
; } const markup = jsx(); expect(markup).toEqual([ { tagName: 'div', children: ['1', 'true', 'null'], attributes: {}, }, ]); }); it('should extract joint- attributes', () => { const markup = jsx(
Hello
); expect(markup).toEqual([ { tagName: 'div', children: [ { tagName: 'span', children: ['Hello'], attributes: {}, }, ], attributes: { id: 'foo' }, bar: 'baz', num: 5, }, ]); }); it('should handle React component function returning null', () => { // eslint-disable-next-line unicorn/consistent-function-scoping function NullComponent() { return null; } const markup = jsx(); expect(markup).toEqual([]); }); it('should handle element with no children', () => { const markup = jsx(); expect(markup).toEqual([ { tagName: 'rect', children: [], attributes: { width: 10, height: 20 }, }, ]); }); it('should handle element with no children (e.g.
)', () => { const markup = jsx(
); expect(markup).toEqual([ { tagName: 'hr', children: [], attributes: {}, }, ]); }); it('should handle element with string children', () => { const markup = jsx(Hello world); expect(markup).toEqual([ { tagName: 'text', children: ['Hello world'], attributes: {}, }, ]); }); });