import { test, expect } from '@chromatic-com/playwright'; import { loginViaAPI, navigateTo } from '../helpers'; import { getFormFields } from '../helpers/interaction-helpers'; import { TEST_USERS } from '../design-tokens'; test.describe('FORMULAIRES & VALIDATION — Chaque formulaire valide/invalide/vide', () => { test('Login — soumission vide affiche des erreurs', async ({ page }) => { await navigateTo(page, '/login'); const submit = page.getByTestId('login-submit'); await submit.waitFor({ state: 'visible', timeout: 10_000 }); // Vider les champs (au cas où ils sont pré-remplis) const email = page.locator('input[type="email"]'); await email.waitFor({ state: 'visible' }); await email.clear(); const password = page.locator('input[type="password"]'); await password.clear(); // Soumettre vide await submit.click(); await page.waitForTimeout(2_000); // Doit rester sur /login expect(page.url()).toContain('/login'); // Devrait afficher des messages d'erreur (validation HTML5 ou custom) const body = await page.textContent('body') || ''; const hasValidation = body.match(/required|requis|obligatoire|invalide|invalid|veuillez|please/i) || (await page.locator('[class*="error"], [class*="destructive"], [role="alert"]').count()) > 0; console.log(`[FORM] Login — validation errors visible: ${!!hasValidation}`); }); test('Register — champs requis sont validés', async ({ page }) => { await navigateTo(page, '/register'); const form = page.getByTestId('register-form').or(page.locator('form')).first(); await form.waitFor({ state: 'visible', timeout: 10_000 }); // Vérifier les champs const fields = await getFormFields(page, form.first() ? 'form' : '[data-testid="register-form"]'); console.log(`[FORM] Register — ${fields.length} champs trouvés:`); for (const field of fields) { console.log(` ${field.name} (${field.type}) — required: ${field.required}, label: "${field.label}"`); } // Au minimum : email, password, username expect(fields.length, 'Le formulaire d\'inscription devrait avoir au moins 3 champs').toBeGreaterThanOrEqual(3); // Tester email invalide const emailInput = page.locator('input[type="email"]'); if (await emailInput.isVisible().catch(() => false)) { await emailInput.fill('not-an-email'); await page.locator('input[type="password"]').first().fill('a'); const submitBtn = page.locator('button[type="submit"]').first(); if (await submitBtn.isVisible().catch(() => false)) { await submitBtn.click(); await page.waitForTimeout(2_000); // Devrait montrer une erreur expect(page.url()).toContain('/register'); } } }); test('Settings — les formulaires de profil sauvegardent correctement', async ({ page }) => { await loginViaAPI(page, TEST_USERS.listener.email, TEST_USERS.listener.password); await navigateTo(page, '/settings'); // Vérifier que les champs de profil sont pré-remplis const inputs = await page.locator('input:visible').all(); let prefilledCount = 0; for (const input of inputs.slice(0, 10)) { const value = await input.inputValue().catch(() => ''); if (value.length > 0) prefilledCount++; } console.log(`[FORM] Settings — ${prefilledCount}/${inputs.length} champs pré-remplis`); }); test('Forms — pas de double soumission (bouton disabled après clic)', async ({ page }) => { await navigateTo(page, '/login'); const email = page.locator('input[type="email"]'); await email.waitFor({ state: 'visible', timeout: 10_000 }); await email.fill(TEST_USERS.listener.email); await page.locator('input[type="password"]').fill(TEST_USERS.listener.password); const submit = page.getByTestId('login-submit'); await submit.click(); // Après le premier clic, vérifier si le bouton est désactivé ou en état loading await page.waitForTimeout(500); const isDisabledOrLoading = await submit.evaluate(el => { return (el as HTMLButtonElement).disabled || el.getAttribute('aria-busy') === 'true' || el.classList.contains('loading') || el.textContent?.includes('...') || false; }).catch(() => false); console.log(`[FORM] Submit button disabled/loading after click: ${isDisabledOrLoading}`); }); test('Forgot password — le formulaire accepte un email et affiche confirmation', async ({ page }) => { await navigateTo(page, '/forgot-password'); const emailInput = page.locator('input[type="email"]'); await emailInput.waitFor({ state: 'visible', timeout: 10_000 }); await emailInput.fill('test@example.com'); const submit = page.locator('button[type="submit"]').first(); if (await submit.isVisible().catch(() => false)) { await submit.click(); await page.waitForTimeout(3_000); // La page ne devrait pas crasher const body = await page.textContent('body') || ''; expect(body).not.toMatch(/500|Internal Server Error/i); } }); });