Initial extraction: groombook/api from groombook/app monorepo
Part of GRO-802 monorepo breakdown. Changes: - Extract apps/api/ as the main API service - Inline packages/db/ (database schema, migrations, utilities) - Inline packages/types/ (shared TypeScript types) - Add CI workflow for lint, typecheck, test, build, docker - Port Dockerfile with 4 stages: runner, migrate, seed, reset Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
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");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user