Rocky_Mountain_Vending/app/api/contact/route.test.ts

154 lines
4.5 KiB
TypeScript

import assert from "node:assert/strict"
import test from "node:test"
import {
processLeadSubmission,
type ContactLeadPayload,
type RequestMachineLeadPayload,
} from "@/lib/server/contact-submission"
test("processLeadSubmission stores and syncs a contact lead", async () => {
const calls: string[] = []
const payload: ContactLeadPayload = {
kind: "contact",
firstName: "John",
lastName: "Doe",
email: "john@example.com",
phone: "(435) 555-1212",
company: "ACME",
intent: "Repairs",
message: "Need vending help for our office.",
serviceTextConsent: true,
marketingTextConsent: false,
consentVersion: "sms-consent-v1-2026-03-26",
consentCapturedAt: "2026-03-25T00:00:00.000Z",
consentSourcePage: "/contact-us",
source: "website",
page: "/contact",
timestamp: "2026-03-25T00:00:00.000Z",
url: "https://rmv.example/contact",
}
const result = await processLeadSubmission(payload, "rmv.example", {
storageConfigured: true,
emailConfigured: true,
ghlConfigured: true,
tenantSlug: "rocky_mountain_vending",
tenantName: "Rocky Mountain Vending",
tenantDomains: ["rockymountainvending.com"],
ingest: async () => {
calls.push("ingest")
return {
inserted: true,
leadId: "lead_123",
idempotencyKey: "abc",
tenantId: "tenant_123",
}
},
updateLeadStatus: async () => {
calls.push("update")
return { ok: true }
},
sendEmail: async () => {
calls.push("email")
return {}
},
createContact: async () => {
calls.push("ghl")
return { contact: { id: "ghl_123" } }
},
logger: console,
})
assert.equal(result.status, 200)
assert.equal(result.body.success, true)
assert.deepEqual(result.body.deliveredVia, ["convex", "email", "ghl"])
assert.equal(calls.filter((call) => call === "email").length, 2)
assert.ok(calls.includes("ingest"))
assert.ok(calls.includes("update"))
assert.ok(calls.includes("ghl"))
})
test("processLeadSubmission validates request-machine submissions", async () => {
const payload: RequestMachineLeadPayload = {
kind: "request-machine",
firstName: "Jane",
lastName: "Smith",
email: "jane@example.com",
phone: "4352339668",
company: "Warehouse Co",
employeeCount: "0",
machineType: "snack",
machineCount: "2",
serviceTextConsent: true,
marketingTextConsent: false,
consentVersion: "sms-consent-v1-2026-03-26",
consentCapturedAt: "2026-03-25T00:00:00.000Z",
consentSourcePage: "/",
}
const result = await processLeadSubmission(payload, "rmv.example", {
storageConfigured: false,
emailConfigured: false,
ghlConfigured: false,
tenantSlug: "rocky_mountain_vending",
tenantName: "Rocky Mountain Vending",
tenantDomains: [],
ingest: async () => {
throw new Error("should not run")
},
updateLeadStatus: async () => {
throw new Error("should not run")
},
sendEmail: async () => {
throw new Error("should not run")
},
createContact: async () => {
throw new Error("should not run")
},
logger: console,
})
assert.equal(result.status, 400)
assert.equal(result.body.success, false)
assert.match(result.body.error || "", /Invalid number of employees/)
})
test("processLeadSubmission returns deduped success when Convex already has the lead", async () => {
const payload: ContactLeadPayload = {
kind: "contact",
firstName: "John",
lastName: "Doe",
email: "john@example.com",
phone: "(435) 555-1212",
message: "Need vending help for our office.",
serviceTextConsent: true,
marketingTextConsent: false,
consentVersion: "sms-consent-v1-2026-03-26",
consentCapturedAt: "2026-03-25T00:00:00.000Z",
consentSourcePage: "/contact-us",
}
const result = await processLeadSubmission(payload, "rmv.example", {
storageConfigured: true,
emailConfigured: false,
ghlConfigured: false,
tenantSlug: "rocky_mountain_vending",
tenantName: "Rocky Mountain Vending",
tenantDomains: [],
ingest: async () => ({
inserted: false,
leadId: "lead_123",
idempotencyKey: "abc",
tenantId: "tenant_123",
}),
updateLeadStatus: async () => ({ ok: true }),
sendEmail: async () => ({}),
createContact: async () => null,
logger: console,
})
assert.equal(result.status, 200)
assert.equal(result.body.success, true)
assert.equal(result.body.deduped, true)
assert.deepEqual(result.body.deliveredVia, ["convex"])
})