import { toHaveNoViolations } from 'jest-axe'; import '@testing-library/jest-dom'; import format, { plugins } from 'pretty-format'; import jsdom from 'jsdom'; function formatHTML(nodes: any) { const htmlContent = format(nodes, { plugins: [plugins.DOMCollection, plugins.DOMElement], }); const filtered = htmlContent .split(/[\n\r]+/) .filter(line => line.trim()) .map(line => line.replace(/\s+$/, '')) .join('\n'); return filtered; } /** * React 17 & 18 will have different behavior in some special cases: * * React 17: * * ```html * Hello World * ``` * * React 18: * * ```html * Hello World * ``` * * These diff is nothing important in front end but will break in snapshot diff. */ expect.addSnapshotSerializer({ test: element => typeof HTMLElement !== 'undefined' && (element instanceof HTMLElement || element instanceof DocumentFragment || element instanceof HTMLCollection || (Array.isArray(element) && element[0] instanceof HTMLElement)), print: element => formatHTML(element), }); /** Demo Test only accept render as SSR to make sure align with both `server` & `client` side */ expect.addSnapshotSerializer({ test: node => node && typeof node === 'object' && node.type === 'demo' && node.html, print: ({ html }) => { const { JSDOM } = jsdom; const { document } = new JSDOM().window; document.body.innerHTML = html; const children = Array.from(document.body.childNodes); // Clean up `data-reactroot` since React 18 do not have this children.forEach((ele: HTMLElement) => { if (typeof ele.removeAttribute === 'function') { ele.removeAttribute('data-reactroot'); } }); return formatHTML(children.length > 1 ? children : children[0]); }, }); expect.extend(toHaveNoViolations);