import { describe, it, expect } from "vitest"; import { processEmailContent } from "./html-processor"; import type { AttachmentData } from "../types"; describe("processEmailContent — body extraction", () => { it("extracts content inside tags", () => { const html = "

Hello

"; expect(processEmailContent(html)).toBe("

Hello

"); }); it("handles body tag with attributes", () => { const html = '

Hi

'; expect(processEmailContent(html)).toBe("

Hi

"); }); it("returns fragment unchanged when no body tags present", () => { const fragment = "

Already a fragment

"; expect(processEmailContent(fragment)).toBe("

Already a fragment

"); }); it("is case-insensitive for body tag matching", () => { const html = "

content

"; expect(processEmailContent(html)).toBe("

content

"); }); }); describe("processEmailContent — plain text", () => { it("wraps plain text in
", () => {
    const text = "Hello world\nSecond line";
    const result = processEmailContent(text);
    expect(result).toMatch(/^
 in plain text", () => {
    const text = "Price < 10 & size > 5";
    const result = processEmailContent(text);
    expect(result).toContain("<");
    expect(result).toContain(">");
    expect(result).toContain("&");
    expect(result).not.toContain("<10");
  });

  it("returns empty string for empty input", () => {
    expect(processEmailContent("")).toBe("");
  });
});

describe("processEmailContent — dangerous element removal", () => {
  it("removes ";
    const result = processEmailContent(html);
    expect(result).not.toContain("Hello

"); }); it("removes

ok

"; const result = processEmailContent(html); expect(result).not.toContain("ok

"); }); it("removes and tags", () => { const html = "

ok

"; const result = processEmailContent(html); expect(result).not.toContain(" { it("removes event handler attributes", () => { const html = "link"; const result = processEmailContent(html); expect(result).not.toContain("onclick"); expect(result).toContain('href="https://x.com"'); }); it("removes onerror on images", () => { const html = ""; const result = processEmailContent(html); expect(result).not.toContain("onerror"); }); it("removes javascript: hrefs", () => { const html = "click"; const result = processEmailContent(html); expect(result).not.toContain("javascript:"); }); it("preserves legitimate href and src attributes", () => { const html = "link"; const result = processEmailContent(html); expect(result).toContain("https://example.com"); }); }); describe("processEmailContent — mso style cleanup", () => { it("strips mso-* properties from inline styles", () => { const html = '

text

'; const result = processEmailContent(html); expect(result).not.toContain("mso-margin-top"); expect(result).toContain("color: red"); }); it("removes style attribute entirely when only mso properties remain", () => { const html = '

text

'; const result = processEmailContent(html); expect(result).not.toContain("style="); }); it("preserves style attribute when non-mso properties remain", () => { const html = '

text

'; const result = processEmailContent(html); expect(result).toContain("font-weight"); expect(result).not.toContain("mso-font-size"); }); }); describe("processEmailContent — inline cid: rewriting", () => { const attachment = ( overrides: Partial = {}, ): AttachmentData => ({ id: "att-123", filename: "chicken big.png", contentType: "image/png", size: 100, contentId: "ii_mpi85rqy0", ...overrides, }); it("rewrites cid: src to a relative /files URL when no baseUrl", () => { const html = 'x'; const result = processEmailContent(html, [attachment()]); expect(result).toContain('src="/files/att-123/chicken%20big.png"'); expect(result).not.toContain("cid:"); }); it("rewrites cid: src to an absolute URL when baseUrl is given", () => { const html = ''; const result = processEmailContent( html, [attachment()], "https://feed.example", ); expect(result).toContain( 'src="https://feed.example/files/att-123/chicken%20big.png"', ); }); it("matches a stored Content-ID that has angle brackets", () => { const html = ''; const result = processEmailContent(html, [ attachment({ contentId: "" }), ]); expect(result).toContain('src="/files/att-123/chicken%20big.png"'); }); it("is case-insensitive on the cid: scheme", () => { const html = ''; const result = processEmailContent(html, [attachment()]); expect(result).toContain('src="/files/att-123/chicken%20big.png"'); }); it("leaves unknown cid references unchanged", () => { const html = ''; const result = processEmailContent(html, [attachment()]); expect(result).toContain('src="cid:unknown"'); }); it("leaves cid references unchanged when no attachments are provided", () => { const html = ''; const result = processEmailContent(html); expect(result).toContain('src="cid:ii_mpi85rqy0"'); }); it("ignores attachments without a contentId", () => { const html = ''; const result = processEmailContent(html, [ attachment({ contentId: undefined }), ]); expect(result).toContain('src="cid:ii_mpi85rqy0"'); }); it("does not touch normal http image sources", () => { const html = ''; const result = processEmailContent(html, [attachment()]); expect(result).toContain('src="https://example.com/a.png"'); }); });