From b52dd40fc6f3fdb34ab0d505e4ff938dad18e7d1 Mon Sep 17 00:00:00 2001 From: mrkvon Date: Wed, 25 Mar 2026 12:19:10 +0100 Subject: [PATCH] [solid-react] Update session and ranInitialCheck synchronously during initial auth check. Fixes #52 --- .../src/createBrowserSolidReactMethods.tsx | 26 ++++---- .../test/Auth-Integration.test.tsx | 66 +++++++++++++++++++ 2 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 packages/solid-react/test/Auth-Integration.test.tsx diff --git a/packages/solid-react/src/createBrowserSolidReactMethods.tsx b/packages/solid-react/src/createBrowserSolidReactMethods.tsx index 837b3c65..29d1528f 100644 --- a/packages/solid-react/src/createBrowserSolidReactMethods.tsx +++ b/packages/solid-react/src/createBrowserSolidReactMethods.tsx @@ -39,21 +39,21 @@ export function createBrowserSolidReactMethods( window.localStorage.setItem(PRE_REDIRECT_URI, window.location.href); } - await handleIncomingRedirect({ + const sessionInfo = await handleIncomingRedirect({ restorePreviousSession: true, }); - // Set timout to ensure this happens after the redirect - setTimeout(() => { - setSession({ ...getDefaultSession().info }); - window.history.replaceState( - {}, - "", - window.localStorage.getItem(PRE_REDIRECT_URI), - ); - window.localStorage.removeItem(PRE_REDIRECT_URI); - setRanInitialAuthCheck(true); - }, 0); + if (!sessionInfo) return; + + setSession(sessionInfo); + window.history.replaceState( + {}, + "", + window.localStorage.getItem(PRE_REDIRECT_URI), + ); + window.localStorage.removeItem(PRE_REDIRECT_URI); + + setRanInitialAuthCheck(true); }, []); const login = useCallback( @@ -69,7 +69,7 @@ export function createBrowserSolidReactMethods( }; window.localStorage.setItem(PRE_REDIRECT_URI, window.location.href); await libraryLogin(fullOptions); - setSession({ ...getDefaultSession().info }); + // user should be redirected away from the app }, [], ); diff --git a/packages/solid-react/test/Auth-Integration.test.tsx b/packages/solid-react/test/Auth-Integration.test.tsx new file mode 100644 index 00000000..1480114f --- /dev/null +++ b/packages/solid-react/test/Auth-Integration.test.tsx @@ -0,0 +1,66 @@ +import React, { type FunctionComponent, useEffect } from "react"; +import { beforeEach, describe, it, vi, expect } from "vitest"; +import { useSolidAuth } from "../src/SolidAuthContext.js"; +import { render, waitFor } from "@testing-library/react"; +import { BrowserSolidLdoProvider } from "@ldo/solid-react"; +import { handleIncomingRedirect } from "@inrupt/solid-client-authn-browser"; + +window.localStorage = { + length: 0, + getItem: () => null, + setItem: () => {}, + clear: () => {}, + removeItem: () => {}, + key: () => null, +}; + +vi.mock("@inrupt/solid-client-authn-browser", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...(actual as Record), + handleIncomingRedirect: vi.fn(), + }; +}); + +describe("Solid Auth Integration Tests", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + // https://github.com/o-development/ldo/issues/52 + it("keeps ranInitialAuthCheck and session.isLoggedIn in sync", async () => { + const renders: ReturnType[] = []; + + vi.mocked(handleIncomingRedirect).mockResolvedValue({ + isLoggedIn: true, + sessionId: "handle-incoming-redirect", + }); + + const TestComponent: FunctionComponent = () => { + const result = useSolidAuth(); + useEffect(() => { + renders.push(result); + }); + return null; + }; + + render( + + + , + ); + + await waitFor(() => { + expect(renders.some((render) => render.session.isLoggedIn)).toBe(true); + expect(renders.some((render) => render.ranInitialAuthCheck)).toBe(true); + }); + + for (const renderData of renders) { + if (renderData.ranInitialAuthCheck === true) { + expect(renderData.session.isLoggedIn).toEqual(true); + } else { + expect(renderData.session.isLoggedIn).toEqual(false); + } + } + }); +});