ee044d03e0
- Add /health endpoint with anonymous access for monitoring - Add FileUploadResult<T> model and PostMultipartForFileResultAsync for proper upload response handling - Add ApiResult.Success() factory method for interface types - Refactor Login.razor for cleaner code - Add comprehensive Playwright E2E test suite with fixtures and helpers
89 lines
3.0 KiB
TypeScript
89 lines
3.0 KiB
TypeScript
import { Page } from '@playwright/test';
|
|
|
|
// Test credentials - FakeAuthService accepts any credentials in development mode
|
|
const DEFAULT_USERNAME = 'testuser';
|
|
const DEFAULT_PASSWORD = 'testpass';
|
|
|
|
/**
|
|
* Login to the application using FakeAuthService credentials
|
|
* @param page - Playwright page object
|
|
* @param username - Optional username (defaults to testuser)
|
|
* @param password - Optional password (defaults to testpass)
|
|
*/
|
|
export async function login(page: Page, username?: string, password?: string): Promise<void> {
|
|
const user = username ?? DEFAULT_USERNAME;
|
|
const pass = password ?? DEFAULT_PASSWORD;
|
|
|
|
// Check if we're on the login page
|
|
const loginForm = page.locator('text=Authentication Required');
|
|
if (await loginForm.isVisible({ timeout: 5000 }).catch(() => false)) {
|
|
// Wait for form inputs to be ready
|
|
await page.locator('input[name="Username"]').waitFor({ state: 'visible', timeout: 10000 });
|
|
|
|
// Fill credentials
|
|
await page.locator('input[name="Username"]').fill(user);
|
|
await page.locator('input[name="Password"]').fill(pass);
|
|
|
|
// Click the submit button
|
|
await page.locator('button[type="submit"]:has-text("LOGIN")').click();
|
|
|
|
// Wait for login to process
|
|
await page.waitForTimeout(3000);
|
|
|
|
// After login, force navigation to refresh state
|
|
await page.goto('/search');
|
|
await page.waitForLoadState('networkidle', { timeout: 60000 });
|
|
|
|
// Verify login succeeded
|
|
if (await loginForm.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
throw new Error('Login failed - still on login page after attempt');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Logout from the application
|
|
* @param page - Playwright page object
|
|
*/
|
|
export async function logout(page: Page): Promise<void> {
|
|
// Click the logout button in the header
|
|
const logoutButton = page.locator('button:has-text("Logout")');
|
|
if (await logoutButton.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
await logoutButton.click();
|
|
await page.waitForLoadState('networkidle', { timeout: 30000 });
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if the user is currently logged in
|
|
* @param page - Playwright page object
|
|
* @returns true if logged in, false otherwise
|
|
*/
|
|
export async function isLoggedIn(page: Page): Promise<boolean> {
|
|
const loginForm = page.locator('text=Authentication Required');
|
|
const logoutButton = page.locator('button:has-text("Logout")');
|
|
|
|
// If logout button is visible, user is logged in
|
|
if (await logoutButton.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
return true;
|
|
}
|
|
|
|
// If login form is visible, user is not logged in
|
|
if (await loginForm.isVisible({ timeout: 2000 }).catch(() => false)) {
|
|
return false;
|
|
}
|
|
|
|
// Default to not logged in
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Ensure user is logged in, performing login if necessary
|
|
* @param page - Playwright page object
|
|
*/
|
|
export async function ensureLoggedIn(page: Page): Promise<void> {
|
|
if (!(await isLoggedIn(page))) {
|
|
await login(page);
|
|
}
|
|
}
|