diff --git a/src/ClientContext.test.tsx b/src/ClientContext.test.tsx index 909635d89..d279a87ee 100644 --- a/src/ClientContext.test.tsx +++ b/src/ClientContext.test.tsx @@ -13,11 +13,11 @@ import { type FC } from "react"; import { ClientProvider, useClientState } from "./ClientContext"; -const mockClient = (): MatrixClient => +const mockClient = (userId = "@alice:example.org"): MatrixClient => ({ on: vi.fn(), removeListener: vi.fn(), - getUserId: () => "@alice:example.org", + getUserId: () => userId, getDeviceId: () => "AAAA", stopClient: vi.fn(), }) as Partial as MatrixClient; @@ -67,3 +67,28 @@ test("does not claim exclusive use of storage when given a client", () => { postMessage.mockRestore(); }); + +test("follows the client when the host swaps it", () => { + const first = mockClient(); + const second = mockClient("@bob:example.org"); + + const { container, rerender } = render( + + + + + , + ); + expect(container.textContent).toBe("@alice:example.org"); + + // A host that re-authenticates hands us a new client on a mounted component + rerender( + + + + + , + ); + + expect(container.textContent).toBe("@bob:example.org"); +}); diff --git a/src/ClientContext.tsx b/src/ClientContext.tsx index 388beb8b1..ced48d446 100644 --- a/src/ClientContext.tsx +++ b/src/ClientContext.tsx @@ -163,7 +163,14 @@ export const ClientProvider: FC = ({ children, client }) => { const initializing = useRef(false); useEffect(() => { if (client !== undefined) { - // Nothing to load, but analytics still need to follow the user's choices. + // Nothing to load, but a host may hand us a different client later — on + // re-authenticating, say — so follow whichever one it has given us. + setInitClientState((current) => + current?.client === client + ? current + : { client, passwordlessUser: false }, + ); + // Analytics still need to follow the user's choices. if (PosthogAnalytics.instance.isEnabled()) PosthogAnalytics.instance.startListeningToSettingsChanges(); return;