2025-12-03 21:56:50 +00:00
|
|
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
|
|
|
import { useAuthStore } from '@/stores/auth';
|
|
|
|
|
import { useUIStore } from '@/stores/ui';
|
|
|
|
|
import { useChatStore } from '@/stores/chat';
|
|
|
|
|
import { useLibraryStore } from '@/stores/library';
|
|
|
|
|
import { usePlayerStore } from '@/stores/player';
|
|
|
|
|
|
|
|
|
|
// Mock localStorage
|
|
|
|
|
const localStorageMock = {
|
|
|
|
|
getItem: vi.fn(),
|
|
|
|
|
setItem: vi.fn(),
|
|
|
|
|
removeItem: vi.fn(),
|
|
|
|
|
clear: vi.fn(),
|
|
|
|
|
};
|
|
|
|
|
Object.defineProperty(window, 'localStorage', {
|
|
|
|
|
value: localStorageMock,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('Zustand Stores', () => {
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
// Reset stores before each test
|
|
|
|
|
useAuthStore.getState().logout();
|
|
|
|
|
useUIStore.getState().clearNotifications();
|
|
|
|
|
useChatStore.getState().setConnected(false);
|
|
|
|
|
useLibraryStore.getState().clearItems();
|
|
|
|
|
usePlayerStore.getState().clearQueue();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('Auth Store', () => {
|
|
|
|
|
it('should have initial state', () => {
|
|
|
|
|
const state = useAuthStore.getState();
|
|
|
|
|
expect(state.user).toBeNull();
|
|
|
|
|
expect(state.isAuthenticated).toBe(false);
|
|
|
|
|
// isLoading peut être true si le store est en cours de rehydration
|
|
|
|
|
expect(typeof state.isLoading).toBe('boolean');
|
|
|
|
|
expect(state.error).toBeNull();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle login action', () => {
|
|
|
|
|
const { login } = useAuthStore.getState();
|
|
|
|
|
expect(typeof login).toBe('function');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle logout action', () => {
|
|
|
|
|
const { logout } = useAuthStore.getState();
|
|
|
|
|
expect(typeof logout).toBe('function');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle clearError action', () => {
|
|
|
|
|
const { clearError } = useAuthStore.getState();
|
|
|
|
|
expect(typeof clearError).toBe('function');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should set user and authentication state on login', () => {
|
|
|
|
|
const mockUser = {
|
|
|
|
|
id: 1,
|
|
|
|
|
username: 'testuser',
|
|
|
|
|
email: 'test@example.com',
|
|
|
|
|
first_name: 'Test',
|
|
|
|
|
last_name: 'User',
|
|
|
|
|
role: 'user' as const,
|
|
|
|
|
is_active: true,
|
|
|
|
|
is_verified: true,
|
|
|
|
|
created_at: '2024-01-01T00:00:00Z',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Mock the login function to simulate successful login
|
|
|
|
|
vi.spyOn(useAuthStore.getState(), 'login').mockImplementation(
|
|
|
|
|
async () => {
|
|
|
|
|
useAuthStore.setState({
|
|
|
|
|
user: mockUser,
|
|
|
|
|
isAuthenticated: true,
|
|
|
|
|
isLoading: false,
|
|
|
|
|
error: null,
|
|
|
|
|
});
|
2025-12-13 02:34:34 +00:00
|
|
|
},
|
2025-12-03 21:56:50 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
expect(useAuthStore.getState().isAuthenticated).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should clear user and authentication state on logout', () => {
|
|
|
|
|
const { logout } = useAuthStore.getState();
|
|
|
|
|
|
|
|
|
|
// Set initial state
|
|
|
|
|
useAuthStore.setState({
|
|
|
|
|
user: { id: 1, username: 'test', email: 'test@example.com' } as any,
|
|
|
|
|
isAuthenticated: true,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
logout();
|
|
|
|
|
|
|
|
|
|
const state = useAuthStore.getState();
|
|
|
|
|
expect(state.user).toBeNull();
|
|
|
|
|
expect(state.isAuthenticated).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('UI Store', () => {
|
|
|
|
|
it('should have 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([]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle theme changes', () => {
|
|
|
|
|
const { setTheme } = useUIStore.getState();
|
|
|
|
|
setTheme('dark');
|
|
|
|
|
expect(useUIStore.getState().theme).toBe('dark');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle language changes', () => {
|
|
|
|
|
const { setLanguage } = useUIStore.getState();
|
|
|
|
|
setLanguage('fr');
|
|
|
|
|
expect(useUIStore.getState().language).toBe('fr');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle sidebar toggle', () => {
|
|
|
|
|
const { setSidebarOpen } = useUIStore.getState();
|
|
|
|
|
setSidebarOpen(false);
|
|
|
|
|
expect(useUIStore.getState().sidebarOpen).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('Chat Store', () => {
|
|
|
|
|
it('should have initial state', () => {
|
|
|
|
|
const state = useChatStore.getState();
|
|
|
|
|
expect(state.conversations).toEqual([]);
|
|
|
|
|
expect(state.currentConversation).toBeNull();
|
|
|
|
|
expect(state.messages).toEqual({});
|
|
|
|
|
expect(state.typingUsers).toEqual({});
|
|
|
|
|
expect(state.isConnected).toBe(false);
|
|
|
|
|
expect(state.isLoading).toBe(false);
|
|
|
|
|
expect(state.error).toBeNull();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle conversation actions', () => {
|
|
|
|
|
const { setConversations, setCurrentConversation } =
|
|
|
|
|
useChatStore.getState();
|
|
|
|
|
expect(typeof setConversations).toBe('function');
|
|
|
|
|
expect(typeof setCurrentConversation).toBe('function');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle message actions', () => {
|
|
|
|
|
const { addMessage, sendMessage } = useChatStore.getState();
|
|
|
|
|
expect(typeof addMessage).toBe('function');
|
|
|
|
|
expect(typeof sendMessage).toBe('function');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('Library Store', () => {
|
|
|
|
|
it('should have initial state', () => {
|
|
|
|
|
const state = useLibraryStore.getState();
|
|
|
|
|
expect(state.items).toEqual([]);
|
|
|
|
|
expect(state.favorites).toEqual([]);
|
|
|
|
|
expect(state.isLoading).toBe(false);
|
|
|
|
|
expect(state.error).toBeNull();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle library actions', () => {
|
|
|
|
|
const { fetchItems, uploadFile, toggleFavorite } =
|
|
|
|
|
useLibraryStore.getState();
|
|
|
|
|
expect(typeof fetchItems).toBe('function');
|
|
|
|
|
expect(typeof uploadFile).toBe('function');
|
|
|
|
|
expect(typeof toggleFavorite).toBe('function');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('Player Store', () => {
|
|
|
|
|
it('should have initial state', () => {
|
|
|
|
|
const state = usePlayerStore.getState();
|
|
|
|
|
expect(state.currentTrack).toBeNull();
|
|
|
|
|
expect(state.isPlaying).toBe(false);
|
|
|
|
|
expect(state.currentTime).toBe(0);
|
|
|
|
|
expect(state.duration).toBe(0);
|
|
|
|
|
expect(state.volume).toBe(100);
|
|
|
|
|
expect(state.muted).toBe(false);
|
|
|
|
|
expect(state.queue).toEqual([]);
|
|
|
|
|
expect(state.currentIndex).toBe(-1);
|
|
|
|
|
expect(state.repeat).toBe('off');
|
|
|
|
|
expect(state.shuffle).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle play action', () => {
|
|
|
|
|
const { play } = usePlayerStore.getState();
|
|
|
|
|
const mockTrack = {
|
|
|
|
|
id: '1',
|
|
|
|
|
title: 'Test Track',
|
|
|
|
|
artist: 'Test Artist',
|
|
|
|
|
duration: 180,
|
|
|
|
|
url: 'https://example.com/track.mp3',
|
|
|
|
|
} as any;
|
2025-12-13 02:34:34 +00:00
|
|
|
|
2025-12-03 21:56:50 +00:00
|
|
|
play(mockTrack);
|
|
|
|
|
const state = usePlayerStore.getState();
|
|
|
|
|
expect(state.currentTrack).toEqual(mockTrack);
|
|
|
|
|
expect(state.isPlaying).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle pause action', () => {
|
|
|
|
|
const { pause } = usePlayerStore.getState();
|
|
|
|
|
pause();
|
|
|
|
|
expect(usePlayerStore.getState().isPlaying).toBe(false);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle resume action', () => {
|
|
|
|
|
const { resume } = usePlayerStore.getState();
|
|
|
|
|
resume();
|
|
|
|
|
expect(usePlayerStore.getState().isPlaying).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle volume changes', () => {
|
|
|
|
|
const { setVolume } = usePlayerStore.getState();
|
|
|
|
|
setVolume(50);
|
|
|
|
|
expect(usePlayerStore.getState().volume).toBe(50);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle toggle mute', () => {
|
|
|
|
|
const { toggleMute } = usePlayerStore.getState();
|
|
|
|
|
const initialMuted = usePlayerStore.getState().muted;
|
|
|
|
|
toggleMute();
|
|
|
|
|
expect(usePlayerStore.getState().muted).toBe(!initialMuted);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle add to queue', () => {
|
|
|
|
|
const { addToQueue } = usePlayerStore.getState();
|
|
|
|
|
const mockTrack = {
|
|
|
|
|
id: '1',
|
|
|
|
|
title: 'Test Track',
|
|
|
|
|
} as any;
|
2025-12-13 02:34:34 +00:00
|
|
|
|
2025-12-03 21:56:50 +00:00
|
|
|
addToQueue(mockTrack);
|
|
|
|
|
const state = usePlayerStore.getState();
|
|
|
|
|
expect(state.queue).toHaveLength(1);
|
|
|
|
|
expect(state.queue[0]).toEqual(mockTrack);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle clear queue', () => {
|
|
|
|
|
const { addToQueue, clearQueue } = usePlayerStore.getState();
|
|
|
|
|
const mockTrack = { id: '1' } as any;
|
2025-12-13 02:34:34 +00:00
|
|
|
|
2025-12-03 21:56:50 +00:00
|
|
|
addToQueue(mockTrack);
|
|
|
|
|
clearQueue();
|
2025-12-13 02:34:34 +00:00
|
|
|
|
2025-12-03 21:56:50 +00:00
|
|
|
const state = usePlayerStore.getState();
|
|
|
|
|
expect(state.queue).toEqual([]);
|
|
|
|
|
expect(state.currentIndex).toBe(-1);
|
|
|
|
|
expect(state.currentTrack).toBeNull();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle toggle shuffle', () => {
|
|
|
|
|
const { toggleShuffle } = usePlayerStore.getState();
|
|
|
|
|
const initialShuffle = usePlayerStore.getState().shuffle;
|
|
|
|
|
toggleShuffle();
|
|
|
|
|
expect(usePlayerStore.getState().shuffle).toBe(!initialShuffle);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle set repeat', () => {
|
|
|
|
|
const { setRepeat } = usePlayerStore.getState();
|
|
|
|
|
setRepeat('playlist');
|
|
|
|
|
expect(usePlayerStore.getState().repeat).toBe('playlist');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|