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

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions