- Added GET /tracks/:id/comments route (public) - Added POST /tracks/:id/comments route (protected) - Added DELETE /comments/:id route (protected) - Initialized CommentService and CommentHandler in setupTrackRoutes - Standardized API responses in comment handlers - Handlers use RespondSuccess and RespondWithAppError Phase: PHASE-2 Priority: P1 Progress: 22/267 (8.2%)
112 lines
3.6 KiB
TypeScript
112 lines
3.6 KiB
TypeScript
import { chromium, FullConfig } from '@playwright/test';
|
|
import { TEST_CONFIG, TEST_USERS } from './utils/test-helpers';
|
|
|
|
/**
|
|
* Global Setup for Playwright E2E Tests
|
|
*
|
|
* This setup runs ONCE before all tests to:
|
|
* 1. Log in as a test user
|
|
* 2. Save the authenticated session state to storageState.json
|
|
* 3. All subsequent tests will use this saved state (no need to login again)
|
|
*
|
|
* This eliminates:
|
|
* - Rate limiting issues (only 1 login instead of N logins)
|
|
* - Test execution time (no login overhead per test)
|
|
* - Flaky authentication failures
|
|
*/
|
|
|
|
async function globalSetup(config: FullConfig) {
|
|
console.log('🔧 [GLOBAL SETUP] Starting global setup...');
|
|
|
|
// Use the first project's browser (usually chromium)
|
|
const project = config.projects[0];
|
|
const browser = await chromium.launch({
|
|
headless: true,
|
|
});
|
|
|
|
const context = await browser.newContext();
|
|
const page = await context.newPage();
|
|
|
|
try {
|
|
// Navigate to login page
|
|
console.log('🔧 [GLOBAL SETUP] Navigating to login page...');
|
|
await page.goto(`${TEST_CONFIG.FRONTEND_URL}/login`, {
|
|
waitUntil: 'networkidle',
|
|
});
|
|
|
|
// Wait for login form to be visible
|
|
await page.waitForSelector('input[type="email"], input[name="email"]', {
|
|
timeout: 10000,
|
|
});
|
|
|
|
// Fill login form
|
|
console.log('🔧 [GLOBAL SETUP] Filling login form...');
|
|
const emailInput = page.locator('input[type="email"], input[name="email"]').first();
|
|
const passwordInput = page.locator('input[type="password"], input[name="password"]').first();
|
|
|
|
await emailInput.fill(TEST_USERS.default.email);
|
|
await passwordInput.fill(TEST_USERS.default.password);
|
|
|
|
// Submit form
|
|
console.log('🔧 [GLOBAL SETUP] Submitting login form...');
|
|
const form = page.locator('form').first();
|
|
await form.evaluate((form) => (form as HTMLFormElement).requestSubmit());
|
|
|
|
// Wait for navigation after login (dashboard or home)
|
|
console.log('🔧 [GLOBAL SETUP] Waiting for login to complete...');
|
|
await page.waitForURL(
|
|
(url) => url.pathname === '/dashboard' || url.pathname === '/',
|
|
{ timeout: 20000 }
|
|
);
|
|
|
|
// Wait for auth state to be persisted
|
|
await page.waitForTimeout(2000);
|
|
|
|
// Verify authentication by checking for auth-storage in localStorage
|
|
const authStorage = await page.evaluate(() => {
|
|
return localStorage.getItem('auth-storage');
|
|
});
|
|
|
|
if (!authStorage) {
|
|
throw new Error('Authentication failed: auth-storage not found in localStorage');
|
|
}
|
|
|
|
const authData = JSON.parse(authStorage);
|
|
if (!authData.state?.isAuthenticated) {
|
|
throw new Error('Authentication failed: isAuthenticated is false');
|
|
}
|
|
|
|
console.log('✅ [GLOBAL SETUP] Login successful!');
|
|
|
|
// Verify token is stored
|
|
const accessToken = await page.evaluate(() => {
|
|
return localStorage.getItem('veza_access_token');
|
|
});
|
|
|
|
if (!accessToken) {
|
|
console.warn('⚠️ [GLOBAL SETUP] Access token not found in localStorage (may be in memory)');
|
|
} else {
|
|
console.log('✅ [GLOBAL SETUP] Access token stored in localStorage');
|
|
}
|
|
|
|
// Save the authenticated state to storageState.json
|
|
const storageStatePath = config.projects[0]?.use?.storageState as string || 'e2e/.auth/user.json';
|
|
console.log(`💾 [GLOBAL SETUP] Saving authenticated state to: ${storageStatePath}`);
|
|
await context.storageState({ path: storageStatePath });
|
|
|
|
console.log('✅ [GLOBAL SETUP] Global setup completed successfully!');
|
|
} catch (error) {
|
|
console.error('❌ [GLOBAL SETUP] Global setup failed:', error);
|
|
throw error;
|
|
} finally {
|
|
await browser.close();
|
|
}
|
|
}
|
|
|
|
export default globalSetup;
|
|
|
|
|
|
|
|
|
|
|
|
|