veza/tests/e2e/audit/interaction/04-toasts-notifications.spec.ts
senke 4d4bfc5452 fix(e2e): prepend CONFIG.baseURL in all audit test page.goto calls
Fix 11 page.goto() calls in 6 test files that used relative URLs
without baseURL (incompatible with @chromatic-com/playwright).

Functional audit: 44/50 pass (6 test-level issues, not app bugs)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 14:26:09 +01:00

97 lines
4.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { test, expect } from '@chromatic-com/playwright';
import { loginViaAPI, loginViaUI, navigateTo, waitForToast, CONFIG } from '../helpers';
import { TEST_USERS } from '../design-tokens';
test.describe('TOASTS & NOTIFICATIONS — Apparaissent, disparaissent, ne cachent rien', () => {
test('Login réussi — un toast ou redirection se produit', async ({ page }) => {
await loginViaUI(page, TEST_USERS.listener.email, TEST_USERS.listener.password);
// Soit un toast de succès apparaît, soit on est redirigé
const redirected = page.url().includes('/dashboard') || page.url().includes('/feed');
const toast = page.getByTestId('toast-alert').first();
const toastVisible = await toast.isVisible({ timeout: 3_000 }).catch(() => false);
expect(redirected || toastVisible, 'Ni redirection ni toast après login').toBe(true);
if (toastVisible) {
// Vérifier que le toast ne cache pas de bouton important
const toastBox = await toast.boundingBox();
if (toastBox) {
console.log(`[TOAST] Position: x=${toastBox.x} y=${toastBox.y} w=${toastBox.width} h=${toastBox.height}`);
}
}
});
test('Login échoué — un toast d\'erreur ou message d\'erreur apparaît', async ({ page }) => {
await page.goto(CONFIG.baseURL + '/login', { waitUntil: 'domcontentloaded' });
await page.waitForLoadState('networkidle').catch(() => {});
await page.locator('main, [role="main"]').first().waitFor({ state: 'visible', timeout: 15_000 }).catch(() => {});
const email = page.locator('input[type="email"]');
await email.waitFor({ state: 'visible', timeout: 10_000 });
await email.fill('wrong@wrong.com');
await page.locator('input[type="password"]').fill('WrongPassword123!');
await page.getByTestId('login-submit').click();
await page.waitForTimeout(3_000);
// Un message d'erreur doit être visible (toast ou inline)
const errorToast = page.getByTestId('toast-alert').first();
const inlineError = page.locator('[role="alert"], [class*="error"], [class*="destructive"]').first();
const toastVisible = await errorToast.isVisible().catch(() => false);
const inlineVisible = await inlineError.isVisible().catch(() => false);
console.log(`[TOAST] Error toast visible: ${toastVisible}, inline error visible: ${inlineVisible}`);
expect(toastVisible || inlineVisible, 'Aucun feedback d\'erreur après login échoué').toBe(true);
});
test('Toast — ne bloque pas les boutons du header ou sidebar', async ({ page }) => {
await loginViaAPI(page, TEST_USERS.listener.email, TEST_USERS.listener.password);
await navigateTo(page, '/dashboard');
// Essayer de provoquer un toast (par exemple, action qui échoue)
// Pour l'instant, vérifier que s'il y a un toast, il est dans un coin non-bloquant
const toast = page.getByTestId('toast-alert').first();
if (await toast.isVisible({ timeout: 3_000 }).catch(() => false)) {
const toastBox = await toast.boundingBox();
const sidebar = page.locator('[data-testid="app-sidebar"]');
const sidebarBox = await sidebar.boundingBox().catch(() => null);
if (toastBox && sidebarBox) {
const overlapX = Math.max(0, Math.min(toastBox.x + toastBox.width, sidebarBox.x + sidebarBox.width) - Math.max(toastBox.x, sidebarBox.x));
const overlapY = Math.max(0, Math.min(toastBox.y + toastBox.height, sidebarBox.y + sidebarBox.height) - Math.max(toastBox.y, sidebarBox.y));
if (overlapX > 0 && overlapY > 0) {
console.log(`[TOAST] Le toast recouvre le sidebar de ${overlapX}×${overlapY}px`);
}
}
}
});
test('Toast — disparaît automatiquement après ~4 secondes', async ({ page }) => {
// Ce test nécessite qu'un toast soit affiché — on peut le provoquer via login
await page.goto(CONFIG.baseURL + '/login', { waitUntil: 'domcontentloaded' });
await page.waitForLoadState('networkidle').catch(() => {});
await page.locator('main, [role="main"]').first().waitFor({ state: 'visible', timeout: 15_000 }).catch(() => {});
// Login invalide pour provoquer un toast d'erreur
const email = page.locator('input[type="email"]');
await email.waitFor({ state: 'visible', timeout: 10_000 });
await email.fill('nonexistent@test.com');
await page.locator('input[type="password"]').fill('WrongPass123!');
await page.getByTestId('login-submit').click();
const toast = page.getByTestId('toast-alert').first();
const appeared = await toast.isVisible({ timeout: 5_000 }).catch(() => false);
if (appeared) {
console.log('[TOAST] Toast d\'erreur apparu — vérification auto-dismiss...');
// Attendre qu'il disparaisse (typiquement 4s)
await toast.waitFor({ state: 'hidden', timeout: 8_000 }).catch(() => {});
const stillVisible = await toast.isVisible().catch(() => false);
console.log(`[TOAST] Encore visible après 8s: ${stillVisible}`);
// Ce n'est pas bloquant si le toast reste (peut avoir un bouton close)
}
});
});