import { createElement } from "react" import { renderToStaticMarkup } from "react-dom/server" import { expect, test } from "vitest" import { HtmlView } from "./HtmlView.tsx" import { toHtmlContent, toSafeHtml, toSafeHtmlColour, } from "./safeHtml.ts" test("the reader renders safe HTML on the server without a DOM or editor runtime", () => { expect(typeof window).toBe("undefined") const html = renderToStaticMarkup( createElement(HtmlView, { label: "Server notes", value: '

Stored & safe

Read', }), ) expect(html).toContain("Stored & safe") expect(html).toContain('role="document"') expect(html).not.toMatch( /onclick| { expect( toSafeHtml( '

Keep & read.

hiddenhidden
', ), ).toBe( "

Keep & read.

", ) }) test.each([ "javascript:attack()", "javascript:attack()", "JaVa Script:attack()", "data:text/html,attack", "file:///private", "vbscript:attack()", ])( "decodes and rejects an unsafe link scheme: %s", (href) => { expect( toSafeHtml( `Read`, ), ).toBe('Read') }, ) test.each([ "https://example.invalid/notes", "/notes", "./notes", "#section", "mailto:help@example.invalid", "tel:1234", ])("keeps a permitted link: %s", (href) => { expect(toSafeHtml(`Read`)).toBe( `Read`, ) }) test("image attributes are closed and rejected image sources disappear", () => { expect( toSafeHtml( 'A & B', ), ).toBe('A & B') }) test("retains only document colour and alignment; CSS cannot load resources or escape the surface", () => { expect( toSafeHtml( '

Notes

', ), ).toBe( '

Notes

', ) expect( toSafeHtml( 'Notes', ), ).toBe("Notes") expect( toSafeHtmlColour("red;position:fixed"), ).toBeUndefined() expect(toSafeHtmlColour("url(/tracker)")).toBeUndefined() }) test("an HTML5 parse, rather than regex replacement, contains malformed foreign content", () => { const safe = toSafeHtml( '', ) expect(safe).not.toMatch(/onerror| { const original = "

5 < 6 & \"quoted\"

" const safe = toSafeHtml(original) expect(safe).toBe( "

5 < 6 & "quoted"

", ) expect(toSafeHtml(safe)).toBe(safe) expect(toHtmlContent(original)).toEqual([ { tag: "p", attributes: {}, children: [{ text: '5 < 6 & "quoted"' }], }, ]) expect(original).toBe( "

5 < 6 & \"quoted\"

", ) })