- 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>
62 lines
2.8 KiB
TypeScript
62 lines
2.8 KiB
TypeScript
import { test, expect } from '@chromatic-com/playwright';
|
|
import { loginViaAPI, navigateTo } from '../helpers';
|
|
import { checkHoverState } from '../helpers/visual-helpers';
|
|
import { TEST_USERS, ROUTES } from '../design-tokens';
|
|
|
|
test.describe('HOVER — Chaque bouton/lien a un feedback visuel au survol', () => {
|
|
const pagesToCheck = [
|
|
{ path: '/login', auth: false, name: 'Login' },
|
|
{ path: '/register', auth: false, name: 'Register' },
|
|
{ path: '/dashboard', auth: true, name: 'Dashboard' },
|
|
{ path: '/discover', auth: true, name: 'Discover' },
|
|
{ path: '/library', auth: true, name: 'Library' },
|
|
{ path: '/settings', auth: true, name: 'Settings' },
|
|
{ path: '/playlists', auth: true, name: 'Playlists' },
|
|
{ path: '/marketplace', auth: true, name: 'Marketplace' },
|
|
{ path: '/feed', auth: true, name: 'Feed' },
|
|
{ path: '/profile', auth: true, name: 'Profile' },
|
|
{ path: '/notifications', auth: true, name: 'Notifications' },
|
|
];
|
|
|
|
for (const p of pagesToCheck) {
|
|
test(`${p.name} (${p.path}) — tous les boutons changent visuellement au hover`, async ({ page }) => {
|
|
if (p.auth) {
|
|
await loginViaAPI(page, TEST_USERS.listener.email, TEST_USERS.listener.password);
|
|
}
|
|
await navigateTo(page, p.path);
|
|
|
|
const buttons = await page.locator('button:visible').all();
|
|
const links = await page.locator('a:visible').all();
|
|
const allInteractive = [...buttons, ...links];
|
|
const issues: string[] = [];
|
|
|
|
for (const btn of allInteractive.slice(0, 30)) {
|
|
try {
|
|
// Skip éléments trop petits ou hors viewport
|
|
const box = await btn.boundingBox();
|
|
if (!box || box.width < 10 || box.height < 10) continue;
|
|
if (box.y < 0 || box.y > 900) continue;
|
|
|
|
const report = await checkHoverState(page, btn);
|
|
if (report.issues.length > 0) {
|
|
issues.push(`"${report.text}" (${report.selector}): ${report.issues.join(', ')}`);
|
|
console.log(`[HOVER ISSUE] "${report.text}"`);
|
|
console.log(` Before: bg=${report.before.bg}, color=${report.before.color}, cursor=${report.before.cursor}`);
|
|
console.log(` After: bg=${report.after.bg}, color=${report.after.color}, cursor=${report.after.cursor}`);
|
|
console.log(` Issues: ${report.issues.join(', ')}`);
|
|
}
|
|
// Reset mouse
|
|
await page.mouse.move(0, 0);
|
|
} catch {
|
|
/* élément détaché — skip */
|
|
}
|
|
}
|
|
|
|
// Tolérance : max 15% de boutons sans hover
|
|
const tolerance = Math.max(3, Math.ceil(allInteractive.length * 0.15));
|
|
expect(issues.length,
|
|
`${issues.length}/${allInteractive.length} bouton(s) sans hover visible sur ${p.path}:\n${issues.join('\n')}`
|
|
).toBeLessThanOrEqual(tolerance);
|
|
});
|
|
}
|
|
});
|