This repository has been archived on 2026-05-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
app/apps/e2e/tests/clients.spec.ts
T
Groom Book CTO 4902ed3ced feat: add client disable/deletion with soft-delete (#67)
Add soft-delete support for clients: disable is the default action
(hiding from client list and booking flow), with permanent deletion
requiring explicit type-to-confirm. Disabled clients remain in
reporting and can be re-enabled by staff.

- Add client_status enum (active/disabled) and disabled_at column
- API defaults GET /api/clients to active-only, ?includeDisabled=true shows all
- PATCH /api/clients/:id accepts status field for disable/enable
- DELETE requires ?confirm=true query param
- Booking flow skips disabled clients
- Frontend: show disabled toggle, disable/enable buttons, delete confirmation modal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 17:15:17 +00:00

66 lines
1.8 KiB
TypeScript

import { test, expect } from "./fixtures.js";
/**
* Client management E2E tests.
*
* API calls are mocked so tests run without a live backend.
*/
const MOCK_CLIENTS = [
{
id: "client-1",
name: "Alice Johnson",
email: "alice@example.com",
phone: "555-0101",
address: null,
notes: null,
emailOptOut: false,
status: "active",
disabledAt: null,
createdAt: "2026-01-01T00:00:00.000Z",
updatedAt: "2026-01-01T00:00:00.000Z",
},
{
id: "client-2",
name: "Bob Williams",
email: "bob@example.com",
phone: null,
address: null,
notes: null,
emailOptOut: false,
status: "active",
disabledAt: null,
createdAt: "2026-01-02T00:00:00.000Z",
updatedAt: "2026-01-02T00:00:00.000Z",
},
];
test.beforeEach(async ({ page }) => {
await page.route("/api/clients**", (route) =>
route.fulfill({ json: MOCK_CLIENTS })
);
// Pets loaded when a client is selected
await page.route("/api/pets**", (route) =>
route.fulfill({ json: [] })
);
});
test("clients page shows client list", async ({ page }) => {
await page.goto("/admin/clients");
await expect(page.getByText("Alice Johnson")).toBeVisible();
await expect(page.getByText("Bob Williams")).toBeVisible();
});
test("clients page shows search input", async ({ page }) => {
await page.goto("/admin/clients");
await expect(page.getByPlaceholder(/search/i)).toBeVisible();
});
test("clicking a client shows their details", async ({ page }) => {
await page.goto("/admin/clients");
await expect(page.getByText("Alice Johnson")).toBeVisible();
await page.getByText("Alice Johnson").click();
// Email appears in both the list row and the detail panel once selected
await expect(page.getByText("alice@example.com")).toHaveCount(2);
});