diff --git a/src/AuthProvider.tsx b/src/AuthProvider.tsx index 842a3dab..d06fe459 100644 --- a/src/AuthProvider.tsx +++ b/src/AuthProvider.tsx @@ -301,6 +301,9 @@ export const AuthProvider = (props: AuthProviderProps): React.JSX.Element => { const removeUser = React.useCallback(async () => { if (!userManager) unsupportedEnvironment("removeUser"); await userManager.removeUser(); + // keep local auth state in sync even when the underlying library + // does not emit UserUnloaded events in this runtime/test setup. + dispatch({ type: "USER_UNLOADED" }); if (onRemoveUser) await onRemoveUser(); }, [userManager, onRemoveUser]); diff --git a/test/AuthProvider.test.tsx b/test/AuthProvider.test.tsx index ea57a002..9d02c5fa 100644 --- a/test/AuthProvider.test.tsx +++ b/test/AuthProvider.test.tsx @@ -225,6 +225,31 @@ describe("AuthProvider", () => { expect(UserManager.prototype.removeUser).toHaveBeenCalled(); }); + it("should mark user as signed out immediately after removeUser", async () => { + const mockGetUser = mocked( + UserManager.prototype, + ).getUser.mockImplementation(() => { + return new Promise((resolve) => { + resolve(user); + }); + }); + + const wrapper = createWrapper({ ...settingsStub }, false); + const { result } = renderHook(() => useAuth(), { + wrapper, + }); + + await waitFor(() => expect(result.current.user).toBe(user)); + expect(result.current.isAuthenticated).toBe(true); + + await act(() => result.current.removeUser()); + + await waitFor(() => expect(result.current.user).toBeUndefined()); + expect(result.current.isAuthenticated).toBe(false); + + mockGetUser.mockRestore(); + }); + it("should handle signoutSilent", async () => { // arrange const wrapper = createWrapper({ ...settingsStub });