import { describe, expect, it } from "vitest"; import { extraRichTextToPlainText, applyRichTextStylePatch, normalizeExtraRichText, richTextContentSignature, sanitizeRichTextHtml, sanitizeRichTextUrl, } from "@/lib/rich-text"; describe("rich text sanitization", () => { it("keeps supported formatting, colors, and safe links", () => { expect(sanitizeRichTextHtml( '

Good news link

', )).toBe( '

Good news link

', ); }); it("normalizes browser-generated RGB text colors to safe hex colors", () => { expect(sanitizeRichTextHtml( '

green yellow

', )).toBe( '

green yellow

', ); }); it("removes executable markup, unsafe links, and unsupported styles", () => { expect(sanitizeRichTextHtml( '

Safe textlink

', )).toBe("

Safe textlink

"); expect(sanitizeRichTextUrl("data:text/html,bad")).toBe(""); }); }); describe("legacy Extra rich text conversion", () => { it("converts stored markup into safe multiline text for cell editing", () => { expect(extraRichTextToPlainText( "

First
line

Second & safe

", )).toBe("First\nline\nSecond & safe"); expect(normalizeExtraRichText(extraRichTextToPlainText("

A
B

"))) .toBe("

A
B

"); }); it("escapes plain text, preserves newlines, and converts phrase colors", () => { expect(normalizeExtraRichText("\nMASSIVE damage", [ { text: "MASSIVE", color: "#ff0000" }, ])).toBe( '

<unsafe>
MASSIVE damage

', ); }); it("leaves sanitized rich text in rich-text form", () => { expect(normalizeExtraRichText('

Ready

', [ { text: "Ready", color: "#ff0000" }, ])).toBe("

Ready

"); }); }); describe("bulk rich-text styles", () => { it("applies a style to every text node without replacing structure or links", () => { expect(applyRichTextStylePatch( '

First link

', { bold: true }, )).toBe( '

First link

', ); }); it("removes only requested styles and applies normalized colors", () => { expect(applyRichTextStylePatch( '

Bold and italic

', { bold: false }, )).toBe("

Bold and italic

"); expect(applyRichTextStylePatch("

Red

", { color: "#00ff00" })) .toBe('

Red

'); expect(applyRichTextStylePatch( '

Green

', { color: null }, )).toBe("

Green

"); }); it("compares content independently from visual formatting", () => { expect(richTextContentSignature( '

Same text

', )).toBe("

Same text

"); expect(richTextContentSignature("

Changed text

")) .not.toBe(richTextContentSignature("

Original text

")); }); });