Production-ready test infrastructure with Page Object Model pattern, reusable fixtures for auth/DB/test-data, and example tests covering login flow, dashboard, accounts CRUD API, and visual regression. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
51 lines
1.7 KiB
TypeScript
51 lines
1.7 KiB
TypeScript
/**
|
|
* Auth setup project — runs ONCE before all browser-based tests.
|
|
*
|
|
* Logs in via the UI, then saves the authenticated browser state
|
|
* (cookies + localStorage) to tests/.auth/user.json so that every
|
|
* subsequent test starts already logged in.
|
|
*
|
|
* This matches Playwright's recommended "global setup via project
|
|
* dependencies" pattern.
|
|
*/
|
|
|
|
import { test as setup, expect } from '@playwright/test';
|
|
import { TEST_USERS } from './fixtures/test-data';
|
|
import path from 'path';
|
|
|
|
const authFile = path.join(__dirname, '.auth', 'user.json');
|
|
|
|
setup('authenticate as test treasurer', async ({ page }) => {
|
|
// Navigate to login page
|
|
await page.goto('/login');
|
|
|
|
// Fill login form — uses Mantine component labels
|
|
await page.getByLabel('Email').fill(TEST_USERS.treasurer.email);
|
|
await page.getByLabel('Password').fill(TEST_USERS.treasurer.password);
|
|
|
|
// Submit
|
|
await page.getByRole('button', { name: 'Sign in' }).click();
|
|
|
|
// Wait for redirect away from login page.
|
|
// After login, the app redirects to /select-org (multi-org) or /dashboard.
|
|
await page.waitForURL(/\/(select-org|dashboard|admin|onboarding)/, {
|
|
timeout: 15_000,
|
|
});
|
|
|
|
// If we land on org selection, pick the first org
|
|
if (page.url().includes('/select-org')) {
|
|
// Click the first organization card/button
|
|
const orgButton = page.getByRole('button').first();
|
|
if (await orgButton.isVisible({ timeout: 3_000 }).catch(() => false)) {
|
|
await orgButton.click();
|
|
await page.waitForURL(/\/dashboard/, { timeout: 10_000 });
|
|
}
|
|
}
|
|
|
|
// Verify we're authenticated — page should not be on /login
|
|
expect(page.url()).not.toContain('/login');
|
|
|
|
// Save authenticated state
|
|
await page.context().storageState({ path: authFile });
|
|
});
|