veza/tests/e2e/design-system.spec.ts

160 lines
6.1 KiB
TypeScript
Raw Normal View History

import { test, expect } from '@playwright/test';
import { navigateTo, assertPageLoads } from './helpers';
const PAGE_PATH = '/design-system';
test.describe('Démo du design system (/design-system)', () => {
test.describe('Chargement & Rendu', () => {
test('la page se charge sans crash', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
await expect(page.locator('main#main-content')).toBeVisible();
});
test('pas d\'erreurs JS dans la console (hors 401 auth)', async ({ page }) => {
const errors = await assertPageLoads(page, PAGE_PATH);
const realErrors = errors.filter(
(e) => !e.includes('/api/v1/auth/me') && !e.includes('401'),
);
expect(realErrors).toHaveLength(0);
});
test('tous les éléments visuels sont présents', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
await expect(page.locator('h1')).toBeVisible();
await expect(page.locator('h1')).not.toBeEmpty();
// Subtitle paragraph
await expect(page.locator('header p')).toBeVisible();
// Under construction message
await expect(page.locator('section p')).toBeVisible();
// Back to home link
await expect(page.locator('a[href="/"]')).toBeVisible();
});
test('document.title est mis à jour', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
await expect(page).toHaveTitle(/Design System/);
});
});
test.describe('Accessibilité', () => {
test('le skip-to-content fonctionne (cible #main-content existe)', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
const skipLink = page.locator('a[href="#main-content"]');
await expect(skipLink).toBeAttached();
const mainContent = page.locator('#main-content');
await expect(mainContent).toBeAttached();
});
test('landmark <main> est présent', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
const main = page.locator('main');
await expect(main).toBeAttached();
await expect(main).toHaveAttribute('id', 'main-content');
});
test('hiérarchie des headings correcte (h1 unique)', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
const h1s = page.locator('main h1');
await expect(h1s).toHaveCount(1);
});
test('navigation au clavier logique (Tab order)', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
// First Tab → skip link
await page.keyboard.press('Tab');
const skipLink = page.locator('a[href="#main-content"]');
await expect(skipLink).toBeFocused();
// Next Tab → "Back to home" link
await page.keyboard.press('Tab');
const backLink = page.locator('a[href="/"]');
await expect(backLink).toBeFocused();
});
test('le lien "Back to home" a un texte accessible', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
const backLink = page.locator('a[href="/"]');
const text = await backLink.textContent();
expect(text?.trim().length).toBeGreaterThan(0);
});
});
test.describe('i18n', () => {
test('pas de clés i18n brutes affichées', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
const bodyText = await page.locator('main').textContent();
// i18n keys look like "designSystem.title" — should not appear as rendered text
expect(bodyText).not.toMatch(/designSystem\./);
});
test('texte cohérent — pas de mélange avec du texte hardcodé', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
const bodyText = await page.locator('main').textContent();
// The old hardcoded text should not appear
expect(bodyText).not.toContain('Component under construction.');
});
});
test.describe('Responsive', () => {
test('mobile 375px — pas d\'overflow horizontal', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 812 });
await navigateTo(page, PAGE_PATH);
const hasOverflow = await page.evaluate(
() => document.documentElement.scrollWidth > document.documentElement.clientWidth,
);
expect(hasOverflow).toBe(false);
});
test('tablet 768px — pas d\'overflow horizontal', async ({ page }) => {
await page.setViewportSize({ width: 768, height: 1024 });
await navigateTo(page, PAGE_PATH);
const hasOverflow = await page.evaluate(
() => document.documentElement.scrollWidth > document.documentElement.clientWidth,
);
expect(hasOverflow).toBe(false);
});
test('desktop 1280px — layout correct', async ({ page }) => {
await page.setViewportSize({ width: 1280, height: 800 });
await navigateTo(page, PAGE_PATH);
const main = page.locator('main');
await expect(main).toBeVisible();
const hasOverflow = await page.evaluate(
() => document.documentElement.scrollWidth > document.documentElement.clientWidth,
);
expect(hasOverflow).toBe(false);
});
});
test.describe('Régression', () => {
test('BUG #1 — #main-content existe pour le skip link', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
await expect(page.locator('#main-content')).toBeAttached();
});
test('BUG #2 — landmark <main> est présent', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
await expect(page.locator('main')).toBeAttached();
});
test('BUG #3 — data-testid est présent', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
await expect(page.locator('[data-testid="design-system-page"]')).toBeAttached();
});
test('BUG #4 — texte traduit via i18n (pas hardcodé)', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
const h1 = await page.locator('h1').textContent();
// h1 should have actual translated content, not a raw key
expect(h1).toBeTruthy();
expect(h1).not.toMatch(/^designSystem\./);
});
test('BUG #5 — document.title est mis à jour', async ({ page }) => {
await navigateTo(page, PAGE_PATH);
const title = await page.title();
expect(title).toContain('Design System');
expect(title).not.toBe('Veza - Plateforme de streaming musical');
});
});
});