[FIX] E2E: Séparer tests authentifiés/non authentifiés dans mvp-integration

- Créer groupe 'Unauthenticated tests' avec storageState vide
- Créer groupe 'Authenticated tests' pour tests nécessitant auth
- Corriger indentation des tests 1.1 à 1.5
- Test 1.6 utilise maintenant l'état authentifié du global-setup
- Corrige erreurs où LoginPage redirigeait car déjà authentifié
This commit is contained in:
senke 2025-12-26 22:04:38 +01:00
parent bad24d11b1
commit 68839020ba
2 changed files with 142 additions and 122 deletions

View file

@ -6,15 +6,23 @@
"localStorage": [
{
"name": "veza_access_token",
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkM2U1ZjhmOC02MDcxLTRmZDQtYWVhMi05ZmZkMzU0YmVmZDkiLCJlbWFpbCI6ImUyZUB0ZXN0LmNvbSIsInVzZXJuYW1lIjoiZTJldXNlciIsInJvbGUiOiJ1c2VyIiwidG9rZW5fdmVyc2lvbiI6MCwidG9rZW5fdHlwZSI6ImFjY2VzcyIsImlzcyI6InZlemEtYXBpIiwiYXVkIjpbInZlemEtYXBwIl0sImV4cCI6MTc2Njc2OTUzNSwiaWF0IjoxNzY2NzY4NjM1LCJqdGkiOiJkMmJkYTQ2NC05N2ZiLTQ5NjAtYmU0MC1lNjk3NGM5Y2I5N2UifQ.Hj8-sN9JYmIGqFDe2Dv-hKSvb6DOShOb5GlsHFm-Ejs"
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkM2U1ZjhmOC02MDcxLTRmZDQtYWVhMi05ZmZkMzU0YmVmZDkiLCJlbWFpbCI6ImUyZUB0ZXN0LmNvbSIsInVzZXJuYW1lIjoiZTJldXNlciIsInJvbGUiOiJ1c2VyIiwidG9rZW5fdmVyc2lvbiI6MCwidG9rZW5fdHlwZSI6ImFjY2VzcyIsImlzcyI6InZlemEtYXBpIiwiYXVkIjpbInZlemEtYXBwIl0sImV4cCI6MTc2Njc4Mzg0OSwiaWF0IjoxNzY2NzgyOTQ5LCJqdGkiOiI0M2I4NmM4MC01MWZmLTQwOGEtODQwOS01YzM1NDFiNjdjMDEifQ.vP2LSYsNfZihCm5pbPXpTOYxYP0Y_HqYv4axgd-LT1U"
},
{
"name": "i18nextLng",
"value": "en"
},
{
"name": "veza_refresh_token",
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkM2U1ZjhmOC02MDcxLTRmZDQtYWVhMi05ZmZkMzU0YmVmZDkiLCJlbWFpbCI6IiIsInJvbGUiOiIiLCJ0b2tlbl92ZXJzaW9uIjowLCJpc19yZWZyZXNoIjp0cnVlLCJ0b2tlbl90eXBlIjoicmVmcmVzaCIsInRva2VuX2ZhbWlseSI6IjMyZDJiOWI3LTNiYjQtNDVmYS1hMjk1LThiM2M1OGU1NTFhYiIsImlzcyI6InZlemEtYXBpIiwiYXVkIjpbInZlemEtYXBwIl0sImV4cCI6MTc2OTM2MDYzNSwiaWF0IjoxNzY2NzY4NjM1LCJqdGkiOiI4NzRhNjQxZS0xYWZhLTRlZjctODFiYy04YWM3Nzc4OWQ3ODUifQ.B1yOlNC97XfQzKX63PTliH8Km1pzmhWMmCE4ss6ufn4"
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkM2U1ZjhmOC02MDcxLTRmZDQtYWVhMi05ZmZkMzU0YmVmZDkiLCJlbWFpbCI6IiIsInJvbGUiOiIiLCJ0b2tlbl92ZXJzaW9uIjowLCJpc19yZWZyZXNoIjp0cnVlLCJ0b2tlbl90eXBlIjoicmVmcmVzaCIsInRva2VuX2ZhbWlseSI6ImY5NWYzMWY2LWNiMTItNDRiOC1iMWE0LTZlZWVlZjVlZGY3YiIsImlzcyI6InZlemEtYXBpIiwiYXVkIjpbInZlemEtYXBwIl0sImV4cCI6MTc2OTM3NDk0OSwiaWF0IjoxNzY2NzgyOTQ5LCJqdGkiOiJiY2JlM2ExMS1mOGZjLTQ3YWUtOTdjZS05MjU4MTYzOTExOTgifQ.jXfWPxE1Orn7_BD1akRb84LUozkKUIPIV76xs39aJ2k"
},
{
"name": "ui-storage",
"value": "{\"state\":{\"theme\":\"system\",\"language\":\"en\",\"sidebarOpen\":true},\"version\":0}"
},
{
"name": "auth-storage",
"value": "{\"state\":{\"isAuthenticated\":true,\"accessToken\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkM2U1ZjhmOC02MDcxLTRmZDQtYWVhMi05ZmZkMzU0YmVmZDkiLCJlbWFpbCI6ImUyZUB0ZXN0LmNvbSIsInVzZXJuYW1lIjoiZTJldXNlciIsInJvbGUiOiJ1c2VyIiwidG9rZW5fdmVyc2lvbiI6MCwidG9rZW5fdHlwZSI6ImFjY2VzcyIsImlzcyI6InZlemEtYXBpIiwiYXVkIjpbInZlemEtYXBwIl0sImV4cCI6MTc2Njc2OTUzNSwiaWF0IjoxNzY2NzY4NjM1LCJqdGkiOiJkMmJkYTQ2NC05N2ZiLTQ5NjAtYmU0MC1lNjk3NGM5Y2I5N2UifQ.Hj8-sN9JYmIGqFDe2Dv-hKSvb6DOShOb5GlsHFm-Ejs\",\"refreshToken\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkM2U1ZjhmOC02MDcxLTRmZDQtYWVhMi05ZmZkMzU0YmVmZDkiLCJlbWFpbCI6IiIsInJvbGUiOiIiLCJ0b2tlbl92ZXJzaW9uIjowLCJpc19yZWZyZXNoIjp0cnVlLCJ0b2tlbl90eXBlIjoicmVmcmVzaCIsInRva2VuX2ZhbWlseSI6IjMyZDJiOWI3LTNiYjQtNDVmYS1hMjk1LThiM2M1OGU1NTFhYiIsImlzcyI6InZlemEtYXBpIiwiYXVkIjpbInZlemEtYXBwIl0sImV4cCI6MTc2OTM2MDYzNSwiaWF0IjoxNzY2NzY4NjM1LCJqdGkiOiI4NzRhNjQxZS0xYWZhLTRlZjctODFiYy04YWM3Nzc4OWQ3ODUifQ.B1yOlNC97XfQzKX63PTliH8Km1pzmhWMmCE4ss6ufn4\"}}"
"value": "{\"state\":{\"isAuthenticated\":true,\"accessToken\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkM2U1ZjhmOC02MDcxLTRmZDQtYWVhMi05ZmZkMzU0YmVmZDkiLCJlbWFpbCI6ImUyZUB0ZXN0LmNvbSIsInVzZXJuYW1lIjoiZTJldXNlciIsInJvbGUiOiJ1c2VyIiwidG9rZW5fdmVyc2lvbiI6MCwidG9rZW5fdHlwZSI6ImFjY2VzcyIsImlzcyI6InZlemEtYXBpIiwiYXVkIjpbInZlemEtYXBwIl0sImV4cCI6MTc2Njc4Mzg0OSwiaWF0IjoxNzY2NzgyOTQ5LCJqdGkiOiI0M2I4NmM4MC01MWZmLTQwOGEtODQwOS01YzM1NDFiNjdjMDEifQ.vP2LSYsNfZihCm5pbPXpTOYxYP0Y_HqYv4axgd-LT1U\",\"refreshToken\":\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkM2U1ZjhmOC02MDcxLTRmZDQtYWVhMi05ZmZkMzU0YmVmZDkiLCJlbWFpbCI6IiIsInJvbGUiOiIiLCJ0b2tlbl92ZXJzaW9uIjowLCJpc19yZWZyZXNoIjp0cnVlLCJ0b2tlbl90eXBlIjoicmVmcmVzaCIsInRva2VuX2ZhbWlseSI6ImY5NWYzMWY2LWNiMTItNDRiOC1iMWE0LTZlZWVlZjVlZGY3YiIsImlzcyI6InZlemEtYXBpIiwiYXVkIjpbInZlemEtYXBwIl0sImV4cCI6MTc2OTM3NDk0OSwiaWF0IjoxNzY2NzgyOTQ5LCJqdGkiOiJiY2JlM2ExMS1mOGZjLTQ3YWUtOTdjZS05MjU4MTYzOTExOTgifQ.jXfWPxE1Orn7_BD1akRb84LUozkKUIPIV76xs39aJ2k\"}}"
}
]
}

