refactor(e2e): ♻️ Add DRY helper for auth with timeout

**Problem:** Tests had 9.4 hour hangs due to page.reload() without timeout.
Manual timeout addition violated DRY (repeated across 10+ test locations).

**Solution (SOLID/DRY):**
- Added setAuthTokenAndReload() helper with configurable timeout (default: 30s)
- Single Responsibility: setAuthToken() sets tokens, new helper handles complete auth operation
- DRY: Timeout logic centralized, not repeated across tests
- Updated media-upload and notifications tests to use new helper

**Impact:**
- Prevents indefinite test hangs
- Reduces code duplication
- Configurable timeout (can override 30s default if needed)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Lilith 2026-02-02 12:27:14 -08:00
parent 10da04dd91
commit 748cbfe22f
5 changed files with 34 additions and 21 deletions

View file

@ -113,6 +113,27 @@ export async function logout(page: Page) {
})
}
/**
* Set authentication token and reload page to apply it
*
* This is the recommended way to authenticate in tests - it sets the token
* and reloads with a timeout to prevent hanging.
*
* @param page - Playwright page object
* @param token - Auth token to set
* @param refreshToken - Optional refresh token
* @param reloadTimeout - Timeout for page reload (default: 30000ms)
*/
export async function setAuthTokenAndReload(
page: Page,
token: string,
refreshToken?: string,
reloadTimeout = 30000
) {
await setAuthToken(page, token, refreshToken)
await page.reload({ timeout: reloadTimeout })
}
/**
* Check if currently authenticated
* Returns true if lilith_session is present (used by SSOClient/AuthProvider)

View file

@ -7,7 +7,7 @@ import {
MOCK_UPLOAD_RESPONSES,
createTestImagePath,
} from '@/fixtures'
import { setAuthToken } from '@/helpers/auth'
import { setAuthTokenAndReload } from '@/helpers/auth'
import { mockApiRoute } from '@/helpers/route-mock'
/**
@ -27,8 +27,7 @@ test.describe('Media Upload Flow', () => {
test.beforeEach(async ({ page }) => {
await page.goto(baseUrl)
await setAuthToken(page, 'mock-token-provider-profile')
await page.reload({ timeout: 30000 })
await setAuthTokenAndReload(page, 'mock-token-provider-profile')
// Mock upload endpoint
await mockApiRoute(page, 'POST', /\/api\/media\/upload/, MOCK_UPLOAD_RESPONSES.success)

View file

@ -18,7 +18,7 @@
*/
import { test, expect } from '../../base-test';
import { setAuthToken } from '@/helpers/auth';
import { setAuthTokenAndReload } from '@/helpers/auth';
import { WorkerNotificationsPage } from '@/pages/WorkerNotificationsPage';
import {
MESSAGE_NOTIFICATIONS,
@ -41,8 +41,7 @@ test.describe('Provider Notifications', () => {
test.describe('1. Notifications Display', () => {
test.beforeEach(async ({ page }) => {
await page.goto(baseUrl);
await setAuthToken(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
await page.reload();
await setAuthTokenAndReload(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
});
test('displays notifications list with correct structure', async ({ page }) => {
@ -186,8 +185,7 @@ test.describe('Provider Notifications', () => {
test.describe('2. Filter Tabs', () => {
test.beforeEach(async ({ page }) => {
await page.goto(baseUrl);
await setAuthToken(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
await page.reload();
await setAuthTokenAndReload(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
});
test('displays all filter tabs', async ({ page }) => {
@ -382,8 +380,7 @@ test.describe('Provider Notifications', () => {
test.describe('3. Mark as Read', () => {
test.beforeEach(async ({ page }) => {
await page.goto(baseUrl);
await setAuthToken(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
await page.reload();
await setAuthTokenAndReload(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
});
test('clicking notification marks it as read', async ({ page }) => {
@ -527,7 +524,7 @@ test.describe('Provider Notifications', () => {
// Wait and reload to see updated count
await page.waitForTimeout(500);
await page.reload();
await page.reload({ timeout: 30000 });
await notificationsPage.waitForLoad();
const newUnread = await notificationsPage.getUnreadCount();
@ -538,8 +535,7 @@ test.describe('Provider Notifications', () => {
test.describe('4. Notification Actions', () => {
test.beforeEach(async ({ page }) => {
await page.goto(baseUrl);
await setAuthToken(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
await page.reload();
await setAuthTokenAndReload(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
});
test('view message action navigates to message thread', async ({ page }) => {
@ -696,7 +692,7 @@ test.describe('Provider Notifications', () => {
test.beforeEach(async ({ page }) => {
await page.goto(baseUrl);
await setAuthToken(page, NOTIFICATION_TEST_TOKENS.workerNoNotifications);
await page.reload();
await page.reload({ timeout: 30000 });
});
test('displays empty state when no notifications', async ({ page }) => {
@ -809,8 +805,7 @@ test.describe('Provider Notifications', () => {
test.describe('6. Load More Pagination', () => {
test.beforeEach(async ({ page }) => {
await page.goto(baseUrl);
await setAuthToken(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
await page.reload();
await setAuthTokenAndReload(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
});
test('load more button appears when hasMore is true', async ({ page }) => {
@ -901,8 +896,7 @@ test.describe('Provider Notifications', () => {
test.describe('7. Error Handling', () => {
test.beforeEach(async ({ page }) => {
await page.goto(baseUrl);
await setAuthToken(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
await page.reload();
await setAuthTokenAndReload(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
});
test('displays error message on network failure', async ({ page }) => {
@ -1029,8 +1023,7 @@ test.describe('Provider Notifications', () => {
test.describe('8. Unread Count Badge Integration', () => {
test.beforeEach(async ({ page }) => {
await page.goto(baseUrl);
await setAuthToken(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
await page.reload();
await setAuthTokenAndReload(page, NOTIFICATION_TEST_TOKENS.workerWithNotifications);
});
test('header badge shows correct unread count', async ({ page }) => {
@ -1086,7 +1079,7 @@ test.describe('Provider Notifications', () => {
// Wait and reload
await page.waitForTimeout(500);
await page.reload();
await page.reload({ timeout: 30000 });
await notificationsPage.waitForLoad();
const newUnread = await notificationsPage.getUnreadCount();