fix(GRO-743): add dedicated client detail route with unconditional data fetch (#316)
Direct navigation to /admin/clients/{id} now:
- Fetches GET /api/clients/{id} on mount (unconditional)
- Fetches GET /api/pets?clientId= on mount
- Shows loading state while fetching
- Shows error state on failure (401/404/5xx)
- Preserves existing link-based navigation from ClientsPage
Added ClientDetailPage.tsx as a standalone route component.
Added 3 E2E tests covering direct nav, loading state, and error state.
Co-authored-by: Test User <test@example.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit was merged in pull request #316.
This commit is contained in:
committed by
GitHub
parent
77971a1ac9
commit
8ecbfbeee4
@@ -63,3 +63,52 @@ test("clicking a client shows their details", async ({ page }) => {
|
||||
// Email appears in both the list row and the detail panel once selected
|
||||
await expect(page.getByText("alice@example.com")).toHaveCount(2);
|
||||
});
|
||||
|
||||
test("direct URL navigation to client detail fetches data and renders client name", async ({ page }) => {
|
||||
// Mock individual client fetch for direct navigation
|
||||
await page.route("/api/clients/client-1", (route) =>
|
||||
route.fulfill({ json: MOCK_CLIENTS[0] })
|
||||
);
|
||||
// Mock pets for this client
|
||||
await page.route("/api/pets**", (route) =>
|
||||
route.fulfill({ json: [] })
|
||||
);
|
||||
|
||||
await page.goto("/admin/clients/client-1");
|
||||
// Client name must be visible without any clicking
|
||||
await expect(page.getByText("Alice Johnson")).toBeVisible();
|
||||
// Should show back to list link
|
||||
await expect(page.getByText("← Back to list")).toBeVisible();
|
||||
});
|
||||
|
||||
test("direct URL navigation shows loading then client", async ({ page }) => {
|
||||
let resolvePets: (value: unknown) => void;
|
||||
const petsPromise = new Promise((resolve) => { resolvePets = resolve; });
|
||||
|
||||
await page.route("/api/clients/client-1", (route) =>
|
||||
route.fulfill({ json: MOCK_CLIENTS[0] })
|
||||
);
|
||||
await page.route("/api/pets**", async (route) => {
|
||||
await petsPromise;
|
||||
await route.fulfill({ json: [] });
|
||||
});
|
||||
|
||||
const navigationPromise = page.goto("/admin/clients/client-1");
|
||||
// Should show loading state briefly
|
||||
await expect(page.getByText("Loading client…")).toBeVisible();
|
||||
// Resolve pets and wait for navigation
|
||||
resolvePets!();
|
||||
await navigationPromise;
|
||||
// After data loads, client name is shown
|
||||
await expect(page.getByText("Alice Johnson")).toBeVisible();
|
||||
});
|
||||
|
||||
test("direct URL navigation shows error state on failure", async ({ page }) => {
|
||||
await page.route("/api/clients/nonexistent", (route) =>
|
||||
route.fulfill({ status: 404, json: { error: "Client not found" } })
|
||||
);
|
||||
|
||||
await page.goto("/admin/clients/nonexistent");
|
||||
await expect(page.getByText(/client not found/i)).toBeVisible();
|
||||
await expect(page.getByText("← Back to clients")).toBeVisible();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user