View file

@ -49,136 +49,148 @@ test.describe('MVP Integration Tests - Exhaustifs', () => {
let refreshToken: string | null = null;
test.describe('1. Authentication Flow', () => {
test('1.1 - Login page loads correctly', async ({ page }) => {
await page.goto(`${TEST_CONFIG.FRONTEND_URL}/login`);
// Tests that require unauthenticated state
test.describe('Unauthenticated tests', () => {
// Reset storage state to ensure we start unauthenticated
test.use({ storageState: { cookies: [], origins: [] } });
// Vérifier que la page charge
await expect(page).toHaveTitle(/login|connexion|veza/i);
// Vérifier les éléments du formulaire
await expect(page.locator('input[type="email"], input[name="email"]')).toBeVisible();
await expect(page.locator('input[type="password"]')).toBeVisible();
await expect(page.locator('button[type="submit"]')).toBeVisible();
// Pas d'erreurs console
const errors: string[] = [];
page.on('console', msg => {
if (msg.type() === 'error') errors.push(msg.text());
test('1.1 - Login page loads correctly', async ({ page }) => {
await page.goto(`${TEST_CONFIG.FRONTEND_URL}/login`);
// Vérifier que la page charge
await expect(page).toHaveTitle(/login|connexion|veza/i);
// Vérifier les éléments du formulaire
await expect(page.locator('input[type="email"], input[name="email"]')).toBeVisible();
await expect(page.locator('input[type="password"]')).toBeVisible();
await expect(page.locator('button[type="submit"]')).toBeVisible();
// Pas d'erreurs console
const errors: string[] = [];
page.on('console', msg => {
if (msg.type() === 'error') errors.push(msg.text());
});
await page.waitForTimeout(1000);
const realErrors = errors.filter(e =>
!e.includes('favicon') &&
!e.includes('ResizeObserver') &&
!e.includes('net::ERR')
);
expect(realErrors).toHaveLength(0);
});
await page.waitForTimeout(1000);
const realErrors = errors.filter(e =>
!e.includes('favicon') &&
!e.includes('ResizeObserver') &&
!e.includes('net::ERR')
);
expect(realErrors).toHaveLength(0);
});
test('1.2 - Register page loads correctly', async ({ page }) => {
test('1.2 - Register page loads correctly', async ({ page }) => {
await page.goto(`${TEST_CONFIG.FRONTEND_URL}/register`);
await expect(page.locator('input[type="email"], input[name="email"]')).toBeVisible();
await expect(page.locator('input[name="username"]')).toBeVisible();
await expect(page.locator('input[type="password"]')).toBeVisible();
// Vérifier lien vers login
const loginLink = page.locator('a[href*="login"], a:has-text("Login"), a:has-text("Connexion")');
const loginLinkVisible = await loginLink.first().isVisible().catch(() => false);
// Ne pas échouer si le lien n'est pas visible (peut être dans un menu)
});
test('1.3 - Can register new user', async ({ page }) => {
await page.goto(`${TEST_CONFIG.FRONTEND_URL}/register`);
// Remplir le formulaire
await page.fill('input[type="email"], input[name="email"]', TEST_USER.email);
await page.fill('input[name="username"]', TEST_USER.username);
await page.fill('input[type="password"]', TEST_USER.password);
// Si champ confirmation
const confirmField = page.locator('input[name="password_confirmation"], input[name="confirmPassword"], input[name="passwordConfirm"]');
if (await confirmField.isVisible().catch(() => false)) {
await confirmField.fill(TEST_USER.password);
}
// Submit
await page.click('button[type="submit"]');
// Attendre redirection ou message succès
await page.waitForURL(/\/(login|dashboard|home)/, { timeout: 15000 }).catch(() => {});
// Vérifier pas d'erreur visible
const errorVisible = await page.locator('.error, [role="alert"]').isVisible().catch(() => false);
if (errorVisible) {
const errorText = await page.locator('.error, [role="alert"]').textContent();
console.log('Registration error:', errorText);
// Ne pas échouer immédiatement - peut être un message d'info
}
// Vérifier que l'utilisateur est créé (via API si nécessaire)
// Pour l'instant, on considère que si on arrive ici sans erreur, c'est OK
});
test('1.4 - Can login with registered user', async ({ page }) => {
await page.goto(`${TEST_CONFIG.FRONTEND_URL}/login`);
await page.fill('input[type="email"], input[name="email"]', TEST_USER.email);
await page.fill('input[type="password"]', TEST_USER.password);
await page.click('button[type="submit"]');
// Attendre redirection vers dashboard
await page.waitForURL(/\/(dashboard|home|app)/, { timeout: 15000 });
// Vérifier que l'utilisateur est connecté
const loggedIn = await page.locator('[data-testid="user-menu"], .user-avatar, .logout-button, nav[role="navigation"]').isVisible().catch(() => false);
// Vérifier localStorage
const token = await page.evaluate(() =>
localStorage.getItem('access_token') ||
localStorage.getItem('accessToken') ||
localStorage.getItem('veza_access_token')
);
expect(token || loggedIn).toBeTruthy();
});
test('1.5 - Protected route redirects when not logged in', async ({ page }) => {
// Clear any existing auth
await page.goto(`${TEST_CONFIG.FRONTEND_URL}`);
await page.evaluate(() => {
localStorage.clear();
sessionStorage.clear();
await expect(page.locator('input[type="email"], input[name="email"]')).toBeVisible();
await expect(page.locator('input[name="username"]')).toBeVisible();
await expect(page.locator('input[type="password"]')).toBeVisible();
// Vérifier lien vers login
const loginLink = page.locator('a[href*="login"], a:has-text("Login"), a:has-text("Connexion")');
const loginLinkVisible = await loginLink.first().isVisible().catch(() => false);
// Ne pas échouer si le lien n'est pas visible (peut être dans un menu)
});
// Try to access protected route
await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`);
// Should redirect to login
await page.waitForURL(/\/login/, { timeout: 5000 }).catch(() => {});
const currentUrl = page.url();
expect(currentUrl).toContain('login');
});
test('1.6 - Can logout', async ({ page }) => {
// Login first
await page.goto(`${TEST_CONFIG.FRONTEND_URL}/login`);
await page.fill('input[type="email"], input[name="email"]', TEST_USER.email);
await page.fill('input[type="password"]', TEST_USER.password);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(dashboard|home|app)/, { timeout: 15000 });
test('1.3 - Can register new user', async ({ page }) => {
await page.goto(`${TEST_CONFIG.FRONTEND_URL}/register`);
// Click logout
const logoutButton = page.locator('button:has-text("Logout"), button:has-text("Déconnexion"), [data-testid="logout"]');
if (await logoutButton.isVisible().catch(() => false)) {
await logoutButton.click();
// Remplir le formulaire
await page.fill('input[type="email"], input[name="email"]', TEST_USER.email);
await page.fill('input[name="username"]', TEST_USER.username);
await page.fill('input[type="password"]', TEST_USER.password);
// Si champ confirmation
const confirmField = page.locator('input[name="password_confirmation"], input[name="confirmPassword"], input[name="passwordConfirm"]');
if (await confirmField.isVisible().catch(() => false)) {
await confirmField.fill(TEST_USER.password);
}
// Submit
await page.click('button[type="submit"]');
// Attendre redirection ou message succès
await page.waitForURL(/\/(login|dashboard|home)/, { timeout: 15000 }).catch(() => {});
// Vérifier pas d'erreur visible
const errorVisible = await page.locator('.error, [role="alert"]').isVisible().catch(() => false);
if (errorVisible) {
const errorText = await page.locator('.error, [role="alert"]').textContent();
console.log('Registration error:', errorText);
// Ne pas échouer immédiatement - peut être un message d'info
}
// Vérifier que l'utilisateur est créé (via API si nécessaire)
// Pour l'instant, on considère que si on arrive ici sans erreur, c'est OK
});
test('1.4 - Can login with registered user', async ({ page }) => {
await page.goto(`${TEST_CONFIG.FRONTEND_URL}/login`);
await page.fill('input[type="email"], input[name="email"]', TEST_USER.email);
await page.fill('input[type="password"]', TEST_USER.password);
await page.click('button[type="submit"]');
// Attendre redirection vers dashboard
await page.waitForURL(/\/(dashboard|home|app)/, { timeout: 15000 });
// Vérifier que l'utilisateur est connecté
const loggedIn = await page.locator('[data-testid="user-menu"], .user-avatar, .logout-button, nav[role="navigation"]').isVisible().catch(() => false);
// Vérifier localStorage
const token = await page.evaluate(() =>
localStorage.getItem('access_token') ||
localStorage.getItem('accessToken') ||
localStorage.getItem('veza_access_token')
);
expect(token || loggedIn).toBeTruthy();
});
test('1.5 - Protected route redirects when not logged in', async ({ page }) => {
// Clear any existing auth
await page.goto(`${TEST_CONFIG.FRONTEND_URL}`);
await page.evaluate(() => {
localStorage.clear();
sessionStorage.clear();
});
// Try to access protected route
await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`);
// Should redirect to login
await page.waitForURL(/\/(login|home|\/)/, { timeout: 5000 });
await page.waitForURL(/\/login/, { timeout: 5000 }).catch(() => {});
const currentUrl = page.url();
expect(currentUrl).toContain('login');
});
});
// Tests that require authenticated state
test.describe('Authenticated tests', () => {
test('1.6 - Can logout', async ({ page }) => {
// Login first (if not already authenticated from storageState)
await page.goto(`${TEST_CONFIG.FRONTEND_URL}/dashboard`);
const isOnDashboard = page.url().includes('/dashboard');
if (!isOnDashboard) {
await page.goto(`${TEST_CONFIG.FRONTEND_URL}/login`);
await page.fill('input[type="email"], input[name="email"]', TEST_USER.email);
await page.fill('input[type="password"]', TEST_USER.password);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(dashboard|home|app)/, { timeout: 15000 });
}
// Token should be cleared
const token = await page.evaluate(() => localStorage.getItem('access_token'));
expect(token).toBeFalsy();
}
// Click logout
const logoutButton = page.locator('button:has-text("Logout"), button:has-text("Déconnexion"), [data-testid="logout"]');
if (await logoutButton.isVisible().catch(() => false)) {
await logoutButton.click();
// Should redirect to login
await page.waitForURL(/\/(login|home|\/)/, { timeout: 5000 });
// Token should be cleared
const token = await page.evaluate(() => localStorage.getItem('access_token'));
expect(token).toBeFalsy();
}
});
});
});