Files
ihasmail-inbuxa/web/src/lib/__tests__/sieveApply.test.ts
T
jcoffey-dev 645b8b510f ihasmail 2.0: rebuild as Stalwart-first JMAP webmail
Replace the FastAPI/HTMX prototype with a Node/Hono session proxy and a
React 19/Vite SPA. Mail (conversation view, search operators, labels,
sanitised HTML, privacy image proxy, invites, undo send, templates),
calendar (month/week/day/agenda, invites, free/busy, categories,
context menus), contacts (JSContact, groups, vCard), files, Sieve filter
builder (incl. filter-from-message with retroactive apply), vacation,
identities with default + Reply-To, PWA/mobile layout, push via SSE,
in-memory mock Stalwart for dev, Docker + CI.
2026-08-23 01:07:13 -07:00

32 lines
2.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { evaluateRule, evaluateTest } from "../sieveApply";
import type { Email } from "@/jmap/types";
import type { SieveRule } from "../sieve";
const email = {
id: "e1", blobId: "b", threadId: "t", mailboxIds: { inbox: true }, keywords: {}, size: 5000, receivedAt: "2026-01-01T00:00:00Z",
from: [{ name: "Ada Lovelace", email: "[email protected]" }], to: [{ name: null, email: "[email protected]" }], subject: "Invoice #42 is ready", preview: "Please find attached",
"header:List-Id:asText": "<dev.lists.example.org>",
} as unknown as Email;
describe("sieve client-side evaluation", () => {
it("evaluates header/address/size/body tests", () => {
expect(evaluateTest(email, { type: "header", header: "from", op: "contains", value: "ada@" })).toBe(true);
expect(evaluateTest(email, { type: "header", header: "subject", op: "matches", value: "invoice*ready" })).toBe(true);
expect(evaluateTest(email, { type: "header", header: "subject", op: "regex", value: "^Invoice #\\d+" })).toBe(true);
expect(evaluateTest(email, { type: "header", header: "list-id", op: "exists", value: "" })).toBe(true);
expect(evaluateTest(email, { type: "header", header: "x-none", op: "notexists", value: "" })).toBe(true);
expect(evaluateTest(email, { type: "address", header: "from", part: "domain", op: "is", value: "example.org" })).toBe(true);
expect(evaluateTest(email, { type: "address", header: "from", part: "localpart", op: "is", value: "ada" })).toBe(true);
expect(evaluateTest(email, { type: "size", op: "over", value: 1000 })).toBe(true);
expect(evaluateTest(email, { type: "size", op: "under", value: 1000 })).toBe(false);
expect(evaluateTest(email, { type: "body", op: "contains", value: "attached" }, "Please find attached the file")).toBe(true);
});
it("combines with allof/anyof", () => {
const base: SieveRule = { id: "r", name: "r", enabled: true, join: "allof", tests: [{ type: "header", header: "from", op: "contains", value: "ada" }, { type: "header", header: "subject", op: "contains", value: "nope" }], actions: [] };
expect(evaluateRule(email, base)).toBe(false);
expect(evaluateRule(email, { ...base, join: "anyof" })).toBe(true);
expect(evaluateRule(email, { ...base, tests: [{ type: "true" }] })).toBe(true);
});
});