Migrate auth hooks to AuthContext and update tests for compatibility

- Refactored `useIsAuthenticated` and `useCurrentUser` to use `useAuth` from `AuthContext` instead of `useAuthStore`.
- Updated test setups to inject `AuthProvider` with mocked store hooks for improved test isolation and consistency.
- Replaced legacy `useAuthStore` mocks with `AuthContext`-compatible implementations in affected tests.
This commit is contained in:
Felipe Cardoso
2025-11-03 14:27:25 +01:00
parent 532577f36c
commit 852c7eceff
3 changed files with 53 additions and 19 deletions

View File

@@ -22,6 +22,7 @@ import {
} from '../client'; } from '../client';
import { useAuthStore } from '@/lib/stores/authStore'; import { useAuthStore } from '@/lib/stores/authStore';
import type { User } from '@/lib/stores/authStore'; import type { User } from '@/lib/stores/authStore';
import { useAuth } from '@/lib/auth/AuthContext';
import { parseAPIError, getGeneralError } from '../errors'; import { parseAPIError, getGeneralError } from '../errors';
import { isTokenWithUser } from '../types'; import { isTokenWithUser } from '../types';
import config from '@/config/app.config'; import config from '@/config/app.config';
@@ -481,7 +482,7 @@ export function usePasswordChange(onSuccess?: (message: string) => void) {
* @returns boolean indicating authentication status * @returns boolean indicating authentication status
*/ */
export function useIsAuthenticated(): boolean { export function useIsAuthenticated(): boolean {
return useAuthStore((state) => state.isAuthenticated); return useAuth((state) => state.isAuthenticated);
} }
/** /**
@@ -489,7 +490,7 @@ export function useIsAuthenticated(): boolean {
* @returns Current user or null * @returns Current user or null
*/ */
export function useCurrentUser(): User | null { export function useCurrentUser(): User | null {
return useAuthStore((state) => state.user); return useAuth((state) => state.user);
} }
/** /**

View File

@@ -6,12 +6,40 @@
import { render, screen } from '@testing-library/react'; import { render, screen } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import ProfileSettingsPage from '@/app/(authenticated)/settings/profile/page'; import ProfileSettingsPage from '@/app/(authenticated)/settings/profile/page';
import { AuthProvider } from '@/lib/auth/AuthContext';
import { useAuthStore } from '@/lib/stores/authStore'; import { useAuthStore } from '@/lib/stores/authStore';
// Mock authStore // Mock authStore
jest.mock('@/lib/stores/authStore'); jest.mock('@/lib/stores/authStore');
const mockUseAuthStore = useAuthStore as jest.MockedFunction<typeof useAuthStore>; const mockUseAuthStore = useAuthStore as jest.MockedFunction<typeof useAuthStore>;
// Mock store hook for AuthProvider
const mockStoreHook = ((selector?: (state: any) => any) => {
const state = {
isAuthenticated: true,
user: {
id: '1',
email: 'test@example.com',
first_name: 'Test',
last_name: 'User',
is_active: true,
is_superuser: false,
created_at: '2024-01-01T00:00:00Z',
},
accessToken: 'token',
refreshToken: 'refresh',
isLoading: false,
tokenExpiresAt: null,
setAuth: jest.fn(),
setTokens: jest.fn(),
setUser: jest.fn(),
clearAuth: jest.fn(),
loadAuthFromStorage: jest.fn(),
isTokenExpired: jest.fn(() => false),
};
return selector ? selector(state) : state;
}) as any;
describe('ProfileSettingsPage', () => { describe('ProfileSettingsPage', () => {
const queryClient = new QueryClient({ const queryClient = new QueryClient({
defaultOptions: { defaultOptions: {
@@ -44,7 +72,9 @@ describe('ProfileSettingsPage', () => {
const renderWithProvider = (component: React.ReactElement) => { const renderWithProvider = (component: React.ReactElement) => {
return render( return render(
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
{component} <AuthProvider store={mockStoreHook}>
{component}
</AuthProvider>
</QueryClientProvider> </QueryClientProvider>
); );
}; };

View File

@@ -11,28 +11,29 @@ import {
useCurrentUser, useCurrentUser,
useIsAdmin, useIsAdmin,
} from '@/lib/api/hooks/useAuth'; } from '@/lib/api/hooks/useAuth';
import { AuthProvider } from '@/lib/auth/AuthContext';
// Mock auth store // Mock auth state (Context-injected)
let mockAuthState: { let mockAuthState: any = {
isAuthenticated: boolean;
user: any;
accessToken: string | null;
refreshToken: string | null;
} = {
isAuthenticated: false, isAuthenticated: false,
user: null, user: null,
accessToken: null, accessToken: null,
refreshToken: null, refreshToken: null,
isLoading: false,
tokenExpiresAt: null,
// Action stubs (unused in these tests)
setAuth: jest.fn(),
setTokens: jest.fn(),
setUser: jest.fn(),
clearAuth: jest.fn(),
loadAuthFromStorage: jest.fn(),
isTokenExpired: jest.fn(() => false),
}; };
jest.mock('@/lib/stores/authStore', () => ({ // Mock store hook compatible with AuthContext (Zustand-like hook)
useAuthStore: (selector?: (state: any) => any) => { const mockStoreHook = ((selector?: (state: any) => any) => {
if (selector) { return selector ? selector(mockAuthState) : mockAuthState;
return selector(mockAuthState); }) as any;
}
return mockAuthState;
},
}));
// Mock router // Mock router
jest.mock('next/navigation', () => ({ jest.mock('next/navigation', () => ({
@@ -51,7 +52,9 @@ const createWrapper = () => {
return ({ children }: { children: React.ReactNode }) => ( return ({ children }: { children: React.ReactNode }) => (
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
{children} <AuthProvider store={mockStoreHook}>
{children}
</AuthProvider>
</QueryClientProvider> </QueryClientProvider>
); );
}; };