From 79011c779f1835f6285ce0b7066f758bcfc1d33b Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Sat, 20 Jun 2026 23:04:34 +0300 Subject: [PATCH] fix: move test SessionProvider to shared layer for FSD compliance --- .../shared/lib/test/TestSessionProvider.tsx | 94 +++++++++++++++++++ .../src/shared/lib/test/test-utils.tsx | 4 +- 2 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 apps/frontend/src/shared/lib/test/TestSessionProvider.tsx diff --git a/apps/frontend/src/shared/lib/test/TestSessionProvider.tsx b/apps/frontend/src/shared/lib/test/TestSessionProvider.tsx new file mode 100644 index 0000000..fdb35d5 --- /dev/null +++ b/apps/frontend/src/shared/lib/test/TestSessionProvider.tsx @@ -0,0 +1,94 @@ +import { useState, useEffect, useCallback, type ReactNode } from 'react'; +import { SessionContext, type SessionContextValue } from '@/entities/session'; +import * as sessionApi from '@/entities/session'; +import type { UserResponse } from '@/shared/api/responses'; + +export function TestSessionProvider({ children }: { children: ReactNode }) { + const [user, setUser] = useState(null); + const [accessToken, setAccessTokenState] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const [initialized, setInitialized] = useState(false); + + const updateSession = useCallback((authData: { user: UserResponse; accessToken: string }) => { + setUser(authData.user); + setAccessTokenState(authData.accessToken); + }, []); + + const clearSession = useCallback(() => { + setUser(null); + setAccessTokenState(null); + }, []); + + const login = useCallback( + async (email: string, password: string) => { + const result = await sessionApi.login(email, password); + updateSession(result); + }, + [updateSession], + ); + + const register = useCallback( + async (email: string, password: string, name?: string) => { + const result = await sessionApi.register(email, password, name); + updateSession(result); + }, + [updateSession], + ); + + const logout = useCallback(async () => { + try { + await sessionApi.logout(); + } catch { + // ignore network errors on logout + } + clearSession(); + }, [clearSession]); + + const updateProfileFn = useCallback(async (data: { name?: string }) => { + const result = await sessionApi.updateProfile(data); + setUser(result); + }, []); + + useEffect(() => { + let mounted = true; + + async function init() { + try { + const result = await sessionApi.refresh(); + if (mounted) { + updateSession(result); + } + } catch { + // No valid session + } finally { + if (mounted) { + setIsLoading(false); + setInitialized(true); + } + } + } + + init(); + + return () => { + mounted = false; + }; + }, [updateSession]); + + if (!initialized && isLoading) { + return
Загрузка...
; + } + + const value: SessionContextValue = { + user, + accessToken, + isAuthenticated: !!user, + isLoading, + login, + register, + logout, + updateProfile: updateProfileFn, + }; + + return {children}; +} diff --git a/apps/frontend/src/shared/lib/test/test-utils.tsx b/apps/frontend/src/shared/lib/test/test-utils.tsx index 3fd863d..7452a0a 100644 --- a/apps/frontend/src/shared/lib/test/test-utils.tsx +++ b/apps/frontend/src/shared/lib/test/test-utils.tsx @@ -2,7 +2,7 @@ import { type ReactElement } from 'react'; import { render, type RenderOptions } from '@testing-library/react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { MemoryRouter } from 'react-router-dom'; -import { SessionProvider } from '@/app/providers'; +import { TestSessionProvider } from './TestSessionProvider'; interface CustomRenderOptions extends Omit { queryClient?: QueryClient; @@ -33,7 +33,7 @@ export function renderWithProviders( initialEntries={[route]} future={{ v7_startTransition: true, v7_relativeSplatPath: true }} > - {children} + {children} );