From c6f2f2eedcf0de354c58fd42de6cecaee74663af Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Wed, 28 Oct 2026 12:25:20 +0300 Subject: [PATCH] fix: stabilize auth client registration (WealthLedger/frontend#95) --- src/features/auth/model/auth.test.tsx | 22 +++++++++++++++++++++- src/features/auth/model/auth.vm.ts | 3 ++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/features/auth/model/auth.test.tsx b/src/features/auth/model/auth.test.tsx index e2dc24d..d00f246 100644 --- a/src/features/auth/model/auth.test.tsx +++ b/src/features/auth/model/auth.test.tsx @@ -3,8 +3,9 @@ import type { FC, PropsWithChildren } from "react"; import { QueryClientProvider, useQueryClient } from "@tanstack/react-query"; import { act, renderHook, waitFor } from "@testing-library/react"; import { http, HttpResponse } from "msw"; -import { describe, expect, it } from "vitest"; +import { describe, expect, it, onTestFinished, vi } from "vitest"; +import * as sharedApi from "@/shared/api"; import { apiClient, apiQueryClient, useAuthenticatedQuery } from "@/shared/api"; import { createTestQueryClient } from "@/test/query"; import { resource } from "@/test/resource"; @@ -398,4 +399,23 @@ describe("AuthProvider", () => { expect(result.current.cards.data?.[0]?.id).toBe("b-card"), ); }); + + it("registers auth handlers once until unmount", async () => { + const configure = vi.spyOn(sharedApi, "configureAuthClient"); + onTestFinished(() => configure.mockRestore()); + + const { rerender, result, unmount } = renderHook(useAuth, { + wrapper: createAuthWrapper(createTestQueryClient()), + }); + + await waitFor(() => expect(result.current.ready).toBe(true)); + const registrations = configure.mock.calls.length; + + rerender(); + expect(configure).toHaveBeenCalledTimes(registrations); + + unmount(); + expect(configure).toHaveBeenCalledTimes(registrations + 1); + expect(configure).toHaveBeenLastCalledWith(); + }); }); diff --git a/src/features/auth/model/auth.vm.ts b/src/features/auth/model/auth.vm.ts index 5cfa2a8..80c71c8 100644 --- a/src/features/auth/model/auth.vm.ts +++ b/src/features/auth/model/auth.vm.ts @@ -161,7 +161,8 @@ function useAuthProviderVm() { refresh, unavailable: () => unavailableRef.current, }); - }); + // `user` tracks access-token changes, which configureAuthClient publishes as session state. + }, [clearSession, refresh, user]); useEffect(() => () => configureAuthClient(), []); const authContextValue = {