The form is built once to the settled field set, and a valid send is saved before anyone is emailed. Co-authored-by: Cursor <cursoragent@cursor.com>
102 lines
3.8 KiB
TypeScript
102 lines
3.8 KiB
TypeScript
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");
|
|
});
|
|
});
|