Files
api/src/__tests__/email.test.ts
T
Chris Farhood abac9dfe6c Extract groombook/api from monorepo with CI workflow
- Add source code from apps/api
- Add packages/db and packages/types workspace dependencies
- Add GitHub Actions CI workflow (lint, typecheck, test, docker)
- Generate pnpm-lock.yaml
- Add .gitignore

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-11 01:26:56 +00:00

107 lines
3.3 KiB
TypeScript

import { describe, it, expect } from "vitest";
import {
buildConfirmationEmail,
buildReminderEmail,
} from "../services/email.js";
const START = new Date("2026-03-25T15:00:00Z");
const BASE = {
clientName: "Jane Doe",
petName: "Biscuit",
serviceName: "Full Groom",
groomerName: "Alex",
startTime: START,
};
describe("buildConfirmationEmail", () => {
it("addresses the correct recipient", () => {
const mail = buildConfirmationEmail("jane@example.com", BASE);
expect(mail.to).toBe("jane@example.com");
});
it("includes the pet name in the subject", () => {
const mail = buildConfirmationEmail("jane@example.com", BASE);
expect(mail.subject).toContain("Biscuit");
});
it("includes confirmation wording in subject", () => {
const mail = buildConfirmationEmail("jane@example.com", BASE);
expect(mail.subject).toMatch(/confirmed/i);
});
it("includes client name in the plain text body", () => {
const mail = buildConfirmationEmail("jane@example.com", BASE);
expect(mail.text).toContain("Jane Doe");
});
it("includes service name in plain text body", () => {
const mail = buildConfirmationEmail("jane@example.com", BASE);
expect(mail.text).toContain("Full Groom");
});
it("includes groomer name when provided", () => {
const mail = buildConfirmationEmail("jane@example.com", BASE);
expect(mail.text).toContain("Alex");
});
it("omits groomer when groomerName is null", () => {
const mail = buildConfirmationEmail("jane@example.com", {
...BASE,
groomerName: null,
});
expect(mail.text).not.toContain("with ");
});
it("includes HTML body", () => {
const mail = buildConfirmationEmail("jane@example.com", BASE);
expect(mail.html).toBeTruthy();
expect(mail.html).toContain("Biscuit");
});
});
describe("buildReminderEmail", () => {
it("addresses the correct recipient", () => {
const mail = buildReminderEmail("jane@example.com", BASE, 24);
expect(mail.to).toBe("jane@example.com");
});
it("says 'tomorrow' for 24-hour reminder", () => {
const mail = buildReminderEmail("jane@example.com", BASE, 24);
expect(mail.subject).toContain("tomorrow");
expect(mail.text).toContain("tomorrow");
});
it("says 'in X hours' for sub-24-hour reminders", () => {
const mail = buildReminderEmail("jane@example.com", BASE, 2);
expect(mail.subject).toContain("in 2 hours");
expect(mail.text).toContain("in 2 hours");
});
it("includes pet name in subject", () => {
const mail = buildReminderEmail("jane@example.com", BASE, 24);
expect(mail.subject).toContain("Biscuit");
});
it("includes service name in plain text body", () => {
const mail = buildReminderEmail("jane@example.com", BASE, 24);
expect(mail.text).toContain("Full Groom");
});
it("includes groomer name when provided", () => {
const mail = buildReminderEmail("jane@example.com", BASE, 24);
expect(mail.text).toContain("Alex");
});
it("omits groomer when groomerName is null", () => {
const mail = buildReminderEmail("jane@example.com", { ...BASE, groomerName: null }, 24);
expect(mail.text).not.toContain("with ");
});
it("includes HTML body", () => {
const mail = buildReminderEmail("jane@example.com", BASE, 24);
expect(mail.html).toBeTruthy();
expect(mail.html).toContain("Biscuit");
});
});