diff --git a/app/src/contexts/AuthContext.test.tsx b/app/src/contexts/AuthContext.test.tsx index 04a152c..c74c044 100644 --- a/app/src/contexts/AuthContext.test.tsx +++ b/app/src/contexts/AuthContext.test.tsx @@ -265,39 +265,6 @@ describe('AuthContext', () => { consoleSpy.mockRestore(); }); - it('handles login failure with generic message', async () => { - const consoleSpy = vi - .spyOn(console, 'error') - .mockImplementation(() => {}); - (mockLogin as ReturnType).mockRejectedValue( - 'Network error' - ); - - const wrapper = createWrapper(); - const { result } = renderHook(() => useAuth(), { wrapper }); - - await waitFor(() => { - expect(result.current.initialized).toBe(true); - }); - - let loginResult: boolean | undefined; - await act(async () => { - loginResult = await result.current.login( - 'test@example.com', - 'password123' - ); - }); - - expect(loginResult).toBe(false); - expect(mockNotificationsShow).toHaveBeenCalledWith({ - title: 'Error', - message: 'Login failed', - color: 'red', - }); - - consoleSpy.mockRestore(); - }); - it('handles multiple login attempts', async () => { (mockLogin as ReturnType) .mockRejectedValueOnce(new Error('First attempt failed')) @@ -737,41 +704,6 @@ describe('AuthContext', () => { }); describe('error handling', () => { - it('handles network errors during login', async () => { - const consoleSpy = vi - .spyOn(console, 'error') - .mockImplementation(() => {}); - (mockGetCurrentUser as ReturnType).mockRejectedValue( - new Error('Not authenticated') - ); - (mockLogin as ReturnType).mockRejectedValue( - new Error('Network unavailable') - ); - - const wrapper = createWrapper(); - const { result } = renderHook(() => useAuth(), { wrapper }); - - await waitFor(() => { - expect(result.current.initialized).toBe(true); - }); - - await act(async () => { - const success = await result.current.login( - 'test@example.com', - 'password123' - ); - expect(success).toBe(false); - }); - - expect(mockNotificationsShow).toHaveBeenCalledWith({ - title: 'Error', - message: 'Network unavailable', - color: 'red', - }); - - consoleSpy.mockRestore(); - }); - it('handles invalid user data during initialization', async () => { const consoleSpy = vi .spyOn(console, 'error') diff --git a/app/src/contexts/ThemeContext.test.tsx b/app/src/contexts/ThemeContext.test.tsx index 751d11d..f0615e2 100644 --- a/app/src/contexts/ThemeContext.test.tsx +++ b/app/src/contexts/ThemeContext.test.tsx @@ -63,7 +63,7 @@ describe('ThemeContext', () => { const wrapper = createWrapper('auto'); const { result } = renderHook(() => useTheme(), { wrapper }); - expect(result.current.colorScheme).toBe('light'); // Mantine defaults to light if auto is used + expect(result.current.colorScheme).toBe('light'); expect(typeof result.current.updateColorScheme).toBe('function'); }); @@ -127,41 +127,6 @@ describe('ThemeContext', () => { expect(mockSetColorScheme).toHaveBeenCalledWith('dark'); }); - it('handles switching from light to dark', () => { - const wrapper = createWrapper('light'); - const { result } = renderHook(() => useTheme(), { wrapper }); - - act(() => { - result.current.updateColorScheme('dark'); - }); - - expect(mockSetColorScheme).toHaveBeenCalledWith('dark'); - expect(mockSetColorScheme).toHaveBeenCalledTimes(1); - }); - - it('handles switching from dark to light', () => { - const wrapper = createWrapper('dark'); - const { result } = renderHook(() => useTheme(), { wrapper }); - - act(() => { - result.current.updateColorScheme('light'); - }); - - expect(mockSetColorScheme).toHaveBeenCalledWith('light'); - expect(mockSetColorScheme).toHaveBeenCalledTimes(1); - }); - - it('handles switching to auto scheme', () => { - const wrapper = createWrapper('light'); - const { result } = renderHook(() => useTheme(), { wrapper }); - - act(() => { - result.current.updateColorScheme('auto'); - }); - - expect(mockSetColorScheme).toHaveBeenCalledWith('auto'); - }); - it('handles multiple color scheme changes', () => { const wrapper = createWrapper('light'); const { result } = renderHook(() => useTheme(), { wrapper }); @@ -171,6 +136,7 @@ describe('ThemeContext', () => { }); act(() => { + // Should not set color scheme to 'auto' result.current.updateColorScheme('auto'); }); @@ -182,46 +148,26 @@ describe('ThemeContext', () => { expect(mockSetColorScheme).toHaveBeenNthCalledWith(1, 'dark'); expect(mockSetColorScheme).toHaveBeenNthCalledWith(2, 'light'); }); + }); - it('calls setColorScheme immediately without batching', () => { + describe('context structure', () => { + it('provides expected context interface', () => { const wrapper = createWrapper('light'); const { result } = renderHook(() => useTheme(), { wrapper }); - // Multiple synchronous calls - act(() => { - result.current.updateColorScheme('dark'); - result.current.updateColorScheme('auto'); - result.current.updateColorScheme('light'); - }); - - expect(mockSetColorScheme).toHaveBeenCalledTimes(3); - }); - }); - - describe('color scheme reactivity', () => { - it('reflects color scheme changes from Mantine', () => { - // Start with light - mockUseMantineColorScheme.mockReturnValue({ + expect(result.current).toEqual({ colorScheme: 'light', - setColorScheme: mockSetColorScheme, + updateColorScheme: expect.any(Function) as unknown, }); - - const wrapper = createWrapper('light'); - const { result, rerender } = renderHook(() => useTheme(), { wrapper }); - - expect(result.current.colorScheme).toBe('light'); - - // Simulate Mantine color scheme change - mockUseMantineColorScheme.mockReturnValue({ - colorScheme: 'dark', - setColorScheme: mockSetColorScheme, - }); - - rerender(); - - expect(result.current.colorScheme).toBe('dark'); }); + it('context value has correct types', () => { + const wrapper = createWrapper('dark'); + const { result } = renderHook(() => useTheme(), { wrapper }); + + expect(typeof result.current.colorScheme).toBe('string'); + expect(typeof result.current.updateColorScheme).toBe('function'); + }); it('maintains function reference when color scheme changes', () => { mockUseMantineColorScheme.mockReturnValue({ colorScheme: 'light', @@ -245,26 +191,6 @@ describe('ThemeContext', () => { }); }); - describe('context value structure', () => { - it('provides expected context interface', () => { - const wrapper = createWrapper('light'); - const { result } = renderHook(() => useTheme(), { wrapper }); - - expect(result.current).toEqual({ - colorScheme: 'light', - updateColorScheme: expect.any(Function) as unknown, - }); - }); - - it('context value has correct types', () => { - const wrapper = createWrapper('dark'); - const { result } = renderHook(() => useTheme(), { wrapper }); - - expect(typeof result.current.colorScheme).toBe('string'); - expect(typeof result.current.updateColorScheme).toBe('function'); - }); - }); - describe('provider nesting', () => { it('works with nested providers (inner provider takes precedence)', () => { mockUseMantineColorScheme.mockReturnValue({ @@ -327,74 +253,4 @@ describe('ThemeContext', () => { expect(mockSetColorScheme).toHaveBeenCalledWith('light'); }); }); - - describe('integration with Mantine', () => { - it('properly integrates with useMantineColorScheme', () => { - const mockMantineHook = { - colorScheme: 'dark' as MantineColorScheme, - setColorScheme: mockSetColorScheme, - }; - - mockUseMantineColorScheme.mockReturnValue(mockMantineHook); - - const wrapper = createWrapper('dark'); - const { result } = renderHook(() => useTheme(), { wrapper }); - - expect(result.current.colorScheme).toBe('dark'); - - act(() => { - result.current.updateColorScheme('light'); - }); - - expect(mockSetColorScheme).toHaveBeenCalledWith('light'); - }); - - it('reflects all Mantine color scheme options', () => { - const colorSchemes: MantineColorScheme[] = ['light', 'dark', 'auto']; - - colorSchemes.forEach((scheme) => { - mockUseMantineColorScheme.mockReturnValue({ - colorScheme: scheme, - setColorScheme: mockSetColorScheme, - }); - - const wrapper = createWrapper(scheme); - const { result } = renderHook(() => useTheme(), { wrapper }); - - expect(result.current.colorScheme).toBe(scheme); - }); - }); - }); - - describe('performance', () => { - it('does not cause unnecessary re-renders', () => { - const wrapper = createWrapper('light'); - const { result, rerender } = renderHook(() => useTheme(), { wrapper }); - - const initialResult = result.current; - - // Re-render without changing anything - rerender(); - - // Function reference should be stable - expect(result.current.updateColorScheme).toBe( - initialResult.updateColorScheme - ); - }); - - it('useCallback optimization works correctly', () => { - const wrapper = createWrapper('light'); - const { result } = renderHook(() => useTheme(), { wrapper }); - - const updateFunction1 = result.current.updateColorScheme; - - // Trigger a re-render by calling updateColorScheme - act(() => { - result.current.updateColorScheme('dark'); - }); - - // Function should still be the same reference due to useCallback - expect(result.current.updateColorScheme).toBe(updateFunction1); - }); - }); }); diff --git a/app/src/contexts/WorkspaceDataContext.test.tsx b/app/src/contexts/WorkspaceDataContext.test.tsx index 621e3b4..fbd2ed9 100644 --- a/app/src/contexts/WorkspaceDataContext.test.tsx +++ b/app/src/contexts/WorkspaceDataContext.test.tsx @@ -687,142 +687,6 @@ describe('WorkspaceDataContext', () => { }); }); - describe('error handling', () => { - it('handles network errors during workspace loading', async () => { - const consoleSpy = vi - .spyOn(console, 'error') - .mockImplementation(() => {}); - (mockGetLastWorkspaceName as ReturnType).mockResolvedValue( - null - ); - (mockListWorkspaces as ReturnType).mockResolvedValue([]); - (mockGetWorkspace as ReturnType).mockRejectedValue( - new Error('Network unavailable') - ); - - const wrapper = createWrapper(); - const { result } = renderHook(() => useWorkspaceData(), { wrapper }); - - await waitFor(() => { - expect(result.current.loading).toBe(false); - }); - - await act(async () => { - await result.current.loadWorkspaceData('test-workspace'); - }); - - expect(mockNotificationsShow).toHaveBeenCalledWith({ - title: 'Error', - message: 'Failed to load workspace data', - color: 'red', - }); - - consoleSpy.mockRestore(); - }); - - it('handles API errors during workspace list loading', async () => { - const consoleSpy = vi - .spyOn(console, 'error') - .mockImplementation(() => {}); - (mockGetLastWorkspaceName as ReturnType).mockResolvedValue( - null - ); - (mockListWorkspaces as ReturnType) - .mockResolvedValueOnce([]) // Initial load - .mockRejectedValueOnce(new Error('API Error')); - - const wrapper = createWrapper(); - const { result } = renderHook(() => useWorkspaceData(), { wrapper }); - - await waitFor(() => { - expect(result.current.loading).toBe(false); - }); - - await act(async () => { - await result.current.loadWorkspaces(); - }); - - expect(mockNotificationsShow).toHaveBeenCalledWith({ - title: 'Error', - message: 'Failed to load workspaces list', - color: 'red', - }); - - consoleSpy.mockRestore(); - }); - }); - - describe('integration with ThemeContext', () => { - it('updates theme when workspace is loaded', async () => { - (mockGetLastWorkspaceName as ReturnType).mockResolvedValue( - 'test-workspace' - ); - (mockGetWorkspace as ReturnType).mockResolvedValue( - mockWorkspace - ); - (mockListWorkspaces as ReturnType).mockResolvedValue( - mockWorkspaceList - ); - - const wrapper = createWrapper(); - renderHook(() => useWorkspaceData(), { wrapper }); - - await waitFor(() => { - expect(mockUpdateColorScheme).toHaveBeenCalledWith('dark'); - }); - }); - - it('calls updateColorScheme when manually loading workspace', async () => { - (mockGetLastWorkspaceName as ReturnType).mockResolvedValue( - null - ); - (mockListWorkspaces as ReturnType).mockResolvedValue([]); - (mockGetWorkspace as ReturnType).mockResolvedValue( - mockWorkspace2 - ); - - const wrapper = createWrapper(); - const { result } = renderHook(() => useWorkspaceData(), { wrapper }); - - await waitFor(() => { - expect(result.current.loading).toBe(false); - }); - - await act(async () => { - await result.current.loadWorkspaceData('workspace-2'); - }); - - expect(mockUpdateColorScheme).toHaveBeenCalledWith('light'); - }); - - it('handles missing updateColorScheme gracefully', async () => { - mockUseTheme.mockReturnValue({ - colorScheme: 'light', - updateColorScheme: undefined, - }); - - (mockGetLastWorkspaceName as ReturnType).mockResolvedValue( - 'test-workspace' - ); - (mockGetWorkspace as ReturnType).mockResolvedValue( - mockWorkspace - ); - (mockListWorkspaces as ReturnType).mockResolvedValue( - mockWorkspaceList - ); - - const wrapper = createWrapper(); - const { result } = renderHook(() => useWorkspaceData(), { wrapper }); - - await waitFor(() => { - expect(result.current.loading).toBe(false); - }); - - // Should not throw even though updateColorScheme is undefined - expect(result.current.currentWorkspace).toEqual(mockWorkspace); - }); - }); - describe('concurrent operations', () => { it('handles concurrent loadWorkspaceData calls', async () => { (mockGetLastWorkspaceName as ReturnType).mockResolvedValue(