test: add E2E tests for threads, auth, and error handling
Also fix CandidateListItem to not use Reorder.Item when isActive=false, which caused a framer-motion crash on resolved thread detail pages. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
59
e2e/error-handling.spec.ts
Normal file
59
e2e/error-handling.spec.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test.describe("Error handling — non-existent routes", () => {
|
||||
test("non-existent thread does not white-screen", async ({ page }) => {
|
||||
await page.goto("/threads/99999");
|
||||
|
||||
// React Query retries failed requests (default 3 times with backoff) before
|
||||
// setting isError=true. Wait for the page to leave loading state and show content.
|
||||
// The thread detail page renders "Thread not found" + "Back to planning" link on error.
|
||||
await expect(page.getByText("Back to planning")).toBeVisible({
|
||||
timeout: 30000,
|
||||
});
|
||||
await expect(page.getByText("Thread not found")).toBeVisible({
|
||||
timeout: 5000,
|
||||
});
|
||||
});
|
||||
|
||||
test("non-existent setup does not white-screen", async ({ page }) => {
|
||||
await page.goto("/setups/99999");
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Setup detail shows "Setup not found." when data is null (no retry — isLoading=false, data=undefined)
|
||||
// The setup query resolves with undefined rather than throwing for missing items.
|
||||
// Check that the page has content (not a blank screen).
|
||||
const body = page.locator("body");
|
||||
await expect(body).not.toBeEmpty();
|
||||
|
||||
// Navigation header should be visible (app did not crash)
|
||||
await expect(page.getByText("GearBox")).toBeVisible({ timeout: 5000 });
|
||||
|
||||
// Wait for setup data to load; it will show "Setup not found." when done
|
||||
await expect(page.getByText("Setup not found.")).toBeVisible({
|
||||
timeout: 30000,
|
||||
});
|
||||
});
|
||||
|
||||
test("app recovers after bad route — dashboard loads fine", async ({
|
||||
page,
|
||||
}) => {
|
||||
// Navigate to a non-existent thread first
|
||||
await page.goto("/threads/99999");
|
||||
|
||||
// The page should render without crashing — wait for the error state
|
||||
// (React Query retries before showing isError state, so use a long timeout)
|
||||
await expect(page.getByText("Back to planning")).toBeVisible({
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
// Now navigate to the dashboard
|
||||
await page.goto("/");
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Dashboard should load normally
|
||||
await expect(page.getByText("GearBox")).toBeVisible({ timeout: 5000 });
|
||||
await expect(page.getByRole("heading", { name: "Collection" })).toBeVisible(
|
||||
{ timeout: 5000 },
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user