Skip to content

test(js): add ProtectChallenge sandbox scenario for protect-check flows#9072

Closed
mwickett wants to merge 3 commits into
theo/protect-check-sdk-supportfrom
mike/protect-challenge-sandbox-scenario
Closed

test(js): add ProtectChallenge sandbox scenario for protect-check flows#9072
mwickett wants to merge 3 commits into
theo/protect-check-sdk-supportfrom
mike/protect-challenge-sandbox-scenario

Conversation

@mwickett

@mwickett mwickett commented Jul 2, 2026

Copy link
Copy Markdown
Member

What

A sandbox scenario for exercising the #8329 protect_check step without any backend — MSW mocks the FAPI responses (protect_check on sign-up create and after sign-in first-factor attempt, PATCH resolution, chaining) and serves a mock challenge module implementing the script contract.

Targets theo/protect-check-sdk-support so it rides with #8329 but stays separately reviewable.

How to use

pnpm dev:sandbox
  • /sign-in?scenario=ProtectChallenge&protectChallengeMode=manual
  • /sign-up?scenario=ProtectChallenge&protectChallengeMode=manual

protectChallengeMode=manual pauses on a "Complete challenge" button (omit for auto-resolve). Add protectChallengeWidget=turnstile to render the real Cloudflare Turnstile widget inside the protect-check card using Cloudflare's universal test sitekeys (always-pass in auto mode, force-interactive in manual mode) — production pixels, mocked proof token. That mode's only network dependency is Cloudflare's CDN.

Why

@alex-carpenter asked in #team-protect how the challenge renders within the flow — this makes that a 30-second local check and gives the PR Playwright coverage for auto/manual resolution on both flows. Verified against a full local clerk_go + warden-go E2E run; the mocked response shapes match real FAPI.

Testing status

The Playwright spec (sandbox/integration/protect-challenge.spec.ts) encodes the intended post-resolution behavior: after a challenge resolves, sign-up continues to email verification and sign-in activates the session. All three tests are annotated test.fail() because that behavior is currently broken on the base branch — once a check resolves, the flow never advances (details in the #8329 review discussion). The moment that's fixed, these flip to "unexpected pass"; delete the annotations and the spec becomes an enforced regression guardrail for exactly that bug.

Run it locally (the sandbox scenario mocks FAPI, so dummy keys suffice):

cd packages/clerk-js
PORT=4021   INTEGRATION_INSTANCE_KEYS='{"sandbox":{"pk":"pk_test_…","sk":"sk_test_dummy"}, …one entry per name referenced by integration/presets/envs.ts…}'   CLERK_TESTING_TOKEN=dummy   pnpm playwright test sandbox/integration/protect-challenge.spec.ts

Open question for the branch owner: test:sandbox:integration isn't part of CI today, so this spec only guards locally until it's wired into a workflow — happy to follow whatever the plan is for the other sandbox specs.

Notes

  • The scenario grafts a full UserJSON onto the mock session (the msw session template ships user: null), so the sign-in test asserts a genuinely hydrated Clerk.user.id rather than a placeholder.
  • Empty changeset — sandbox/tooling only, no published-package changes.
  • Two UI bugs found while testing the flow E2E will be left as review comments on feat(clerk-js,shared,ui): Add Protect SDK challenge support during sign-up and sign-in #8329 (post-resolution auto-advance; retry duplicating the challenge widget).

Adds an MSW scenario that gates sign-in and sign-up with a protect_check
challenge so the new protect-check step can be exercised without a real
Protect decision service:

- auto and manual modes (protectChallengeMode=manual pauses on a button)
- optional protectChallengeWidget=turnstile renders the real Cloudflare
  Turnstile widget via Cloudflare's universal test sitekeys for visual QA
- Playwright spec covering sign-up auto/manual resolution and sign-in
- sandbox README section documenting the URLs
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Jul 2, 2026 4:52pm
swingset Ready Ready Preview, Comment Jul 2, 2026 4:52pm

Request Review

@changeset-bot

changeset-bot Bot commented Jul 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5ee9bee

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: c788d773-7c26-4651-9880-cd8ebc6883d6

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

Settle the Turnstile run exactly once: attach load AND error handlers on
the reused in-flight script tag, guard render against an already-aborted
or settled run, and remove the abort listener on settle. Previously an
abort during script load could render into an abandoned container, and a
reused loading script had no error path.
…ranch fix

The spec encodes the intended post-resolution behavior (sign-up continues
to verification, sign-in activates a session), which is currently broken
on the base branch — the flow never advances once a protect check
resolves. Annotate all three tests with test.fail() so the suite runs
green today and flips to 'unexpected pass' when the fix lands, at which
point removing the annotations turns the spec into an enforced regression
guardrail.

Also graft a full UserJSON onto the mock session (the msw session
template ships user: null) so the sign-in test asserts a genuinely
hydrated Clerk.user.id — verified via manual setActive that session
activation itself works against the mock — and use a bounded expect.poll
instead of page.waitForFunction, since a test-level timeout is not
covered by test.fail() but a failed assertion is.
@mwickett

mwickett commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

Ok, closing this out because I don't like the idea of mocking this with a service worker. The real fix is to get the actual Integration Testing instance in staging configured to have Protect enabled.

@mwickett mwickett closed this Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant