Creates test infrastructure to enable previously skipped e2e tests: - Onboarding user (no period data) for setup flow tests - Established user (period 14 days ago) for normal usage tests - Calendar user (with calendarToken) for ICS feed tests - Garmin user (valid tokens) for connected state tests - Garmin expired user (expired tokens) for expiry warning tests Also fixes ICS feed route to strip .ics suffix from Next.js dynamic route param, adds calendarToken to /api/user response, and sets viewRule on users collection for unauthenticated ICS access. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
87 lines
2.7 KiB
TypeScript
87 lines
2.7 KiB
TypeScript
// ABOUTME: Playwright test fixtures for different user states.
|
|
// ABOUTME: Provides pre-authenticated pages for onboarding, established, calendar, and garmin users.
|
|
import { test as base, type Page } from "@playwright/test";
|
|
import { TEST_USERS, type TestUserPreset } from "./pocketbase-harness";
|
|
|
|
/**
|
|
* Logs in a user via the email/password form.
|
|
* Throws if the email form is not visible (OIDC-only mode).
|
|
*/
|
|
async function loginUser(
|
|
page: Page,
|
|
email: string,
|
|
password: string,
|
|
): Promise<void> {
|
|
await page.goto("/login");
|
|
await page.waitForLoadState("networkidle");
|
|
|
|
const emailInput = page.getByLabel(/email/i);
|
|
const hasEmailForm = await emailInput.isVisible().catch(() => false);
|
|
|
|
if (!hasEmailForm) {
|
|
throw new Error(
|
|
"Email/password form not visible - app may be in OIDC-only mode",
|
|
);
|
|
}
|
|
|
|
await emailInput.fill(email);
|
|
await page.getByLabel(/password/i).fill(password);
|
|
await page.getByRole("button", { name: /sign in/i }).click();
|
|
|
|
// Wait for successful redirect to dashboard
|
|
await page.waitForURL("/", { timeout: 15000 });
|
|
}
|
|
|
|
/**
|
|
* Creates a fixture for a specific user preset.
|
|
*/
|
|
function createUserFixture(preset: TestUserPreset) {
|
|
return async (
|
|
{ page }: { page: Page },
|
|
use: (page: Page) => Promise<void>,
|
|
) => {
|
|
const user = TEST_USERS[preset];
|
|
await loginUser(page, user.email, user.password);
|
|
await use(page);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Extended test fixtures providing pre-authenticated pages for each user type.
|
|
*
|
|
* Usage:
|
|
* import { test, expect } from './fixtures';
|
|
*
|
|
* test('onboarding user sees set date button', async ({ onboardingPage }) => {
|
|
* await onboardingPage.goto('/');
|
|
* // User has no period data, will see onboarding UI
|
|
* });
|
|
*
|
|
* test('established user sees dashboard', async ({ establishedPage }) => {
|
|
* await establishedPage.goto('/');
|
|
* // User has period data from 14 days ago
|
|
* });
|
|
*/
|
|
type TestFixtures = {
|
|
/** User with no period data - sees onboarding UI */
|
|
onboardingPage: Page;
|
|
/** User with period data (14 days ago) - sees normal dashboard */
|
|
establishedPage: Page;
|
|
/** User with period data and calendar token - can copy/regenerate URL */
|
|
calendarPage: Page;
|
|
/** User with valid Garmin tokens (90 days until expiry) */
|
|
garminPage: Page;
|
|
/** User with expired Garmin tokens */
|
|
garminExpiredPage: Page;
|
|
};
|
|
|
|
export const test = base.extend<TestFixtures>({
|
|
onboardingPage: createUserFixture("onboarding"),
|
|
establishedPage: createUserFixture("established"),
|
|
calendarPage: createUserFixture("calendar"),
|
|
garminPage: createUserFixture("garmin"),
|
|
garminExpiredPage: createUserFixture("garminExpired"),
|
|
});
|
|
|
|
export { expect } from "@playwright/test";
|