import { describe, it, expect } from "bun:test";
import { renderMarkdown } from "../lib/markdown";
describe("renderMarkdown — XSS sanitization", () => {
it("strips raw <script> tags and their payload", () => {
const out = renderMarkdown("<script>alert(1)</script>");
expect(out).not.toContain("<script");
expect(out).not.toContain("alert(1)");
});
it("strips img onerror handlers", () => {
const out = renderMarkdown("<img src=x onerror=alert(1)>");
expect(out).not.toContain("onerror");
expect(out.toLowerCase()).not.toContain("onerror=");
});
it("strips svg onload handlers", () => {
const out = renderMarkdown("<svg onload=alert(1)></svg>");
expect(out.toLowerCase()).not.toContain("onload");
expect(out).not.toContain("<svg");
});
it("strips iframes with javascript: src", () => {
const out = renderMarkdown('<iframe src="javascript:alert(1)"></iframe>');
expect(out).not.toContain("<iframe");
expect(out.toLowerCase()).not.toContain("javascript:");
});
it("neutralizes javascript: links in markdown link syntax", () => {
const out = renderMarkdown("[x](javascript:alert(1))");
expect(/href=["']?\s*javascript:/i.test(out)).toBe(false);
expect(out.toLowerCase()).not.toContain("javascript:alert");
});
it("strips inline event handlers on otherwise-allowed tags", () => {
const out = renderMarkdown('<a href="https://example.com" onclick="alert(1)">x</a>');
expect(out.toLowerCase()).not.toContain("onclick");
});
it("drops <style>, <object>, <embed>, <form> tags", () => {
const out = renderMarkdown(
"<style>body{display:none}</style><object data=x></object><embed src=x><form></form>",
);
expect(out).not.toContain("<style");
expect(out).not.toContain("<object");
expect(out).not.toContain("<embed");
expect(out).not.toContain("<form");
});
it("disallows data: URIs on images", () => {
const out = renderMarkdown("</script>)");
expect(out.toLowerCase()).not.toContain("data:text/html");
});
});
describe("renderMarkdown — normal rendering preserved", () => {
it("renders headings", () => {
const out = renderMarkdown("# Hello");
expect(out).toContain("<h1");
expect(out).toContain("Hello");
});
it("renders bold text", () => {
const out = renderMarkdown("**bold**");
expect(out).toContain("<strong>bold</strong>");
});
it("renders safe http links", () => {
const out = renderMarkdown("[site](https://example.com)");
expect(out).toContain('href="https://example.com"');
});
it("renders images from http(s) sources", () => {
const out = renderMarkdown("");
expect(out).toContain('src="https://example.com/a.png"');
expect(out).toContain('alt="alt"');
});
it("preserves syntax-highlighted fenced code blocks", () => {
const out = renderMarkdown("```js\nconst x = 1;\n```");
expect(out).toContain("<pre>");
expect(out).toContain("<code");
expect(out).toContain('class="language-js"');
expect(out).toContain("hljs-");
expect(out).toContain('class="hljs-');
});
it("renders inline code", () => {
const out = renderMarkdown("use `bun test` here");
expect(out).toContain("<code>bun test</code>");
});
});
|