diff --git a/.changeset/isolate-mosaic-fake-fapi.md b/.changeset/isolate-mosaic-fake-fapi.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/isolate-mosaic-fake-fapi.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/mosaic/docs/testing.md b/packages/mosaic/docs/testing.md index 07d64e1e551..dddb9b355a0 100644 --- a/packages/mosaic/docs/testing.md +++ b/packages/mosaic/docs/testing.md @@ -165,9 +165,11 @@ in [Test placement](#test-placement). `navigate` is the router Clerk was loaded with, called with the path. The setup file (`vitest.setup.browser.mts`) starts the worker and focuses the -window. After each test it cleans up, resets the handlers and the shared query -cache, and **fails the test on any FAPI request without a handler**, or on a -`holdRequests` hold never released or failed. When a +window. Before each test it moves FAPI to a new host, so a request a previous +test's Clerk sends late fails with a network error instead of reaching this +test's handlers. After each test it cleans up, resets the handlers and the +shared query cache, and **fails the test on any FAPI request without a +handler**, or on a `holdRequests` hold never released or failed. When a feature needs a new endpoint, add a handler to `serveFapi` that mirrors what FAPI returns. 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 new file mode 100644 index 00000000000..bc3a28aab87 --- /dev/null +++ b/packages/mosaic/src/__tests__/feature/fake-fapi-isolation.feature.test.tsx @@ -0,0 +1,37 @@ +import { describe, expect, it } from 'vitest'; + +import { holdRequests, serveFapi } from './fake-fapi'; +import { fapiClient, fapiSession, fapiUser } from './fapi'; +import { renderWithClerk } from './render'; + +describe('fake FAPI isolation between tests', () => { + it('leaves a request in flight when the test ends', async () => { + const user = fapiUser({ id: 'user_1' }); + serveFapi({ client: fapiClient([fapiSession({ id: 'sess_1', user })]) }); + const { clerk } = await renderWithClerk(
); + void clerk.user?.getOrganizationMemberships().catch(() => undefined); + }); + + it('does not hand the previous test’s request to this test’s handlers', async () => { + serveFapi(); + const memberships = holdRequests('get', '/v1/me/organization_memberships'); + await new Promise(resolve => setTimeout(resolve, 200)); + expect(memberships.requests).toHaveLength(0); + memberships.release(); + }); + + it('starts a request after the test ends', async () => { + const user = fapiUser({ id: 'user_1' }); + serveFapi({ client: fapiClient([fapiSession({ id: 'sess_1', user })]) }); + const { clerk } = await renderWithClerk(); + setTimeout(() => void clerk.user?.getOrganizationMemberships().catch(() => undefined), 50); + }); + + it('does not let the previous test’s Clerk reach this test’s handlers', async () => { + serveFapi(); + const memberships = holdRequests('get', '/v1/me/organization_memberships'); + await new Promise(resolve => setTimeout(resolve, 200)); + expect(memberships.requests).toHaveLength(0); + memberships.release(); + }); +}); diff --git a/packages/mosaic/src/__tests__/feature/fake-fapi.ts b/packages/mosaic/src/__tests__/feature/fake-fapi.ts index fa82dc89c7a..07ffcd6d258 100644 --- a/packages/mosaic/src/__tests__/feature/fake-fapi.ts +++ b/packages/mosaic/src/__tests__/feature/fake-fapi.ts @@ -48,10 +48,18 @@ import { fapiWeb3Wallet, } from './fapi'; -export const PUBLISHABLE_KEY = 'pk_live_Y2xlcmsuYWJjZWYuMTIzNDUucHJvZC5sY2xjbGVyay5jb20k'; -const FAPI = 'https://clerk.abcef.12345.prod.lclclerk.com'; +const FAPI_DOMAIN = '12345.prod.lclclerk.com'; +let fapiRun = 0; +let fapiHost = `clerk.run${fapiRun}.${FAPI_DOMAIN}`; -export const fapiUrl = (path: string) => `${FAPI}${path}`; +export function switchFapiHost() { + fapiRun += 1; + fapiHost = `clerk.run${fapiRun}.${FAPI_DOMAIN}`; +} + +export const publishableKey = () => `pk_live_${btoa(`${fapiHost}$`)}`; + +export const fapiUrl = (path: string) => `https://${fapiHost}${path}`; export interface FakeFapiState { environment: FapiEnvironment; @@ -92,13 +100,17 @@ export type FakeFapiSeed = Partial