veza/tests/e2e/audit/interaction/06-keyboard-navigation.spec.ts
senke 6fad0ad68d fix: stabilize frontend — 98 TS errors to 0, align API endpoints, optimize bundle
- Fix 98 TypeScript errors across 37 files:
  - Service layer double-unwrapping (subscriptionService, distributionService, gearService)
  - Self-referencing variables in SearchPageResults
  - FeedView/ExploreView .posts→.items alignment
  - useQueueSync Zustand subscribe API
  - AdminAuditLogsView missing interface fields
  - Toast proxy type, interceptor type narrowing
  - 22 unused imports/variables removed
  - 5 storybook mock data fixes

- Align frontend API calls with backend endpoints:
  - Analytics: useAnalyticsView now calls /creator/analytics/dashboard (was /analytics)
  - Chat: chatService uses /conversations (was mock data), WS URL from backend token
  - Dashboard StatsSection: uses real /dashboard API data (was hardcoded zeros)
  - Settings: suppress 2FA toast error when endpoint unavailable

- Fix marketplace products: seed uses 'active' status (was 'published')
- Enrich seed: admin follows all creators (feed has content)

- Optimize bundle: vendor catch-all 793KB→318KB gzip (-60%)
  Split into vendor-charts, vendor-emoji, vendor-swagger, vendor-media, etc.

- Clean repo: remove ~100 orphaned screenshots, audit reports, logs from root

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 21:18:49 +01:00

96 lines
4 KiB
TypeScript

import { test, expect } from '@chromatic-com/playwright';
import { loginViaAPI, navigateTo } from '../helpers';
import { testKeyboardNav } from '../helpers/interaction-helpers';
import { TEST_USERS, ROUTES } from '../design-tokens';
test.describe('KEYBOARD — Tab, Enter, Escape fonctionnent sur tout', () => {
test('Login — le formulaire est entièrement navigable au clavier', async ({ page }) => {
await navigateTo(page, '/login');
// Tab through the form
const { focusOrder, issues } = await testKeyboardNav(page, 10);
// Au moins email, password, submit doivent être focusables
const hasTags = focusOrder.map(f => f.tag);
expect(hasTags, 'Le formulaire de login devrait avoir des tab stops (input, button)').not.toHaveLength(0);
// Enter sur le bouton submit devrait soumettre le formulaire
// (testé indirectement via les tests fonctionnels)
console.log(`[KEYBOARD] Login — ${focusOrder.length} tab stops, ${issues.length} sans focus visible`);
});
test('Dashboard — Escape ferme les éléments ouverts', async ({ page }) => {
await loginViaAPI(page, TEST_USERS.listener.email, TEST_USERS.listener.password);
await navigateTo(page, '/dashboard');
// Vérifier que Escape ne cause pas d'erreur sur une page sans modal ouvert
await page.keyboard.press('Escape');
await page.waitForTimeout(500);
// La page ne devrait pas crasher
const body = await page.textContent('body') || '';
expect(body).not.toMatch(/500|Internal Server Error/i);
});
for (const route of ROUTES.listener.slice(0, 8)) {
test(`${route.name} (${route.path}) — navigation clavier possible`, async ({ page }) => {
await loginViaAPI(page, TEST_USERS.listener.email, TEST_USERS.listener.password);
await navigateTo(page, route.path);
const { focusOrder, totalTabStops } = await testKeyboardNav(page, 15);
console.log(`[KEYBOARD] ${route.path}${totalTabStops} tab stops`);
// Chaque page devrait avoir au moins 1 élément focusable
expect(totalTabStops, `Aucun tab stop sur ${route.path} — la page n'est pas navigable au clavier`).toBeGreaterThan(0);
});
}
test('Enter active les boutons focusés', async ({ page }) => {
await navigateTo(page, '/login');
// Focus sur le bouton submit
const submit = page.getByTestId('login-submit');
await submit.waitFor({ state: 'visible', timeout: 10_000 });
// Tab jusqu'au submit
for (let i = 0; i < 10; i++) {
await page.keyboard.press('Tab');
const focused = await page.evaluate(() => document.activeElement?.getAttribute('data-testid'));
if (focused === 'login-submit') break;
}
// Vérifier que l'élément focusé est bien le submit
const focusedTestId = await page.evaluate(() => document.activeElement?.getAttribute('data-testid'));
console.log(`[KEYBOARD] Focused element: ${focusedTestId}`);
});
test('Space toggle les checkboxes et switches', async ({ page }) => {
await loginViaAPI(page, TEST_USERS.listener.email, TEST_USERS.listener.password);
await navigateTo(page, '/settings');
// Chercher un switch ou checkbox
const toggle = page.locator('[role="switch"]:visible, input[type="checkbox"]:visible').first();
if (!await toggle.isVisible({ timeout: 5_000 }).catch(() => false)) return;
// Capturer l'état initial
const before = await toggle.evaluate(el => {
if (el.getAttribute('role') === 'switch') return el.getAttribute('aria-checked');
return (el as HTMLInputElement).checked ? 'true' : 'false';
});
// Focus + Space
await toggle.focus();
await page.keyboard.press('Space');
await page.waitForTimeout(300);
const after = await toggle.evaluate(el => {
if (el.getAttribute('role') === 'switch') return el.getAttribute('aria-checked');
return (el as HTMLInputElement).checked ? 'true' : 'false';
});
console.log(`[KEYBOARD] Switch/checkbox: ${before}${after}`);
// Le toggle devrait changer d'état (sauf si disabled)
});
});