import { describe, expect, it } from "vitest"; import { buildWorkshopConfirmationMail, buildWorkshopInboxMail } from "../../lib/workshopSignupMail"; import { EMPTY_WORKSHOP_FORM_VALUES, suggestWorkshopRoute, type WorkshopFormValues, } from "../../lib/workshopSignup"; import { parseWorkshopSignupPayload } from "../../lib/server/validation/workshopSignupSchemas"; const values: WorkshopFormValues = { ...EMPTY_WORKSHOP_FORM_VALUES, challenges: ["big-change"], organizationName: "Northside Credit Union", organizationKind: "credit-union", memberCount: "1000-10000", contactName: "Ada Lovelace", email: "ada@example.com", sourcePage: "/workshops", sourceUrl: "https://communityrule.com/workshops", }; describe("suggestWorkshopRoute", () => { it("sends volunteer-run groups to the kit", () => { expect( suggestWorkshopRoute({ organizationKind: "volunteer", memberCount: "10000-100000" }), ).toEqual({ largeOrganization: false, note: "Volunteer-run group: send the kit and office hours.", }); }); it("flags 1,000 or more members as a large organization and names no price", () => { const route = suggestWorkshopRoute({ organizationKind: "credit-union", memberCount: "1000-10000", }); expect(route.largeOrganization).toBe(true); expect(route.note).toBe("Large organization: call with the facilitator lead."); expect(route.note.toLowerCase()).not.toMatch(/price|fee|\$|£|€/); }); it("sends smaller leagues to a partnership call", () => { expect( suggestWorkshopRoute({ organizationKind: "league", memberCount: "under-1000" }).note, ).toBe("League, association or co-op developer: partnership call."); }); it("sends everyone else the one-page brief", () => { expect( suggestWorkshopRoute({ organizationKind: "housing-coop", memberCount: "not-sure" }).note, ).toBe("Send the one-page brief, then offer a call."); }); }); describe("workshop signup mail", () => { it("keeps a price out of the inbox note and the confirmation", () => { const inbox = buildWorkshopInboxMail({ values, routeNote: "Large organization: call with the facilitator lead.", largeOrganization: true, requestId: "req-1", schedulingUrl: "https://calendar.example/workshop", }); const confirmation = buildWorkshopConfirmationMail({ largeOrganization: true, schedulingUrl: "https://calendar.example/workshop", }); const combined = `${inbox.text}\n${confirmation.text}`.toLowerCase(); expect(combined).not.toMatch(/price|fee|\$|£|€/); expect(confirmation.text).toContain("two working days"); expect(confirmation.text).toContain("Choose a time"); expect(inbox.text).toContain("Northside Credit Union"); expect(inbox.text).toContain("https://communityrule.com/workshops"); }); }); describe("parseWorkshopSignupPayload", () => { it("keeps answers and reports each missing required field", () => { const parsed = parseWorkshopSignupPayload({ unspokenQuestion: "How do we grow?", organizationName: "Northside", email: "not-an-email", }); expect(parsed.values.unspokenQuestion).toBe("How do we grow?"); expect(parsed.values.organizationName).toBe("Northside"); expect(parsed.fieldErrors.challenges).toBe("required"); expect(parsed.fieldErrors.organizationKind).toBe("required"); expect(parsed.fieldErrors.memberCount).toBe("required"); expect(parsed.fieldErrors.contactName).toBe("required"); expect(parsed.fieldErrors.email).toBe("invalid"); }); it("accepts the full field set", () => { const parsed = parseWorkshopSignupPayload({ ...values, startedAt: Date.now() - 10_000, }); expect(parsed.fieldErrors).toEqual({}); expect(parsed.values.email).toBe("ada@example.com"); }); });