veza/apps/web/src/components/layout/DashboardLayout.test.tsx
senke 39b2b642d2 feat(web): UI premium Discord/Spotify-like — tokens, shadows, focus, layout
Plan UI premium 6–8 semaines (design system, shell, Storybook, a11y):

- Design system: DESIGN_TOKENS.md, APP_SHELL.md, FULL_LAYOUT_PAGE.md. Single source
  for layout/shell (index.css), shadows (design-system.css), durations/easing.
- Tokens: shadow-cover-depth, shadow-gold-glow, shadow-fab-glow; layout max-height
  (max-h-layout-drawer, max-h-layout-panel, max-h-layout-list). All duration-200/300/500
  replaced by --duration-fast/normal/slow. Arbitrary shadows replaced by token classes.
- Shell & player: Sidebar, Header, GlobalPlayer, MiniPlayer, PlayerQueue, PlayerControls,
  AudioPlayer use tokens; focus-visible on Sidebar, PlayerQueue, DropdownMenuTrigger/Item,
  TabsTrigger. Typography: text-[10px]/[9px] → text-xs where applicable.
- ESLint: no-restricted-syntax (warn) for w-/h-/rounded-/shadow-/text-/spacing arbitrary.
- Scripts: report-arbitrary-values.mjs, capture/compare/generate visual; visual-complete.spec.ts.
- Stories full layout: Dashboard, Playlists, Library, Settings, Profile in DashboardLayout.stories.
- .cursorrules + README: DESIGN_TOKENS, APP_SHELL, visual commands, no arbitrary without justification.
- apps/web/.gitignore: e2e test artifacts (test-results-visual, playwright-report-visual).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-08 17:15:58 +01:00

150 lines
3.8 KiB
TypeScript

import { render, screen } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { BrowserRouter } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ToastProvider } from '@/components/feedback/ToastProvider';
import { DashboardLayout } from './DashboardLayout';
// Mock useTranslation
vi.mock('@/hooks/useTranslation', () => ({
useTranslation: () => ({
t: (key: string) => key,
i18n: { changeLanguage: vi.fn() },
language: 'fr',
changeLanguage: vi.fn(),
isReady: true,
}),
}));
// Mock useAuthStore
vi.mock('@/features/auth/store/authStore', () => ({
useAuthStore: () => ({
user: { id: '1', username: 'testuser', email: 'test@example.com' },
isAuthenticated: true,
logout: vi.fn(),
}),
}));
// Mock useUIStore
vi.mock('@/stores/ui', () => ({
useUIStore: () => ({
sidebarOpen: true,
setSidebarOpen: vi.fn(),
theme: 'light',
setTheme: vi.fn(),
}),
}));
const createTestQueryClient = () =>
new QueryClient({
defaultOptions: {
queries: { retry: false },
mutations: { retry: false },
},
});
const TestWrapper = ({ children }: { children: React.ReactNode }) => {
const queryClient = createTestQueryClient();
return (
<QueryClientProvider client={queryClient}>
<BrowserRouter>
<ToastProvider>{children}</ToastProvider>
</BrowserRouter>
</QueryClientProvider>
);
};
describe('DashboardLayout Component', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('renders layout with sidebar and header', () => {
render(
<TestWrapper>
<DashboardLayout>
<div>Dashboard Content</div>
</DashboardLayout>
</TestWrapper>,
);
// Vérifier que le layout est présent
const layout = screen
.getByText('Dashboard Content')
.closest('.flex.h-screen');
expect(layout).toBeInTheDocument();
});
it('renders children content in main section', () => {
render(
<TestWrapper>
<DashboardLayout>
<div>Dashboard Content</div>
</DashboardLayout>
</TestWrapper>,
);
expect(screen.getByText('Dashboard Content')).toBeInTheDocument();
});
it('renders Sidebar component', () => {
render(
<TestWrapper>
<DashboardLayout>
<div>Dashboard Content</div>
</DashboardLayout>
</TestWrapper>,
);
// Vérifier que la sidebar est présente (chercher un élément caractéristique)
const sidebar = document.querySelector('aside');
expect(sidebar).toBeInTheDocument();
});
it('renders Header component', () => {
render(
<TestWrapper>
<DashboardLayout>
<div>Dashboard Content</div>
</DashboardLayout>
</TestWrapper>,
);
// Vérifier que le header est présent
const header = document.querySelector('header');
expect(header).toBeInTheDocument();
});
it('has correct layout structure with flex classes', () => {
const { container } = render(
<TestWrapper>
<DashboardLayout>
<div>Dashboard Content</div>
</DashboardLayout>
</TestWrapper>,
);
const layout = container.querySelector('.flex.h-screen');
expect(layout).toBeInTheDocument();
const mainContent = container.querySelector('.flex-1.flex.flex-col');
expect(mainContent).toBeInTheDocument();
const main = container.querySelector('main.flex-1');
expect(main).toBeInTheDocument();
});
it('renders multiple children correctly', () => {
render(
<TestWrapper>
<DashboardLayout>
<div>Child 1</div>
<div>Child 2</div>
</DashboardLayout>
</TestWrapper>,
);
expect(screen.getByText('Child 1')).toBeInTheDocument();
expect(screen.getByText('Child 2')).toBeInTheDocument();
});
});