import { test, expect } from '@playwright/test'; /** * Test de debug pour le problème de focus sur les inputs * Ce test capture l'état actuel et génère un rapport de debug * NE REQUIERT PAS d'authentification */ test.describe('Debug Input Focus Issue', () => { test.use({ // Ne pas utiliser le storageState pour ce test de debug storageState: undefined, }); test.beforeEach(async ({ page }) => { // Aller sur la page de login await page.goto('/login'); // Attendre que la page soit complètement chargée await page.waitForLoadState('domcontentloaded'); await page.waitForTimeout(1000); // Attendre le rendu React // Capturer une screenshot pour debug await page.screenshot({ path: 'test-results/debug-page-loaded.png', fullPage: true }); // Vérifier que la page est chargée const bodyText = await page.textContent('body'); console.log('📄 Contenu de la page:', bodyText?.substring(0, 200)); }); test('Debug: Vérifier les styles CSS des inputs au chargement', async ({ page }) => { // Lister tous les inputs pour debug const allInputs = await page.locator('input').all(); console.log(`🔍 Nombre d'inputs trouvés: ${allInputs.length}`); const inputsInfo = []; for (let i = 0; i < allInputs.length; i++) { const input = allInputs[i]; const type = await input.getAttribute('type') || 'text'; const name = await input.getAttribute('name') || ''; const id = await input.getAttribute('id') || ''; const placeholder = await input.getAttribute('placeholder') || ''; const classes = await input.getAttribute('class') || ''; inputsInfo.push({ index: i, type, name, id, placeholder, classes }); console.log(` Input ${i}: type=${type}, name=${name}, id=${id}, placeholder=${placeholder}`); } // Trouver l'input email (peut être type="email" ou name="email") let emailInput = page.locator('input[type="email"]').first(); if (await emailInput.count() === 0) { emailInput = page.locator('input[name="email"]').first(); } if (await emailInput.count() === 0 && allInputs.length > 0) { // Utiliser le premier input si aucun email spécifique emailInput = allInputs[0]; console.log('⚠️ Utilisation du premier input trouvé'); } if (await emailInput.count() === 0) { throw new Error('Aucun input trouvé sur la page'); } await expect(emailInput).toBeVisible({ timeout: 10000 }); // Capturer une screenshot await page.screenshot({ path: 'test-results/debug-input-initial.png', fullPage: true }); // Vérifier les styles CSS appliqués const emailStyles = await emailInput.evaluate((el) => { const computed = window.getComputedStyle(el); return { borderColor: computed.borderColor, outline: computed.outline, outlineWidth: computed.outlineWidth, boxShadow: computed.boxShadow, ringWidth: computed.getPropertyValue('--tw-ring-width'), classes: el.className, hasFocus: document.activeElement === el, }; }); console.log('📊 Styles de l\'input Email au chargement:'); console.log(JSON.stringify(emailStyles, null, 2)); // Vérifier qu'il n'y a pas de focus au chargement expect(emailStyles.hasFocus).toBe(false); // Vérifier que le border n'est pas cyan const borderColorRgb = emailStyles.borderColor; const hasCyanBorder = borderColorRgb.includes('102') && borderColorRgb.includes('252') && borderColorRgb.includes('241'); if (hasCyanBorder) { console.error('❌ PROBLÈME: Border cyan visible au chargement!'); console.error(` Border color: ${borderColorRgb}`); } else { console.log('✅ Pas de border cyan au chargement'); } }); test('Debug: Vérifier les styles CSS au clic souris', async ({ page }) => { // Trouver l'input (peut être type="email" ou name="email" ou premier input) let emailInput = page.locator('input[type="email"]').first(); if (await emailInput.count() === 0) { emailInput = page.locator('input[name="email"]').first(); } if (await emailInput.count() === 0) { emailInput = page.locator('input').first(); } await expect(emailInput).toBeVisible({ timeout: 10000 }); // Cliquer sur l'input await emailInput.click(); await page.waitForTimeout(200); // Attendre que les styles soient appliqués // Capturer une screenshot await page.screenshot({ path: 'test-results/debug-input-after-click.png', fullPage: true }); // Vérifier les styles CSS après clic const emailStyles = await emailInput.evaluate((el) => { const computed = window.getComputedStyle(el); return { borderColor: computed.borderColor, outline: computed.outline, outlineWidth: computed.outlineWidth, boxShadow: computed.boxShadow, ringWidth: computed.getPropertyValue('--tw-ring-width'), classes: el.className, hasFocus: document.activeElement === el, isFocusVisible: el.matches(':focus-visible'), }; }); console.log('📊 Styles de l\'input Email après clic:'); console.log(JSON.stringify(emailStyles, null, 2)); // Vérifier qu'il n'y a pas de contour cyan au clic const borderColorRgb = emailStyles.borderColor; const hasCyanBorder = borderColorRgb.includes('102') && borderColorRgb.includes('252') && borderColorRgb.includes('241'); console.log(`🔍 Border color: ${borderColorRgb}`); console.log(`🔍 Has cyan border: ${hasCyanBorder}`); console.log(`🔍 Is focus-visible: ${emailStyles.isFocusVisible}`); console.log(`🔍 Has focus: ${emailStyles.hasFocus}`); // Le border ne devrait PAS être cyan au clic (seulement au clavier) if (hasCyanBorder && !emailStyles.isFocusVisible) { console.error('❌ PROBLÈME DÉTECTÉ: Border cyan visible au clic souris!'); console.error(' Le fix CSS ne fonctionne pas correctement.'); console.error(` Classes: ${emailStyles.classes}`); } else if (!hasCyanBorder) { console.log('✅ Pas de border cyan au clic (correct)'); } }); test('Debug: Vérifier les styles CSS au clavier (Tab)', async ({ page }) => { // Trouver l'input (peut être type="email" ou name="email" ou premier input) let emailInput = page.locator('input[type="email"]').first(); if (await emailInput.count() === 0) { emailInput = page.locator('input[name="email"]').first(); } if (await emailInput.count() === 0) { emailInput = page.locator('input').first(); } await expect(emailInput).toBeVisible({ timeout: 10000 }); // Naviguer avec Tab await page.keyboard.press('Tab'); await page.waitForTimeout(200); // Capturer une screenshot await page.screenshot({ path: 'test-results/debug-input-after-tab.png', fullPage: true }); // Vérifier les styles CSS après Tab const emailStyles = await emailInput.evaluate((el) => { const computed = window.getComputedStyle(el); return { borderColor: computed.borderColor, outline: computed.outline, outlineWidth: computed.outlineWidth, boxShadow: computed.boxShadow, ringWidth: computed.getPropertyValue('--tw-ring-width'), classes: el.className, hasFocus: document.activeElement === el, isFocusVisible: el.matches(':focus-visible'), }; }); console.log('📊 Styles de l\'input Email après Tab:'); console.log(JSON.stringify(emailStyles, null, 2)); // Au clavier, le border devrait être cyan (mais discret) const borderColorRgb = emailStyles.borderColor; const hasCyanBorder = borderColorRgb.includes('102') && borderColorRgb.includes('252') && borderColorRgb.includes('241'); console.log(`🔍 Border color: ${borderColorRgb}`); console.log(`🔍 Has cyan border: ${hasCyanBorder}`); console.log(`🔍 Is focus-visible: ${emailStyles.isFocusVisible}`); // Au clavier, le border devrait être cyan if (emailStyles.isFocusVisible && !hasCyanBorder) { console.warn('⚠️ Le border cyan n\'apparaît pas au clavier (focus-visible)'); } else if (emailStyles.isFocusVisible && hasCyanBorder) { console.log('✅ Border cyan visible au clavier (correct)'); } }); test('Debug: Analyser toutes les classes CSS appliquées', async ({ page }) => { // Trouver l'input (peut être type="email" ou name="email" ou premier input) let emailInput = page.locator('input[type="email"]').first(); if (await emailInput.count() === 0) { emailInput = page.locator('input[name="email"]').first(); } if (await emailInput.count() === 0) { emailInput = page.locator('input').first(); } await expect(emailInput).toBeVisible({ timeout: 10000 }); // Analyser toutes les classes et styles const analysis = await emailInput.evaluate((el) => { const computed = window.getComputedStyle(el); const allStyles: Record = {}; // Récupérer tous les styles CSS for (let i = 0; i < computed.length; i++) { const prop = computed[i]; allStyles[prop] = computed.getPropertyValue(prop); } return { classes: el.className, classList: Array.from(el.classList), hasFocusClass: el.className.includes('focus:'), hasFocusVisibleClass: el.className.includes('focus-visible:'), inlineStyle: el.getAttribute('style'), computedStyles: { borderColor: computed.borderColor, borderWidth: computed.borderWidth, borderStyle: computed.borderStyle, outline: computed.outline, outlineWidth: computed.outlineWidth, boxShadow: computed.boxShadow, '--tw-ring-width': computed.getPropertyValue('--tw-ring-width'), '--tw-ring-color': computed.getPropertyValue('--tw-ring-color'), }, allStyles: Object.fromEntries( Object.entries(allStyles).filter(([key]) => key.includes('border') || key.includes('outline') || key.includes('ring') || key.includes('shadow') ) ), }; }); console.log('📊 Analyse complète de l\'input Email:'); console.log(JSON.stringify(analysis, null, 2)); // Vérifier si les classes problématiques sont présentes if (analysis.hasFocusClass) { console.warn('⚠️ Classes focus: détectées dans className:', analysis.classList.filter(c => c.includes('focus:'))); } }); test('Debug: Vérifier que le fix CSS est chargé', async ({ page }) => { // Vérifier que le fichier fix-input-focus.css est chargé const stylesheets = await page.evaluate(() => { return Array.from(document.styleSheets).map((sheet, index) => { try { return { index, href: sheet.href || 'inline', rules: sheet.cssRules ? Array.from(sheet.cssRules).length : 0, }; } catch (e) { return { index, href: sheet.href || 'inline', rules: 'cross-origin', }; } }); }); console.log('📊 Feuilles de style chargées:'); console.log(JSON.stringify(stylesheets, null, 2)); // Vérifier que fix-input-focus.css est présent const hasFixCss = stylesheets.some(s => s.href && s.href.includes('fix-input-focus')); console.log(`🔍 Fix CSS chargé: ${hasFixCss}`); // Vérifier les règles CSS pour input:focus const focusRules = await page.evaluate(() => { const rules: Array<{ selector: string; borderColor?: string }> = []; Array.from(document.styleSheets).forEach((sheet) => { try { if (sheet.cssRules) { Array.from(sheet.cssRules).forEach((rule: any) => { if (rule.selectorText && rule.selectorText.includes('input') && rule.selectorText.includes('focus')) { const style = rule.style; rules.push({ selector: rule.selectorText, borderColor: style.borderColor || style.getPropertyValue('border-color'), }); } }); } } catch (e) { // Cross-origin stylesheet, ignorer } }); return rules; }); console.log('📊 Règles CSS pour input:focus trouvées:'); console.log(JSON.stringify(focusRules, null, 2)); }); });