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/portal-data.spec.ts
T
Test User 510273a6e3 fix(E2E): add missing API mocks for invoices stats and portal billing
navigation.spec.ts:
- Add mock for /api/invoices/stats/summary returning the shape
  { revenueThisMonth, outstanding, refundsThisMonth, methodBreakdown }
  that InvoicesPage useEffect fetches on mount

portal-data.spec.ts billing test:
- Replace incorrect /api/billing** mock with correct portal endpoint
  mocks: /api/portal/config, /api/portal/invoices, /api/portal/payment-methods
  These are the actual endpoints BillingPayments component calls

Both fixes address the E2E failures reported by Lint Roller on PR #348.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-21 20:25:12 +00:00

119 lines
3.7 KiB
TypeScript

import { test, expect } from "./fixtures.js";
/**
* E2E tests for portal data integrity.
* Verifies that portal sections render correctly without JS errors
* and without showing "Please sign in" messages.
*/
const MOCK_PET = {
id: "pet-1",
name: "Buddy",
species: "dog",
breed: "Golden Retriever",
clientId: "client-1",
};
const MOCK_SESSION = {
id: "session-1",
staffId: "staff-1",
clientId: "client-1",
reason: "E2E test",
status: "active",
startedAt: new Date().toISOString(),
endedAt: null,
expiresAt: new Date(Date.now() + 30 * 60 * 1000).toISOString(),
createdAt: new Date().toISOString(),
};
test.describe("Portal Data Integrity", () => {
test.beforeEach(async ({ page }) => {
// Login as Carol Client first
await page.goto("/login");
await page.getByText("Carol Client").click();
await expect(page).toHaveURL("/");
// Mock portal/me for client data
await page.route("**/api/portal/me", (route) =>
route.fulfill({ json: { id: "client-1", name: "Carol Client", email: "carol@example.com" } })
);
// Mock portal session endpoint
await page.route("**/api/portal/dev-session", (route) =>
route.fulfill({ json: MOCK_SESSION })
);
});
test("appointments section renders without Please sign in", async ({ page }) => {
// Navigate to appointments section
await page.getByRole("button", { name: /Appointments/i }).click();
// Should not show "Please sign in" message
await expect(page.locator("text=/Please sign in/i")).not.toBeVisible({ timeout: 5_000 });
// Content area should be present
await expect(page.locator("main")).toBeVisible();
});
test("pets section renders with content or empty state", async ({ page }) => {
// Mock pets endpoint
await page.route("**/api/pets**", (route) =>
route.fulfill({ json: [MOCK_PET] })
);
// Navigate to pets section
await page.getByRole("button", { name: /My Pets/i }).click();
// Should not show "Please sign in" message
await expect(page.locator("text=/Please sign in/i")).not.toBeVisible({ timeout: 5_000 });
// Content should render - either pet card or empty state
await expect(page.locator("main")).toBeVisible();
});
test("billing section renders without JS errors", async ({ page }) => {
// Mock portal billing endpoints
await page.route("**/api/portal/config**", (route) =>
route.fulfill({ json: { stripePublishableKey: "" } })
);
await page.route("**/api/portal/invoices**", (route) =>
route.fulfill({ json: [] })
);
await page.route("**/api/portal/payment-methods**", (route) =>
route.fulfill({ json: [] })
);
const consoleErrors: string[] = [];
page.on("console", (msg) => {
if (msg.type() === "error") {
consoleErrors.push(msg.text());
}
});
// Navigate to billing section
await page.getByRole("button", { name: /Billing/i }).click();
// Wait for content to load
await page.waitForTimeout(1_000);
// Should not show "Please sign in" message
await expect(page.locator("text=/Please sign in/i")).not.toBeVisible({ timeout: 5_000 });
// No JS errors should have occurred
const jsErrors = consoleErrors.filter(e => !e.includes("favicon") && !e.includes("404"));
expect(jsErrors).toHaveLength(0);
});
test("dashboard renders correctly after login", async ({ page }) => {
// Should already be on dashboard (/) after login
// Should not show "Please sign in"
await expect(page.locator("text=/Please sign in/i")).not.toBeVisible({ timeout: 5_000 });
// Should show the greeting with client name
await expect(page.locator("text=/Hi,\\s*Carol/")).toBeVisible();
// Navigation should be visible
await expect(page.locator("nav")).toBeVisible();
});
});