Files
buzz-sheet/lib/rich-text.test.ts
T
gunshiz 5314996ef3
CI / Verify (push) Successful in 1m4s
CI / Build immutable images and deploy (push) Successful in 2m28s
fix(extra) : preserve rich text colors
2026-09-05 13:28:56 +07:00

49 lines
1.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
normalizeExtraRichText,
sanitizeRichTextHtml,
sanitizeRichTextUrl,
} from "@/lib/rich-text";
describe("rich text sanitization", () => {
it("keeps supported formatting, colors, and safe links", () => {
expect(sanitizeRichTextHtml(
'<p><strong>Good</strong> <span style="color: #ff3b30">news</span> <a href="https://example.com" onclick="bad()">link</a></p>',
)).toBe(
'<p><strong>Good</strong> <span style="color: #FF3B30">news</span> <a href="https://example.com" target="_blank" rel="noopener noreferrer">link</a></p>',
);
});
it("normalizes browser-generated RGB text colors to safe hex colors", () => {
expect(sanitizeRichTextHtml(
'<p><span style="color: rgb(0, 255, 0);">green</span> <span style="color: rgb(255, 204, 0)">yellow</span></p>',
)).toBe(
'<p><span style="color: #00FF00">green</span> <span style="color: #FFCC00">yellow</span></p>',
);
});
it("removes executable markup, unsafe links, and unsupported styles", () => {
expect(sanitizeRichTextHtml(
'<script>alert(1)</script><p onclick="bad()">Safe <span style="background:red;color:red">text</span><a href="javascript:bad()">link</a></p>',
)).toBe("<p>Safe <span>text</span><a>link</a></p>");
expect(sanitizeRichTextUrl("data:text/html,bad")).toBe("");
});
});
describe("legacy Extra rich text conversion", () => {
it("escapes plain text, preserves newlines, and converts phrase colors", () => {
expect(normalizeExtraRichText("<unsafe>\nMASSIVE damage", [
{ text: "MASSIVE", color: "#ff0000" },
])).toBe(
'<p>&lt;unsafe&gt;<br><span style="color: #FF0000">MASSIVE</span> damage</p>',
);
});
it("leaves sanitized rich text in rich-text form", () => {
expect(normalizeExtraRichText('<p><em>Ready</em></p>', [
{ text: "Ready", color: "#ff0000" },
])).toBe("<p><em>Ready</em></p>");
});
});