veza/apps/web/e2e/global-setup.ts
senke 55a8b5340d [TEST] Playwright E2E - Global setup avec API login direct
- Création utilisateur de test permanent (e2e@test.com)
- Modification global-setup pour utiliser API login directement
- Contournement du problème de routage frontend (404 sur /login)
- Configuration test-helpers mise à jour
- Backend doit être accessible pour que les tests passent
2026-01-04 01:44:15 +01:00

133 lines
4.5 KiB
TypeScript

import { chromium, FullConfig } from '@playwright/test';
import { TEST_CONFIG, TEST_USERS } from './utils/test-helpers';
// Load test user credentials from environment or use defaults
const getTestUser = () => {
const email = process.env.TEST_EMAIL || 'e2e@test.com';
const password = process.env.TEST_PASSWORD || 'Xk9$mP2#vL7@nQ4!wR8';
return { email, password };
};
/**
* 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...');
const testUser = getTestUser();
console.log(`🔧 [GLOBAL SETUP] Using test user: ${testUser.email}`);
// 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 frontend root (not /login to avoid routing issues)
console.log('🔧 [GLOBAL SETUP] Navigating to frontend...');
await page.goto(TEST_CONFIG.FRONTEND_URL, {
waitUntil: 'domcontentloaded',
timeout: 30000,
});
// Login via API directly in the browser context
console.log('🔧 [GLOBAL SETUP] Attempting API login via browser...');
console.log(`🔧 [GLOBAL SETUP] API URL: ${TEST_CONFIG.API_URL}`);
const loginResult = await page.evaluate(async ({ apiUrl, email, password }) => {
try {
console.log(`[BROWSER] Attempting login to: ${apiUrl}/auth/login`);
const response = await fetch(`${apiUrl}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email,
password,
}),
});
if (!response.ok) {
const errorText = await response.text();
return { success: false, error: `HTTP ${response.status}: ${errorText}` };
}
const data = await response.json();
const accessToken = data?.token?.access_token || data?.data?.token?.access_token || data?.access_token;
const refreshToken = data?.token?.refresh_token || data?.data?.token?.refresh_token || data?.refresh_token;
if (!accessToken) {
return { success: false, error: 'No access token in response', data };
}
// Store tokens in localStorage
localStorage.setItem('veza_access_token', accessToken);
if (refreshToken) {
localStorage.setItem('veza_refresh_token', refreshToken);
}
// Also set auth-storage for Zustand
const authStorage = {
state: {
isAuthenticated: true,
accessToken: accessToken,
refreshToken: refreshToken,
},
};
localStorage.setItem('auth-storage', JSON.stringify(authStorage));
return { success: true, accessToken, refreshToken };
} catch (error) {
return { success: false, error: error instanceof Error ? error.message : String(error) };
}
}, { apiUrl: TEST_CONFIG.API_URL, email: testUser.email, password: testUser.password });
if (!loginResult.success) {
throw new Error(`API login failed: ${loginResult.error}`);
}
console.log('✅ [GLOBAL SETUP] API login successful!');
console.log(`✅ [GLOBAL SETUP] Access token: ${loginResult.accessToken?.substring(0, 20)}...`);
// Verify tokens are stored
const storedToken = await page.evaluate(() => localStorage.getItem('veza_access_token'));
if (!storedToken) {
throw new Error('Token not stored in localStorage');
}
// Save the authenticated state
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;