import React from 'react'; import * as html from '../html'; describe('html', () => { describe('unescapeHTML', () => { it('returns unescaped HTML', () => { const output = html.unescapeHTML( '
lorem
ipsum
lorem ipsum
'; const output = html.htmlStringToComponents(input); expect(output).toMatchSnapshot(); }); it('handles nested elements', () => { const input = 'lorem ipsum
'; const output = html.htmlStringToComponents(input); expect(output).toMatchSnapshot(); }); it('ignores empty text nodes', () => { const input = 'lorem ipsum
'; const output = html.htmlStringToComponents(input); expect(output).toMatchSnapshot(); }); it('copies attributes to props', () => { const input = 'link'; const output = html.htmlStringToComponents(input); expect(output).toMatchSnapshot(); }); it('respects maxDepth option', () => { const input = 'lorem ipsum
'; const output = html.htmlStringToComponents(input, { maxDepth: 2 }); expect(output).toMatchSnapshot(); }); it('calls onText callback', () => { const input = 'lorem ipsum
'; const onText = vi.fn((text: string) => text); html.htmlStringToComponents(input, { onText }); expect(onText).toHaveBeenCalledExactlyOnceWith('lorem ipsum', {}); }); it('calls onElement callback', () => { const input = 'lorem ipsum
'; const onElement = vi.fnlorem ipsum
'; const onElement = vi.fn(() => undefined); const output = html.htmlStringToComponents(input, { onElement }); expect(onElement).toHaveBeenCalledExactlyOnceWith( expect.objectContaining({ tagName: 'P' }), // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment expect.objectContaining({ key: expect.any(String) }), expect.arrayContaining(['lorem ipsum']), {}, ); expect(output).toMatchSnapshot(); }); it('calls onAttribute callback', () => { const input = 'link'; const onAttribute = vi.fn( (name: string, value: string) => [name, value] satisfies [string, string], ); html.htmlStringToComponents(input, { onAttribute }); expect(onAttribute).toHaveBeenCalledTimes(3); expect(onAttribute).toHaveBeenCalledWith( 'href', 'https://example.com', 'a', {}, ); expect(onAttribute).toHaveBeenCalledWith('target', '_blank', 'a', {}); expect(onAttribute).toHaveBeenCalledWith('rel', 'nofollow', 'a', {}); }); it('respects allowedTags option', () => { const input = 'lorem ipsum dolor
'; const output = html.htmlStringToComponents(input, { allowedTags: { p: {}, em: {} }, }); expect(output).toMatchSnapshot(); }); it('ensure performance is acceptable with large input', () => { const input = '' + 'lorem'.repeat(1_000) + '
'; const start = performance.now(); html.htmlStringToComponents(input); const duration = performance.now() - start; // Arbitrary threshold of 200ms for this test. // Normally it's much less (<50ms), but the GH Action environment can be slow. expect(duration).toBeLessThan(200); }); }); });