Refine auth, player, tracks, playlists, search, workflows, edge cases, forms, responsive, network errors, error boundary, performance, visual regression, cross-browser, profile, smoke, storybook, chat, and session tests. Add audit test suite (accessibility, ethical, functional, design tokens). Update test helpers and visual snapshots. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
115 lines
4.8 KiB
TypeScript
115 lines
4.8 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import { loginViaAPI, navigateTo } from '../helpers';
|
|
import { TEST_USERS } from '../design-tokens';
|
|
|
|
test.describe('BORDURES, ARRONDIS & OMBRES — Cohérence visuelle', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await loginViaAPI(page, TEST_USERS.listener.email, TEST_USERS.listener.password);
|
|
});
|
|
|
|
test('Dashboard — les cards ont des border-radius cohérents', async ({ page }) => {
|
|
await navigateTo(page, '/dashboard');
|
|
|
|
const cardRadii = await page.evaluate(() => {
|
|
const cards = document.querySelectorAll('[class*="card"], [class*="Card"], [role="article"]');
|
|
const radii: Array<{ selector: string; text: string; borderRadius: string }> = [];
|
|
|
|
cards.forEach(el => {
|
|
const style = getComputedStyle(el);
|
|
if (style.display === 'none') return;
|
|
const br = style.borderRadius;
|
|
if (br === '0px') return;
|
|
|
|
radii.push({
|
|
selector: el.getAttribute('data-testid') || (typeof el.className === 'string' ? el.className : '').split(' ').slice(0, 2).join('.'),
|
|
text: el.textContent?.trim().slice(0, 20) || '',
|
|
borderRadius: br,
|
|
});
|
|
});
|
|
return radii;
|
|
});
|
|
|
|
if (cardRadii.length < 2) return;
|
|
|
|
// Vérifier la cohérence : toutes les cards du même type devraient avoir le même radius
|
|
const uniqueRadii = [...new Set(cardRadii.map(c => c.borderRadius))];
|
|
if (uniqueRadii.length > 2) {
|
|
console.log(`[RADIUS] ${uniqueRadii.length} border-radius différents sur les cards du dashboard:`);
|
|
for (const card of cardRadii) {
|
|
console.log(` ${card.selector}: ${card.borderRadius}`);
|
|
}
|
|
console.log(` FIX: Uniformiser les cards avec rounded-lg (12px) ou rounded-xl (16px)`);
|
|
}
|
|
|
|
// Tolérance de 2 variantes (ex: rounded-lg pour les cards principales, rounded-xl pour les featured)
|
|
expect(uniqueRadii.length,
|
|
`Trop de border-radius différents (${uniqueRadii.length}) sur les cards: [${uniqueRadii.join(', ')}]. FIX: Uniformiser.`
|
|
).toBeLessThanOrEqual(3);
|
|
});
|
|
|
|
test('Boutons — border-radius cohérent par variante', async ({ page }) => {
|
|
await navigateTo(page, '/dashboard');
|
|
|
|
const buttonRadii = await page.evaluate(() => {
|
|
const buttons = document.querySelectorAll('button:not([hidden])');
|
|
const radii: Array<{ text: string; borderRadius: string; classes: string }> = [];
|
|
|
|
buttons.forEach(btn => {
|
|
const style = getComputedStyle(btn);
|
|
if (style.display === 'none' || style.visibility === 'hidden') return;
|
|
|
|
radii.push({
|
|
text: btn.textContent?.trim().slice(0, 20) || btn.getAttribute('aria-label') || '',
|
|
borderRadius: style.borderRadius,
|
|
classes: (typeof btn.className === 'string' ? btn.className : '').slice(0, 60),
|
|
});
|
|
});
|
|
return radii;
|
|
});
|
|
|
|
// Les boutons devraient utiliser des radius standard du design system
|
|
const validRadii = ['4px', '6px', '8px', '12px', '16px', '9999px', '0px'];
|
|
const invalidButtons = buttonRadii.filter(b => {
|
|
const allCorners = b.borderRadius.split(' ').map(v => v.trim());
|
|
return !allCorners.every(corner => validRadii.includes(corner));
|
|
});
|
|
|
|
if (invalidButtons.length > 0) {
|
|
console.log(`[RADIUS] Boutons avec border-radius non-standard:`);
|
|
for (const b of invalidButtons) {
|
|
console.log(` "${b.text}": ${b.borderRadius} — FIX: utiliser rounded-sm (4px), rounded-md (6px), rounded-lg (12px), ou rounded-full (9999px)`);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('Inputs — tous les champs ont un border radius d\'au moins 6px', async ({ page }) => {
|
|
await navigateTo(page, '/settings');
|
|
|
|
const inputRadii = await page.evaluate(() => {
|
|
const inputs = document.querySelectorAll('input:not([type="hidden"]):not([type="checkbox"]):not([type="radio"]), textarea, select');
|
|
return Array.from(inputs)
|
|
.filter(el => getComputedStyle(el).display !== 'none')
|
|
.map(el => ({
|
|
type: (el as HTMLInputElement).type || el.tagName.toLowerCase(),
|
|
name: (el as HTMLInputElement).name || (el as HTMLInputElement).placeholder?.slice(0, 20) || '',
|
|
borderRadius: getComputedStyle(el).borderRadius,
|
|
}));
|
|
});
|
|
|
|
const tooSharp = inputRadii.filter(i => {
|
|
const px = parseFloat(i.borderRadius);
|
|
return !isNaN(px) && px < 6;
|
|
});
|
|
|
|
if (tooSharp.length > 0) {
|
|
console.log(`[RADIUS] Inputs avec radius < 6px (design system minimum: 6px / rounded-md):`);
|
|
for (const i of tooSharp) {
|
|
console.log(` input[type="${i.type}"] "${i.name}": ${i.borderRadius} — FIX: utiliser rounded-lg (12px)`);
|
|
}
|
|
}
|
|
|
|
expect(tooSharp.length,
|
|
`${tooSharp.length} inputs avec border-radius trop petit:\n${tooSharp.map(i => `input[type="${i.type}"] "${i.name}": ${i.borderRadius}`).join('\n')}`
|
|
).toBe(0);
|
|
});
|
|
});
|