veza/apps/web/src/stores/ui.test.ts
senke f5eaa0034a [T0-003] fix(frontend): Corriger erreurs TypeScript/React
- Variables non utilisées préfixées avec _
- Badge variants corrigés (outline -> default/secondary)
- Types ApiError corrigés (rate_limit supprimé)
- Logger errors corrigés (LogContext au lieu de Error)
- Types PaginatedResponse corrigés (items au lieu de data)
- Types génériques complexes corrigés (stateCleanup, undoRedo)
- Fichiers .example.ts exclus du typecheck
- Status undefined vérifié dans client.ts

Résultats:
- npm run build  (réussit)
- npm run typecheck  (0 erreurs)
- npm run lint ⚠️ (1521 erreurs restantes - style/variables non utilisées)

Files: 35 fichiers modifiés
Hours: 6 estimated, 6 actual
2026-01-04 01:44:20 +01:00

218 lines
6.4 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
// Mock BroadcastChannel before importing stores
if (typeof global.BroadcastChannel === 'undefined') {
(global as any).BroadcastChannel = class MockBroadcastChannel {
postMessage = vi.fn();
close = vi.fn();
addEventListener = vi.fn();
removeEventListener = vi.fn();
onmessage = null;
};
}
import { useUIStore } from './ui';
// Mock window.matchMedia
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: vi.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: vi.fn(),
removeListener: vi.fn(),
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
dispatchEvent: vi.fn(),
})),
});
// Mock crypto.randomUUID
Object.defineProperty(global, 'crypto', {
value: {
randomUUID: () => `test-uuid-${ Math.random().toString(36).substring(7)}`,
},
});
describe('UIStore', () => {
beforeEach(() => {
// Reset store state
useUIStore.setState({
theme: 'system',
language: 'en',
sidebarOpen: true,
notifications: [],
});
vi.clearAllMocks();
});
describe('Initial State', () => {
it('should have correct initial state', () => {
const state = useUIStore.getState();
expect(state.theme).toBe('system');
expect(state.language).toBe('en');
expect(state.sidebarOpen).toBe(true);
expect(state.notifications).toEqual([]);
});
});
describe('setTheme', () => {
it('should set theme to light', () => {
useUIStore.getState().setTheme('light');
expect(useUIStore.getState().theme).toBe('light');
expect(document.documentElement.classList.contains('dark')).toBe(false);
});
it('should set theme to dark', () => {
useUIStore.getState().setTheme('dark');
expect(useUIStore.getState().theme).toBe('dark');
expect(document.documentElement.classList.contains('dark')).toBe(true);
});
it('should set theme to system', () => {
useUIStore.getState().setTheme('system');
expect(useUIStore.getState().theme).toBe('system');
});
});
describe('setLanguage', () => {
it('should set language to en', () => {
useUIStore.getState().setLanguage('en');
expect(useUIStore.getState().language).toBe('en');
});
it('should set language to fr', () => {
useUIStore.getState().setLanguage('fr');
expect(useUIStore.getState().language).toBe('fr');
});
});
describe('setSidebarOpen', () => {
it('should set sidebar open state', () => {
useUIStore.getState().setSidebarOpen(false);
expect(useUIStore.getState().sidebarOpen).toBe(false);
useUIStore.getState().setSidebarOpen(true);
expect(useUIStore.getState().sidebarOpen).toBe(true);
});
});
describe('addNotification', () => {
it('should add a notification', () => {
useUIStore.getState().addNotification({
type: 'success',
message: 'Test notification',
});
const notifications = useUIStore.getState().notifications;
expect(notifications).toHaveLength(1);
expect(notifications[0].message).toBe('Test notification');
expect(notifications[0].type).toBe('success');
expect(notifications[0].id).toBeDefined();
expect(notifications[0].timestamp).toBeDefined();
});
it('should add multiple notifications', () => {
useUIStore.getState().addNotification({
type: 'info',
message: 'First notification',
});
useUIStore.getState().addNotification({
type: 'warning',
message: 'Second notification',
});
const notifications = useUIStore.getState().notifications;
expect(notifications).toHaveLength(2);
expect(notifications[0].message).toBe('First notification');
expect(notifications[1].message).toBe('Second notification');
});
});
describe('removeNotification', () => {
it('should remove a notification by id', () => {
useUIStore.getState().addNotification({
type: 'success',
message: 'Test notification',
});
const notifications = useUIStore.getState().notifications;
const notificationId = notifications[0].id;
useUIStore.getState().removeNotification(notificationId);
expect(useUIStore.getState().notifications).toHaveLength(0);
});
it('should not remove notification with wrong id', () => {
useUIStore.getState().addNotification({
type: 'success',
message: 'Test notification',
});
useUIStore.getState().removeNotification('wrong-id');
expect(useUIStore.getState().notifications).toHaveLength(1);
});
});
describe('markNotificationAsRead', () => {
it('should mark notification as read', () => {
useUIStore.getState().addNotification({
type: 'info',
message: 'Test notification',
});
const notifications = useUIStore.getState().notifications;
const notificationId = notifications[0].id;
expect(notifications[0].read).toBeUndefined();
useUIStore.getState().markNotificationAsRead(notificationId);
const updatedNotifications = useUIStore.getState().notifications;
expect(updatedNotifications[0].read).toBe(true);
});
it('should not mark other notifications as read', () => {
useUIStore.getState().addNotification({
type: 'info',
message: 'First notification',
});
useUIStore.getState().addNotification({
type: 'warning',
message: 'Second notification',
});
const notifications = useUIStore.getState().notifications;
const firstId = notifications[0].id;
useUIStore.getState().markNotificationAsRead(firstId);
const updatedNotifications = useUIStore.getState().notifications;
expect(updatedNotifications[0].read).toBe(true);
expect(updatedNotifications[1].read).toBeUndefined();
});
});
describe('clearNotifications', () => {
it('should clear all notifications', () => {
useUIStore.getState().addNotification({
type: 'info',
message: 'First notification',
});
useUIStore.getState().addNotification({
type: 'warning',
message: 'Second notification',
});
expect(useUIStore.getState().notifications).toHaveLength(2);
useUIStore.getState().clearNotifications();
expect(useUIStore.getState().notifications).toHaveLength(0);
});
});
});