Refactor to enforce AuthContext usage over useAuthStore and improve test stability

- Replaced `useAuthStore` with `useAuth` from `AuthContext` across frontend components and tests to ensure dependency injection compliance.
- Enhanced E2E test stability by delaying navigation until the auth context is fully initialized.
- Updated Playwright configuration to use a single worker to prevent mock conflicts.
- Refactored test setup to consistently inject `AuthProvider` for improved isolation and mocking.
- Adjusted comments and documentation to clarify dependency injection and testability patterns.
This commit is contained in:
Felipe Cardoso
2025-11-05 08:37:01 +01:00
parent 7c98ceb5b9
commit f23fdb974a
14 changed files with 160 additions and 80 deletions

View File

@@ -35,13 +35,16 @@ let refreshPromise: Promise<string> | null = null;
/* istanbul ignore next */
const getAuthStore = async () => {
// Check for E2E test store injection (same pattern as AuthProvider)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if (typeof window !== 'undefined' && (window as any).__TEST_AUTH_STORE__) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const testStore = (window as any).__TEST_AUTH_STORE__;
// Test store must have getState() method for non-React contexts
return testStore.getState();
}
// Production: use real Zustand store
// Note: Dynamic import is acceptable here (non-React context, checks __TEST_AUTH_STORE__ first)
const { useAuthStore } = await import('@/lib/stores/authStore');
return useAuthStore.getState();
};

View File

@@ -20,7 +20,6 @@ import {
confirmPasswordReset,
changeCurrentUserPassword,
} from '../client';
import { useAuthStore } from '@/lib/stores/authStore';
import type { User } from '@/lib/stores/authStore';
import { useAuth } from '@/lib/auth/AuthContext';
import { parseAPIError, getGeneralError } from '../errors';
@@ -50,8 +49,8 @@ export const authKeys = {
* @returns React Query result with user data
*/
export function useMe() {
const { isAuthenticated, accessToken } = useAuthStore();
const setUser = useAuthStore((state) => state.setUser);
const { isAuthenticated, accessToken } = useAuth();
const setUser = useAuth((state) => state.setUser);
const query = useQuery({
queryKey: authKeys.me,
@@ -95,7 +94,7 @@ export function useMe() {
export function useLogin(onSuccess?: () => void) {
const router = useRouter();
const queryClient = useQueryClient();
const setAuth = useAuthStore((state) => state.setAuth);
const setAuth = useAuth((state) => state.setAuth);
return useMutation({
mutationFn: async (credentials: { email: string; password: string }) => {
@@ -163,7 +162,7 @@ export function useLogin(onSuccess?: () => void) {
export function useRegister(onSuccess?: () => void) {
const router = useRouter();
const queryClient = useQueryClient();
const setAuth = useAuthStore((state) => state.setAuth);
const setAuth = useAuth((state) => state.setAuth);
return useMutation({
mutationFn: async (data: {
@@ -240,8 +239,8 @@ export function useRegister(onSuccess?: () => void) {
export function useLogout() {
const router = useRouter();
const queryClient = useQueryClient();
const clearAuth = useAuthStore((state) => state.clearAuth);
const refreshToken = useAuthStore((state) => state.refreshToken);
const clearAuth = useAuth((state) => state.clearAuth);
const refreshToken = useAuth((state) => state.refreshToken);
return useMutation({
mutationFn: async () => {
@@ -296,7 +295,7 @@ export function useLogout() {
export function useLogoutAll() {
const router = useRouter();
const queryClient = useQueryClient();
const clearAuth = useAuthStore((state) => state.clearAuth);
const clearAuth = useAuth((state) => state.clearAuth);
return useMutation({
mutationFn: async () => {

View File

@@ -9,7 +9,7 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { updateCurrentUser } from '../client';
import { useAuthStore } from '@/lib/stores/authStore';
import { useAuth } from '@/lib/auth/AuthContext';
import type { User } from '@/lib/stores/authStore';
import { parseAPIError, getGeneralError } from '../errors';
import { authKeys } from './useAuth';
@@ -31,7 +31,7 @@ import { authKeys } from './useAuth';
*/
export function useUpdateProfile(onSuccess?: (message: string) => void) {
const queryClient = useQueryClient();
const setUser = useAuthStore((state) => state.setUser);
const setUser = useAuth((state) => state.setUser);
return useMutation({
mutationFn: async (data: {

View File

@@ -13,6 +13,7 @@
import { createContext, useContext } from "react";
import type { ReactNode } from "react";
// eslint-disable-next-line no-restricted-imports -- This is the DI boundary, needs real store for production
import { useAuthStore as useAuthStoreImpl } from "@/lib/stores/authStore";
import type { User } from "@/lib/stores/authStore";