import { campaignJsonForAttachmentPreview } from "../src/features/campaigns/utils/templatePreviewDraft"; import { checkContentLibraryCompatibility } from "../src/features/campaigns/utils/contentLibraryCompatibility"; function assert(condition: unknown, message = "assertion failed"): void { if (!condition) throw new Error(message); } function asRecord(value: unknown): Record { return value && typeof value === "object" && !Array.isArray(value) ? value as Record : {}; } const draft = { recipients: { from: { name: "", email: "" }, to: [{ name: "Bob", email: " bob@example.org " }, { name: "", email: "" }] }, entries: { inline: [{ id: "recipient-1", active: true, name: "", email: "", from: [], to: [{ name: "", email: "" }, { name: "Alice", email: " alice@example.org " }], cc: [], bcc: [], merge_to: false }], defaults: { name: "", email: "", to: [{ name: "", email: "" }], attachments: [] } } }; const normalized = campaignJsonForAttachmentPreview(draft); const entries = asRecord(normalized.entries); const inline = entries.inline as Record[]; const entry = inline[0]; const to = entry.to as Record[]; const defaults = asRecord(entries.defaults); const recipients = asRecord(normalized.recipients); const globalTo = recipients.to as Record[]; assert(recipients.from === undefined, "empty global from object is stripped"); assert(globalTo.length === 1 && globalTo[0].email === "bob@example.org", "global recipient arrays are sanitized"); assert(entry.email === undefined, "empty legacy entry email is stripped"); assert(entry.name === undefined, "empty legacy entry name is stripped"); assert(Array.isArray(entry.from) && (entry.from as unknown[]).length === 0, "empty address arrays remain arrays"); assert(to.length === 1 && to[0].email === "alice@example.org", "empty recipient objects are removed and valid addresses are trimmed"); assert(defaults.email === undefined, "empty defaults email is stripped"); assert(Array.isArray(defaults.to) && (defaults.to as unknown[]).length === 0, "empty defaults recipients are removed"); assert((asRecord(draft.entries).inline as Record[])[0].email === "", "original draft is not mutated"); const compatibility = checkContentLibraryCompatibility([ { path: "local::display_name", value_type: "string", label: "Display name", required: true }, { path: "global.case_reference", value_type: "string", label: "Case reference", required: true }, { path: "count", value_type: "number", label: "Count", required: true }, { path: "local.to.2.email", value_type: "string", label: "Second recipient", required: true }, { path: "optional", value_type: "string", required: false } ], new Map([ ["local:display_name", "string"], ["local:to", "string"], ["count", "boolean"] ])); assert(!compatibility.compatible, "missing or wrong-typed fields are incompatible"); assert(compatibility.missing.length === 1 && compatibility.missing[0].path === "global:case_reference", "namespaced missing fields are normalized"); assert(compatibility.incompatible.length === 1 && compatibility.incompatible[0].actual === "boolean", "type mismatches are reported");