/** Direct tests for the shared lockups in the target types module. */ import { assertStringIncludes } from "@std/assert"; import { expect } from "@std/expect"; import { describe, it as test } from "@std/testing/bdd"; import { AUDIENCES, BULK_COMPOSE_COPY, fixedControl, isBulkEmailTarget, rawFieldReaders, } from "#shared/bulk-email-targets/types.ts"; import { FormParams } from "#shared/form-data.ts"; describe("the bulk-email target types module", () => { test("fixedControl round-trips one pre-chosen field value", () => { expect(fixedControl("attendee", "token-1")).toEqual({ fields: [["attendee", "token-1"]], mode: "fixed", }); }); test("rawFieldReaders skips a blank value and parses a claimed one", () => { const { fromForm, fromQuery } = rawFieldReaders( (raw: string) => ({ kind: "attendee", token: raw }), { form: "attendee", query: "attendee_id" }, ); const attendee = { kind: "attendee", token: "token-1" }; expect(fromForm(new FormParams([["attendee", ""]]))).toBe(undefined); expect(fromQuery(new URLSearchParams([["attendee_id", ""]]))).toBe( undefined, ); expect(fromForm(new FormParams([["attendee", "token-1"]]))).toEqual( attendee, ); expect( fromQuery(new URLSearchParams([["attendee_id", "token-1"]])), ).toEqual(attendee); }); test("the bulk compose copy carries a heading and an intro", () => { expect(BULK_COMPOSE_COPY.heading).toBe("Send a bulk email"); assertStringIncludes(BULK_COMPOSE_COPY.intro, "Choose who receives it"); }); test("each audience names itself and who it covers", () => { expect(AUDIENCES).toEqual([ { description: "Everyone booked onto a listing that is currently active.", id: "active", label: "Active listing attendees", }, { description: "Everyone booked onto an active listing that has not happened yet.", id: "upcoming", label: "Upcoming listing attendees", }, { description: "Everyone who has ever registered, across every listing.", id: "all", label: "All attendees", }, ]); }); test("the target guard names each kind a target can have", () => { // A blanked kind literal widens the variant: a target of that kind no // longer parses, so a stored draft would read as invalid. expect(isBulkEmailTarget({ audience: "active", kind: "audience" })).toBe( true, ); expect(isBulkEmailTarget({ kind: "listing", listingId: 1 })).toBe(true); expect( isBulkEmailTarget({ day: "2026-01-01", kind: "listing-day", listingId: 1, }), ).toBe(true); expect(isBulkEmailTarget({ kind: "attendee", token: "token-1" })).toBe( true, ); expect(isBulkEmailTarget({ kind: "" })).toBe(false); }); });