veza/tests/e2e/design-system.spec.ts
senke 9a4c0d2af4 feat(web): update all features, stories, e2e tests, and auth interceptor
Update auth, playlists, tracks, search, profile, dashboard, player,
settings, and social features. Add e2e audit specs for all major pages.
Update ESLint config, vitest config, and route configuration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 19:16:36 +02:00

159 lines
6.1 KiB
TypeScript

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');
});
});
});