From 45a137918518c6b3eab41aad66b62aae104d6761 Mon Sep 17 00:00:00 2001 From: austincalvelage Date: Mon, 2 Nov 2026 12:09:11 -0700 Subject: [PATCH 1/4] test(mosaic): cover feature renderer cookie isolation --- .../__tests__/feature/render.feature.test.tsx | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 packages/mosaic/src/__tests__/feature/render.feature.test.tsx diff --git a/packages/mosaic/src/__tests__/feature/render.feature.test.tsx b/packages/mosaic/src/__tests__/feature/render.feature.test.tsx new file mode 100644 index 00000000000..f301d014ce4 --- /dev/null +++ b/packages/mosaic/src/__tests__/feature/render.feature.test.tsx @@ -0,0 +1,30 @@ +import { describe, expect, it } from 'vitest'; + +import { serveFapi } from './fake-fapi'; +import { fapiClient, fapiSession, fapiUser } from './fapi'; +import { renderWithClerk } from './render'; + +describe('feature renderer cookie isolation', () => { + it('loads an active session without leaving session cookies by default', async () => { + const user = fapiUser({ id: 'user_1' }); + serveFapi({ client: fapiClient([fapiSession({ id: 'sess_1', user })]) }); + + const { clerk, unmount } = await renderWithClerk(
); + + expect(clerk.session?.id).toBe('sess_1'); + expect(await clerk.session?.getToken()).toEqual(expect.any(String)); + unmount(); + expect(document.cookie).not.toMatch(/(?:^|; )__session(?:_|=)/); + }); + + it('writes session cookies when standard browser behavior is requested', async () => { + const user = fapiUser({ id: 'user_1' }); + serveFapi({ client: fapiClient([fapiSession({ id: 'sess_1', user })]) }); + + const { clerk } = await renderWithClerk(
, { standardBrowser: true }); + const token = await clerk.session?.getToken(); + + expect(token).toEqual(expect.any(String)); + expect(document.cookie.split('; ')).toContain(`__session=${token}`); + }); +}); From c21b64bae7e304de514cccb50f7040cd64a31cd6 Mon Sep 17 00:00:00 2001 From: austincalvelage Date: Mon, 2 Nov 2026 12:09:27 -0700 Subject: [PATCH 2/4] test(mosaic): disable browser cookie services in feature fixtures --- .changeset/mosaic-feature-cookie-isolation.md | 2 ++ packages/mosaic/docs/testing.md | 3 +++ packages/mosaic/src/__tests__/feature/render.tsx | 9 ++++++++- 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 .changeset/mosaic-feature-cookie-isolation.md diff --git a/.changeset/mosaic-feature-cookie-isolation.md b/.changeset/mosaic-feature-cookie-isolation.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/mosaic-feature-cookie-isolation.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/mosaic/docs/testing.md b/packages/mosaic/docs/testing.md index 8ddb38e614e..9402e35266a 100644 --- a/packages/mosaic/docs/testing.md +++ b/packages/mosaic/docs/testing.md @@ -178,6 +178,9 @@ in [Test placement](#test-placement). `ClerkContextProvider` and `MosaicProvider`, loads Clerk, and returns `{ clerk, navigate, rerender, ... }`. `navigate` is the router Clerk was loaded with, called with the path. + By default, `standardBrowser: false` skips Clerk's browser cookie service, + preventing session cookies from accumulating across tests. Pass + `{ standardBrowser: true }` when a test needs browser authentication behavior. The setup file (`vitest.setup.browser.mts`) starts the worker and focuses the window. Before each test it moves FAPI to a new host, so a request a previous diff --git a/packages/mosaic/src/__tests__/feature/render.tsx b/packages/mosaic/src/__tests__/feature/render.tsx index 933e4dbffca..cbcf75842b2 100644 --- a/packages/mosaic/src/__tests__/feature/render.tsx +++ b/packages/mosaic/src/__tests__/feature/render.tsx @@ -33,7 +33,14 @@ export async function renderWithClerk( ); let current = ui; const view = render(wrap(current)); - await act(() => clerk.load({ routerPush: to => navigate(to), routerReplace: to => navigate(to), ...options })); + await act(() => + clerk.load({ + standardBrowser: false, + routerPush: to => navigate(to), + routerReplace: to => navigate(to), + ...options, + }), + ); view.rerender(wrap(current)); return { From ea3f1b0ba3163579d437b0148b1d51fb2fe65fe2 Mon Sep 17 00:00:00 2001 From: austincalvelage Date: Mon, 2 Nov 2026 12:27:28 -0700 Subject: [PATCH 3/4] test(mosaic): move cookie isolation regression into the isolation suite --- packages/mosaic/docs/testing.md | 7 +++-- .../fake-fapi-isolation.feature.test.tsx | 8 +++++ .../__tests__/feature/render.feature.test.tsx | 30 ------------------- 3 files changed, 12 insertions(+), 33 deletions(-) delete mode 100644 packages/mosaic/src/__tests__/feature/render.feature.test.tsx diff --git a/packages/mosaic/docs/testing.md b/packages/mosaic/docs/testing.md index 9402e35266a..50da1a750ca 100644 --- a/packages/mosaic/docs/testing.md +++ b/packages/mosaic/docs/testing.md @@ -178,9 +178,10 @@ in [Test placement](#test-placement). `ClerkContextProvider` and `MosaicProvider`, loads Clerk, and returns `{ clerk, navigate, rerender, ... }`. `navigate` is the router Clerk was loaded with, called with the path. - By default, `standardBrowser: false` skips Clerk's browser cookie service, - preventing session cookies from accumulating across tests. Pass - `{ standardBrowser: true }` when a test needs browser authentication behavior. + It loads Clerk with `standardBrowser: false`, so there are no cookies, token + polling, captcha, or FAPI-initiated redirects. A test's Clerk is never + disposed, and its cookie service would otherwise write cookies into later + tests. The setup file (`vitest.setup.browser.mts`) starts the worker and focuses the window. Before each test it moves FAPI to a new host, so a request a previous diff --git a/packages/mosaic/src/__tests__/feature/fake-fapi-isolation.feature.test.tsx b/packages/mosaic/src/__tests__/feature/fake-fapi-isolation.feature.test.tsx index 700da58ae8a..9ed44df552f 100644 --- a/packages/mosaic/src/__tests__/feature/fake-fapi-isolation.feature.test.tsx +++ b/packages/mosaic/src/__tests__/feature/fake-fapi-isolation.feature.test.tsx @@ -36,4 +36,12 @@ describe('fake FAPI isolation between tests', () => { expect(memberships.requests).toHaveLength(0); memberships.release(); }); + + it('does not let any Clerk write session cookies', async () => { + const user = fapiUser({ id: 'user_1' }); + serveFapi({ client: fapiClient([fapiSession({ id: 'sess_1', user })]) }); + const { clerk } = await renderWithClerk(
); + expect(await clerk.session?.getToken()).toEqual(expect.any(String)); + expect(document.cookie).not.toMatch(/(?:^|; )__session/); + }); }); diff --git a/packages/mosaic/src/__tests__/feature/render.feature.test.tsx b/packages/mosaic/src/__tests__/feature/render.feature.test.tsx deleted file mode 100644 index f301d014ce4..00000000000 --- a/packages/mosaic/src/__tests__/feature/render.feature.test.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { describe, expect, it } from 'vitest'; - -import { serveFapi } from './fake-fapi'; -import { fapiClient, fapiSession, fapiUser } from './fapi'; -import { renderWithClerk } from './render'; - -describe('feature renderer cookie isolation', () => { - it('loads an active session without leaving session cookies by default', async () => { - const user = fapiUser({ id: 'user_1' }); - serveFapi({ client: fapiClient([fapiSession({ id: 'sess_1', user })]) }); - - const { clerk, unmount } = await renderWithClerk(
); - - expect(clerk.session?.id).toBe('sess_1'); - expect(await clerk.session?.getToken()).toEqual(expect.any(String)); - unmount(); - expect(document.cookie).not.toMatch(/(?:^|; )__session(?:_|=)/); - }); - - it('writes session cookies when standard browser behavior is requested', async () => { - const user = fapiUser({ id: 'user_1' }); - serveFapi({ client: fapiClient([fapiSession({ id: 'sess_1', user })]) }); - - const { clerk } = await renderWithClerk(
, { standardBrowser: true }); - const token = await clerk.session?.getToken(); - - expect(token).toEqual(expect.any(String)); - expect(document.cookie.split('; ')).toContain(`__session=${token}`); - }); -}); From 73f4a1a1a0930f6681d2cb1e87b37304b3364537 Mon Sep 17 00:00:00 2001 From: austincalvelage Date: Mon, 2 Nov 2026 12:33:49 -0700 Subject: [PATCH 4/4] docs(mosaic): trim the renderWithClerk standardBrowser note --- packages/mosaic/docs/testing.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/mosaic/docs/testing.md b/packages/mosaic/docs/testing.md index 50da1a750ca..e1b8cfc278d 100644 --- a/packages/mosaic/docs/testing.md +++ b/packages/mosaic/docs/testing.md @@ -178,8 +178,7 @@ in [Test placement](#test-placement). `ClerkContextProvider` and `MosaicProvider`, loads Clerk, and returns `{ clerk, navigate, rerender, ... }`. `navigate` is the router Clerk was loaded with, called with the path. - It loads Clerk with `standardBrowser: false`, so there are no cookies, token - polling, captcha, or FAPI-initiated redirects. A test's Clerk is never + It loads Clerk with `standardBrowser: false`. A test's Clerk is never disposed, and its cookie service would otherwise write cookies into later tests.