Add 36 new E2E tests across 5 test files
All checks were successful
Deploy / deploy (push) Successful in 1m41s
All checks were successful
Deploy / deploy (push) Successful in 1m41s
New E2E test files: - e2e/health.spec.ts: 3 tests for health/observability endpoints - e2e/history.spec.ts: 7 tests for history page - e2e/plan.spec.ts: 7 tests for exercise plan page - e2e/decision-engine.spec.ts: 8 tests for decision display and overrides - e2e/cycle.spec.ts: 11 tests for cycle tracking, settings, and period logging Total E2E tests: 100 (up from 64) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
165
e2e/plan.spec.ts
Normal file
165
e2e/plan.spec.ts
Normal file
@@ -0,0 +1,165 @@
|
||||
// ABOUTME: E2E tests for the exercise plan reference page.
|
||||
// ABOUTME: Tests phase display, training guidelines, and current status.
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test.describe("plan page", () => {
|
||||
test.describe("unauthenticated", () => {
|
||||
test("redirects to login when not authenticated", async ({ page }) => {
|
||||
await page.goto("/plan");
|
||||
|
||||
// Should redirect to login
|
||||
await expect(page).toHaveURL(/\/login/);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("authenticated", () => {
|
||||
// These tests require TEST_USER_EMAIL and TEST_USER_PASSWORD env vars
|
||||
test.beforeEach(async ({ page }) => {
|
||||
const email = process.env.TEST_USER_EMAIL;
|
||||
const password = process.env.TEST_USER_PASSWORD;
|
||||
|
||||
if (!email || !password) {
|
||||
test.skip();
|
||||
return;
|
||||
}
|
||||
|
||||
// Login via the login page
|
||||
await page.goto("/login");
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
const emailInput = page.getByLabel(/email/i);
|
||||
const hasEmailForm = await emailInput.isVisible().catch(() => false);
|
||||
|
||||
if (!hasEmailForm) {
|
||||
test.skip();
|
||||
return;
|
||||
}
|
||||
|
||||
await emailInput.fill(email);
|
||||
await page.getByLabel(/password/i).fill(password);
|
||||
await page.getByRole("button", { name: /sign in/i }).click();
|
||||
|
||||
// Wait for redirect to dashboard then navigate to plan
|
||||
await page.waitForURL("/", { timeout: 10000 });
|
||||
await page.goto("/plan");
|
||||
});
|
||||
|
||||
test("displays exercise plan page with title", async ({ page }) => {
|
||||
// Check for plan page title
|
||||
const heading = page.getByRole("heading", { name: "Exercise Plan" });
|
||||
await expect(heading).toBeVisible();
|
||||
});
|
||||
|
||||
test("shows current cycle status section", async ({ page }) => {
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Look for Current Status section
|
||||
const statusSection = page.getByRole("heading", {
|
||||
name: "Current Status",
|
||||
});
|
||||
const hasStatus = await statusSection.isVisible().catch(() => false);
|
||||
|
||||
if (hasStatus) {
|
||||
await expect(statusSection).toBeVisible();
|
||||
|
||||
// Should show day number
|
||||
await expect(page.getByText(/day \d+/i)).toBeVisible();
|
||||
|
||||
// Should show training type
|
||||
await expect(page.getByText(/training type:/i)).toBeVisible();
|
||||
|
||||
// Should show weekly limit
|
||||
await expect(page.getByText(/weekly limit:/i)).toBeVisible();
|
||||
} else {
|
||||
// If no status, should see loading or error state
|
||||
const loading = page.getByText(/loading/i);
|
||||
const error = page.getByRole("alert");
|
||||
const hasLoading = await loading.isVisible().catch(() => false);
|
||||
const hasError = await error.isVisible().catch(() => false);
|
||||
|
||||
expect(hasLoading || hasError).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
test("shows all 5 phase cards", async ({ page }) => {
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Check for Phase Overview section
|
||||
const phaseOverview = page.getByRole("heading", {
|
||||
name: "Phase Overview",
|
||||
});
|
||||
const hasPhaseOverview = await phaseOverview
|
||||
.isVisible()
|
||||
.catch(() => false);
|
||||
|
||||
if (hasPhaseOverview) {
|
||||
// Should show all 5 phase cards using data-testid
|
||||
await expect(page.getByTestId("phase-MENSTRUAL")).toBeVisible();
|
||||
await expect(page.getByTestId("phase-FOLLICULAR")).toBeVisible();
|
||||
await expect(page.getByTestId("phase-OVULATION")).toBeVisible();
|
||||
await expect(page.getByTestId("phase-EARLY_LUTEAL")).toBeVisible();
|
||||
await expect(page.getByTestId("phase-LATE_LUTEAL")).toBeVisible();
|
||||
}
|
||||
});
|
||||
|
||||
test("shows strength training reference table", async ({ page }) => {
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Check for Strength Training section
|
||||
const strengthSection = page.getByRole("heading", {
|
||||
name: /strength training/i,
|
||||
});
|
||||
const hasStrength = await strengthSection.isVisible().catch(() => false);
|
||||
|
||||
if (hasStrength) {
|
||||
// Should have exercise table
|
||||
const table = page.locator("table");
|
||||
await expect(table).toBeVisible();
|
||||
|
||||
// Check for some exercises
|
||||
await expect(page.getByText("Squats")).toBeVisible();
|
||||
await expect(page.getByText("Push-ups")).toBeVisible();
|
||||
await expect(page.getByText("Plank")).toBeVisible();
|
||||
}
|
||||
});
|
||||
|
||||
test("shows rebounding techniques", async ({ page }) => {
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Check for Rebounding Techniques section
|
||||
const reboundingSection = page.getByRole("heading", {
|
||||
name: /rebounding techniques/i,
|
||||
});
|
||||
const hasRebounding = await reboundingSection
|
||||
.isVisible()
|
||||
.catch(() => false);
|
||||
|
||||
if (hasRebounding) {
|
||||
// Should show techniques section - use first() for specific match
|
||||
await expect(
|
||||
page.getByText("Health bounce, lymphatic drainage"),
|
||||
).toBeVisible();
|
||||
}
|
||||
});
|
||||
|
||||
test("shows weekly guidelines", async ({ page }) => {
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// Check for Weekly Guidelines section
|
||||
const weeklySection = page.getByRole("heading", {
|
||||
name: "Weekly Guidelines",
|
||||
});
|
||||
const hasWeekly = await weeklySection.isVisible().catch(() => false);
|
||||
|
||||
if (hasWeekly) {
|
||||
// Should show guidelines for each phase - use exact matches
|
||||
await expect(
|
||||
page.getByRole("heading", { name: "Menstrual Phase (Days 1-3)" }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("heading", { name: "Follicular Phase (Days 4-14)" }),
|
||||
).toBeVisible();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user