veza/tests/e2e/audit/interaction/07-toasts-advanced.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

101 lines
4.5 KiB
TypeScript

import { test, expect } from '@chromatic-com/playwright';
import { loginViaAPI, navigateTo, CONFIG } from '../helpers';
import { TEST_USERS } from '../design-tokens';
test.describe('TOASTS AVANCÉS — Positionnement, style et timing', () => {
test('Les toasts apparaissent en haut à droite (pas au centre)', async ({ page }) => {
await loginViaAPI(page, TEST_USERS.listener.email, TEST_USERS.listener.password);
await navigateTo(page, '/settings');
// Provoquer un toast — chercher un bouton de sauvegarde ou action
const saveBtn = page.locator('button').filter({ hasText: /sauvegarder|save|enregistrer|mettre à jour|update/i }).first();
if (await saveBtn.isVisible({ timeout: 5_000 }).catch(() => false)) {
await saveBtn.click();
await page.waitForTimeout(2_000);
}
// Vérifier la position des toasts s'il y en a
const toastInfo = await page.evaluate(() => {
const toasts = document.querySelectorAll('[data-testid="toast-alert"], [role="alert"][class*="toast"], [class*="Toast"]');
if (toasts.length === 0) return null;
const first = toasts[0];
const rect = first.getBoundingClientRect();
const vw = window.innerWidth;
const vh = window.innerHeight;
return {
x: Math.round(rect.x),
y: Math.round(rect.y),
width: Math.round(rect.width),
isTopRight: rect.right > vw * 0.5 && rect.top < vh * 0.3,
isBottomRight: rect.right > vw * 0.5 && rect.bottom > vh * 0.7,
isCentered: rect.left > vw * 0.25 && rect.right < vw * 0.75,
};
});
if (toastInfo) {
console.log(`[TOAST] Position: x=${toastInfo.x}, y=${toastInfo.y}, w=${toastInfo.width}`);
console.log(` Top-right: ${toastInfo.isTopRight}, Bottom-right: ${toastInfo.isBottomRight}, Centered: ${toastInfo.isCentered}`);
}
});
test('Toast d\'erreur a le style vermillion (rouge)', 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('nonexistent@test.com');
await page.locator('input[type="password"]').fill('WrongPassword!');
await page.getByTestId('login-submit').click();
await page.waitForTimeout(3_000);
const toastStyle = await page.evaluate(() => {
const toast = document.querySelector('[data-testid="toast-alert"], [role="alert"]');
if (!toast) return null;
const style = getComputedStyle(toast);
const bg = style.backgroundColor;
const text = toast.textContent?.trim().slice(0, 50) || '';
// Parse RGB to check if it's reddish
const match = bg.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
let isReddish = false;
if (match) {
const [r, g, b] = [parseInt(match[1]), parseInt(match[2]), parseInt(match[3])];
isReddish = r > g && r > b;
}
return { bg, text, isReddish, borderColor: style.borderColor };
});
if (toastStyle) {
console.log(`[TOAST STYLE] Error toast: bg=${toastStyle.bg}, text="${toastStyle.text}", isReddish=${toastStyle.isReddish}`);
}
});
test('Toasts n\'empêchent pas l\'interaction avec le reste de la page', async ({ page }) => {
await loginViaAPI(page, TEST_USERS.listener.email, TEST_USERS.listener.password);
await navigateTo(page, '/dashboard');
// S'il y a un toast, vérifier que les éléments derrière sont cliquables
const toast = page.getByTestId('toast-alert').first();
if (await toast.isVisible({ timeout: 3_000 }).catch(() => false)) {
const toastBox = await toast.boundingBox();
if (toastBox) {
// Vérifier le z-index du toast
const zIndex = await toast.evaluate(el => parseInt(getComputedStyle(el).zIndex) || 0);
console.log(`[TOAST] z-index: ${zIndex}, position: ${toastBox.x},${toastBox.y}`);
// Les toasts doivent avoir pointer-events: auto mais ne pas avoir pointer-events: none sur les éléments en dessous
const blocksClick = await page.evaluate((box) => {
const el = document.elementFromPoint(box.x + box.width / 2, box.y + box.height + 10);
return el ? getComputedStyle(el).pointerEvents : 'none';
}, toastBox);
expect(blocksClick, 'Les éléments sous le toast ne sont pas cliquables (pointer-events bloqué)').not.toBe('none');
}
}
});
});