veza/apps/web/e2e/debug-input-focus.spec.ts
senke 023b8a89c6 fix: Corriger URL Swagger et finaliser implémentation DeveloperPage
- Ajouter fallback pour Swagger UI si doc.json ne fonctionne pas
- Améliorer message d'erreur avec bouton pour ouvrir Swagger UI directement
- Les fonctionnalités API Keys et Usage Stats sont maintenant complètes et fonctionnelles
- Tous les onglets de DeveloperPage sont maintenant implémentés
2026-01-18 13:55:28 +01:00

316 lines
12 KiB
TypeScript

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<string, string> = {};
// 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));
});
});