abac9dfe6c
- 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>
107 lines
3.3 KiB
TypeScript
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");
|
|
});
|
|
});
|