veza/tests/e2e/audit/interaction/01-dropdowns-menus.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

112 lines
4.2 KiB
TypeScript

import { test, expect } from '@chromatic-com/playwright';
import { loginViaAPI, navigateTo } from '../helpers';
import { testDropdown } from '../helpers/interaction-helpers';
import { TEST_USERS } from '../design-tokens';
test.describe('DROPDOWNS & MENUS — Tous s\'ouvrent, se ferment, et ne débordent pas', () => {
test.beforeEach(async ({ page }) => {
await loginViaAPI(page, TEST_USERS.listener.email, TEST_USERS.listener.password);
});
test('Sidebar — les dropdowns de navigation fonctionnent', async ({ page }) => {
await navigateTo(page, '/dashboard');
// Chercher les triggers de dropdown dans le sidebar
const sidebar = page.locator('[data-testid="app-sidebar"]');
if (!await sidebar.isVisible({ timeout: 5_000 }).catch(() => false)) return;
const dropdownTriggers = await sidebar.locator('button[aria-expanded], button[aria-haspopup]').all();
for (const trigger of dropdownTriggers.slice(0, 5)) {
try {
const text = await trigger.textContent().then(t => t?.trim().slice(0, 20) || '').catch(() => '');
console.log(`[DROPDOWN] Testing sidebar trigger: "${text}"`);
await trigger.click();
await page.waitForTimeout(300);
// Vérifier qu'un menu apparaît
const expanded = await trigger.getAttribute('aria-expanded');
if (expanded === 'true') {
// Escape ferme
await page.keyboard.press('Escape');
await page.waitForTimeout(200);
const closedAfterEscape = await trigger.getAttribute('aria-expanded');
expect(closedAfterEscape, `Dropdown "${text}" ne se ferme pas avec Escape`).not.toBe('true');
}
} catch {
/* skip detached elements */
}
}
});
test('Settings — les select/dropdown de préférences fonctionnent', async ({ page }) => {
await navigateTo(page, '/settings');
// Chercher les selects et dropdowns
const selects = await page.locator('select:visible, [role="combobox"]:visible, [role="listbox"]:visible').all();
for (const select of selects.slice(0, 5)) {
try {
const box = await select.boundingBox();
if (!box) continue;
await select.click();
await page.waitForTimeout(300);
// Vérifier que les options sont affichées
const options = page.locator('[role="option"]:visible, option:visible');
const optionCount = await options.count().catch(() => 0);
console.log(`[SELECT] ${optionCount} options visibles`);
// Fermer
await page.keyboard.press('Escape');
await page.waitForTimeout(200);
} catch {
/* skip */
}
}
});
test('Header — le menu utilisateur fonctionne', async ({ page }) => {
await navigateTo(page, '/dashboard');
// Chercher le menu utilisateur dans le header
const userMenu = page.locator('header button[aria-haspopup], header [data-testid*="user-menu"], header [data-testid*="profile"]').first();
if (!await userMenu.isVisible({ timeout: 5_000 }).catch(() => false)) {
console.log('[DROPDOWN] Pas de menu utilisateur trouvé dans le header');
return;
}
await userMenu.click();
await page.waitForTimeout(400);
const menuContent = page.locator('[role="menu"]:visible, [role="dialog"]:visible').first();
const menuVisible = await menuContent.isVisible().catch(() => false);
if (menuVisible) {
// Escape ferme
await page.keyboard.press('Escape');
await page.waitForTimeout(200);
const closed = !(await menuContent.isVisible().catch(() => false));
expect(closed, 'Le menu utilisateur ne se ferme pas avec Escape').toBe(true);
}
});
test('Discover — les filtres/genre buttons fonctionnent', async ({ page }) => {
await navigateTo(page, '/discover');
// Les boutons de genre sont des boutons qui filtre les tracks
const genreButtons = await page.locator('button').filter({ has: page.locator('.font-heading') }).all();
if (genreButtons.length > 0) {
const firstGenre = genreButtons[0];
await firstGenre.click();
await page.waitForTimeout(1_000);
// Après le clic, la page devrait afficher des tracks ou un état vide
const body = await page.textContent('body');
expect(body).not.toMatch(/500|Internal Server Error/i);
}
});
});