import { describe, it, expect } from "vitest"; import { EmailParser } from "./email-parser"; // Inbound mailbox parsing lives on the MailboxId VO (see mailbox-id.test.ts); // EmailParser no longer wraps it. describe("EmailParser.decodeEncodedWords", () => { it("returns plain text unchanged", () => { expect(EmailParser.decodeEncodedWords("Hello World")).toBe("Hello World"); }); it("returns empty string for empty input", () => { expect(EmailParser.decodeEncodedWords("")).toBe(""); }); it("decodes a Base64-encoded word (UTF-8 subject)", () => { // =?UTF-8?B?SGVsbG8=?= → "Hello" expect(EmailParser.decodeEncodedWords("=?UTF-8?B?SGVsbG8=?=")).toBe( "Hello", ); }); it("decodes a quoted-printable encoded word", () => { // =?UTF-8?Q?caf=C3=A9?= → "café" (but decodeQuotedPrintable works byte-by-byte) // Use a simple ASCII QP sequence to stay charset-agnostic in tests // =?US-ASCII?Q?Hello=20World?= → "Hello World" (=20 → space, _ → space) expect(EmailParser.decodeEncodedWords("=?US-ASCII?Q?Hello=20World?=")).toBe( "Hello World", ); }); it("decodes underscores as spaces in QP encoding", () => { expect(EmailParser.decodeEncodedWords("=?US-ASCII?Q?Hello_World?=")).toBe( "Hello World", ); }); it("leaves unrecognised encoded-word syntax unchanged", () => { expect(EmailParser.decodeEncodedWords("=?UTF-8?X?something?=")).toBe( "=?UTF-8?X?something?=", ); }); }); describe("EmailParser.parseForwardEmailPayload", () => { it("throws on null payload", () => { expect(() => EmailParser.parseForwardEmailPayload(null)).toThrow( "Missing or invalid webhook payload", ); }); it("throws on undefined payload", () => { expect(() => EmailParser.parseForwardEmailPayload(undefined)).toThrow(); }); it("parses subject, from, and HTML content", () => { const payload = { subject: "Test Subject", from: { text: "sender@example.com" }, html: "
Hello
", date: "2024-01-15T10:00:00.000Z", }; const result = EmailParser.parseForwardEmailPayload(payload); expect(result.subject).toBe("Test Subject"); expect(result.from).toBe("sender@example.com"); expect(result.content).toBe("Hello
"); expect(result.receivedAt).toBe( new Date("2024-01-15T10:00:00.000Z").getTime(), ); }); it("prefers HTML content over plain text", () => { const payload = { from: { text: "a@b.com" }, html: "HTML", text: "Plain", }; expect(EmailParser.parseForwardEmailPayload(payload).content).toBe( "HTML", ); }); it("falls back to plain text when HTML is absent", () => { const payload = { from: { text: "a@b.com" }, text: "Plain text", }; expect(EmailParser.parseForwardEmailPayload(payload).content).toBe( "Plain text", ); }); it("uses structured from.value when from.text is absent", () => { const payload = { from: { value: [{ name: "Alice", address: "alice@example.com" }], }, html: "", }; const result = EmailParser.parseForwardEmailPayload(payload); expect(result.from).toBe("Alice