Files
mb-grid-solutions.com/tests/api-contact.test.ts
Marc Mintel 109c8389f3
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 4s
Build & Deploy / 🧪 QA (push) Successful in 2m28s
Build & Deploy / 🏗️ Build (push) Successful in 4m45s
Build & Deploy / 🚀 Deploy (push) Failing after 13s
Build & Deploy / 🩺 Health Check (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 1s
test: add api integration tests for contact form
2026-02-27 13:34:23 +01:00

169 lines
4.6 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from "vitest";
// Mock Payload CMS
const { mockCreate, mockSendEmail } = vi.hoisted(() => ({
mockCreate: vi.fn(),
mockSendEmail: vi.fn(),
}));
vi.mock("payload", () => ({
getPayload: vi.fn().mockResolvedValue({
create: mockCreate,
sendEmail: mockSendEmail,
}),
}));
// Mock Email Template renders
vi.mock("@mintel/mail", () => ({
render: vi.fn().mockResolvedValue("<html>Mocked Email HTML</html>"),
ContactFormNotification: () => "ContactFormNotification",
ConfirmationMessage: () => "ConfirmationMessage",
}));
// Mock Notifications and Analytics
const { mockNotify, mockTrack, mockCaptureException } = vi.hoisted(() => ({
mockNotify: vi.fn(),
mockTrack: vi.fn(),
mockCaptureException: vi.fn(),
}));
vi.mock("@/lib/services/create-services.server", () => ({
getServerAppServices: () => ({
logger: {
child: () => ({
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
}),
},
analytics: {
setServerContext: vi.fn(),
track: mockTrack,
},
notifications: {
notify: mockNotify,
},
errors: {
captureException: mockCaptureException,
},
}),
}));
// Import the route handler we want to test
import { POST } from "../app/api/contact/route";
import { NextResponse } from "next/server";
import type { Mock } from "vitest";
describe("Contact API Integration", () => {
beforeEach(() => {
vi.clearAllMocks();
(NextResponse.json as Mock).mockImplementation((body: any, init?: any) => ({
status: init?.status || 200,
json: async () => body,
}));
});
it("should validate and decline empty or short messages", async () => {
const req = new Request("http://localhost/api/contact", {
method: "POST",
body: JSON.stringify({
name: "Test User",
email: "test@example.com",
message: "too short",
}),
});
const response = await POST(req);
expect(response.status).toBe(400);
const data = await response.json();
expect(data.error).toBe("message_too_short");
// Ensure payload and email were NOT called
expect(mockCreate).not.toHaveBeenCalled();
expect(mockSendEmail).not.toHaveBeenCalled();
});
it("should catch honeypot submissions", async () => {
const req = new Request("http://localhost/api/contact", {
method: "POST",
body: JSON.stringify({
name: "Spam Bot",
email: "spam@example.com",
message: "This is a very long spam message that passes length checks.",
website: "http://spam.com", // Honeypot filled
}),
});
const response = await POST(req);
// Honeypot returns 200 OK so the bot thinks it succeeded
expect(response.status).toBe(200);
// But it actually does NOTHING internally
expect(mockCreate).not.toHaveBeenCalled();
expect(mockSendEmail).not.toHaveBeenCalled();
});
it("should successfully save to Payload and send emails", async () => {
const req = new Request("http://localhost/api/contact", {
method: "POST",
headers: {
"user-agent": "vitest",
"x-forwarded-for": "127.0.0.1",
},
body: JSON.stringify({
name: "Jane Doe",
email: "jane@example.com",
company: "Jane Tech",
message:
"Hello, I am interested in exploring your high-voltage grid solutions.",
}),
});
const response = await POST(req);
expect(response.status).toBe(200);
const data = await response.json();
expect(data.message).toBe("Ok");
// 1. Verify Payload creation
expect(mockCreate).toHaveBeenCalledTimes(1);
expect(mockCreate).toHaveBeenCalledWith({
collection: "form-submissions",
data: {
name: "Jane Doe",
email: "jane@example.com",
company: "Jane Tech",
message:
"Hello, I am interested in exploring your high-voltage grid solutions.",
},
});
// 2. Verify Email Sending
// Note: sendEmail is called twice (Notification + User Confirmation)
expect(mockSendEmail).toHaveBeenCalledTimes(2);
expect(mockSendEmail).toHaveBeenNthCalledWith(
1,
expect.objectContaining({
subject: "Kontaktanfrage von Jane Doe",
replyTo: "jane@example.com",
}),
);
expect(mockSendEmail).toHaveBeenNthCalledWith(
2,
expect.objectContaining({
to: "jane@example.com",
subject: "Ihre Kontaktanfrage bei MB Grid Solutions",
}),
);
// 3. Verify notification and analytics
expect(mockNotify).toHaveBeenCalledTimes(1);
expect(mockTrack).toHaveBeenCalledWith("contact-form-success", {
has_company: true,
});
});
});