Skip to content

@clerk/testing/playwright: clerk.loaded() incompatible with @clerk/react #8058

@mahula

Description

@mahula

Preliminary Checks

Reproduction

Minimal Reproduction Repository: N/A (general compatibility issue)

A minimal reproduction can be created by:

  1. Creating a new React app (e.g., Vite + React + TypeScript)
  2. Installing @clerk/react and @clerk/testing/playwright
  3. Setting up ClerkProvider in the app
  4. Attempting to use clerk.loaded({ page }) in a Playwright test

Publishable Key: pk_test_placeholder (for issue reporting purposes)

Description

Steps to reproduce

  1. Install @clerk/react and @clerk/testing/playwright in a React project
  2. Set up Playwright with @clerk/testing/playwright according to the documentation at https://clerk.com/docs/testing/playwright
  3. Attempt to use clerk.loaded({ page }) from @clerk/testing/playwright in a Playwright test
  4. Observe that the function times out because window.Clerk is never defined

Expected behavior

clerk.loaded({ page }) should detect when Clerk is ready, regardless of whether the app uses @clerk/clerk-js (vanilla) or @clerk/react (React SDK).

Actual behavior

clerk.loaded() relies on checking for window.Clerk:

// From @clerk/testing/dist/playwright/index.js (line ~137)
var C = async ({page:e}) => {
  await e.waitForFunction(() => window.Clerk !== void 0),
  await e.waitForFunction(() => window.Clerk.loaded)
}

Technical Details:

  • @clerk/react loads Clerk JS dynamically from Clerk's CDN via loadClerkJSScript() from @clerk/shared
  • While window.Clerk eventually gets created asynchronously when Clerk JS loads, there is no guarantee it will be available at test runtime when clerk.loaded() checks for it
  • @clerk/react does not expose window.Clerk in the same synchronous, reliable way as the vanilla @clerk/clerk-js SDK
  • Instead, @clerk/react uses React Context internally via useClerk() hook

This makes @clerk/testing/playwright completely incompatible with @clerk/react, which is one of the most popular ways to integrate Clerk in modern web applications.

Impact

  • Cannot use clerk.loaded() to wait for Clerk readiness in React apps
  • Cannot use clerk.signIn() for automated testing (relies on window.Clerk.client.signIn.create() and window.Clerk.setActive())
  • Cannot use clerk.signOut() for automated testing (relies on window.Clerk.signOut())
  • Users must write custom solutions to detect Clerk loading state in React apps
  • No documentation warning about this limitation in the testing docs

Suggested Fix

  1. Option A: Add React-specific testing utilities to @clerk/testing that detect Clerk loading via alternative signals (e.g., React-rendered elements, window.__CLERK_JS__)
  2. Option B: Document prominently that @clerk/testing only works with @clerk/clerk-js and is incompatible with framework SDKs like @clerk/react, @clerk/nextjs, etc.
  3. Option C: Add a method in @clerk/testing that polls for window.Clerk with retry logic to handle async loading in framework SDKs

Environment

npmPackages:
@clerk/react: ^6.x (tested with 6.1.0)
@clerk/testing: ^2.x (tested with 2.0.1)
@clerk/shared: ^4.x
@playwright/test: ^1.x
react: ^18.x
vite: ^5.x

Additional Context

This issue was discovered while implementing E2E tests for a React application using @clerk/react. The testing documentation at https://clerk.com/docs/testing/playwright does not mention any limitations regarding framework SDKs.

Related existing issue: #7891 (signIn() times out with concurrent Playwright workers) - different but related to testing reliability.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions