test(e2e): Wave 4b — UI-driven Razorpay TEST-card payment E2E (free → upgrade → Pro)#194
Merged
Merged
Conversation
… upgrade → Pro)
The CEO ask: "There is no CI that actually tries to create a test user, then
tries to upgrade and enter test details and check everything is working fine."
This adds the real UI loop. Design: docs/ci/01-CI-INTEGRATION-DESIGN.md
§"Razorpay test-card payment E2E" (Approach A) + the api Wave 4b PR (cohort
test-mode rzp_test_* checkout routing).
e2e/live-ui-payment.spec.ts — TWO tests, two lanes:
1. @pr-smoke CONTRACT-ONLY (PR-able, no card entry): mint a free cohort user
via the factory → drive the dashboard /app/checkout?plan=pro UI →
createCheckout → assert the SPA reaches a Razorpay checkout URL, OR the
inert cohort path (synthetic_test_cohort 403, when rzp_test_* keys aren't
wired), OR the honest billing-not-configured fallback. All three prove the
UI→api→checkout wiring end-to-end against the REAL api. Reaped.
2. FULL card-entry (nightly only, gated on E2E_RAZORPAY_TEST_MODE=1): same up
to the Razorpay page, then fill the subscription test card
4718 6091 0820 4366 + OTP 1234 (cross-origin iframes + popup handled), submit
→ poll /api/v1/capabilities for tier=pro (the real TEST-mode webhook drives
the upgrade). RESILIENT + SOFT-FAILS (skip-with-reason) on a Razorpay
markup change or an unreachable webhook so a UI change never reds the
nightly. Deterministic upgrade is covered by the api webhook-injection suite.
Wiring: the spec matches live-*.spec.ts so it runs in e2e-prod.yml (30-min) +
e2e-live.yml (nightly staging); the @pr-smoke leg runs per-PR via
e2e-pr-smoke.yml. Both nightly workflows now pass E2E_RAZORPAY_TEST_MODE from a
repo var (inert until the operator wires test keys) + arm the factory token.
Gating: skips clean until E2E_LIVE/E2E_ACCOUNT_TOKEN (and, for the card leg,
E2E_RAZORPAY_TEST_MODE) are set. Verified live: the @pr-smoke contract-only test
PASSES against prod api.instanode.dev (minted free cohort → UI → reached the
inert cohort path, reaped). npm run gate green (tsc + build + 1129 vitest).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
size-limit report 📦
|
…egexp-anchor CodeQL flagged the unanchored /(razorpay\.com|rzp\.io)/i regex used to validate a reached checkout URL: an unanchored substring match means a hostile URL like https://evil.com/?x=razorpay.com would pass. Replace the assertion with a parsed isRazorpayCheckoutHost() that inspects the URL hostname (exact apex or subdomain match), and anchor the Playwright route() regex on scheme + exact host segment. No security weakening — strictly tightens the host check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Wave 4b (Part 2 of 2) — web: the UI-driven Razorpay TEST-card payment E2E
The CEO ask: "There is no CI that actually tries to create a test user, then tries to upgrade and enter test details and check everything is working fine." This adds that real UI loop. Pairs with the api Wave 4b PR (InstaNode-dev/api#268 — cohort test-mode
rzp_test_*checkout routing). Design:docs/ci/01-CI-INTEGRATION-DESIGN.md§"Razorpay test-card payment E2E" (Approach A).e2e/live-ui-payment.spec.ts— two tests, two lanes1.
@pr-smokeCONTRACT-ONLY (PR-able, no card entry). Mint a free cohort user via the factory → drive the dashboard/app/checkout?plan=proUI →createCheckout→ assert the SPA reaches one of: a Razorpay checkout URL (test keys wired), the inert cohort path (synthetic_test_cohort403, whenrzp_test_*keys aren't wired — prod today), or the honestbilling-not-configuredfallback. All three prove the UI→api→checkout wiring end-to-end against the real api. Reaped.2. FULL card-entry (nightly only, gated
E2E_RAZORPAY_TEST_MODE=1). Same up to the Razorpay page, then fill the subscription test card 4718 6091 0820 4366 + OTP 1234 (cross-origin iframes + popup handled) → submit → poll/api/v1/capabilitiesfortier=pro(the real TEST-mode webhook drives the upgrade). RESILIENT + SOFT-FAILS (skip-with-reason) on a Razorpay markup change or an unreachable webhook — a Razorpay UI change must never red the nightly. Deterministic upgrade is covered by the api webhook-injection suite.Wiring
live-*.spec.ts→ runs ine2e-prod.yml(30-min) +e2e-live.yml(nightly staging). The@pr-smokeleg runs per-PR viae2e-pr-smoke.yml.E2E_RAZORPAY_TEST_MODEfrom a repo var (inert until the operator wires test keys) + arm the factory token.Gating + live verification
Skips clean until
E2E_LIVE/E2E_ACCOUNT_TOKEN(and, for the card leg,E2E_RAZORPAY_TEST_MODE) are set. Verified live: the@pr-smokecontract-only test PASSES against prodapi.instanode.dev— minted a free cohort user → drove the dashboard UI → reached the inert cohort path (synthetic_test_cohort403, since prod has no test keys yet) → reaped clean.npm run gategreen (tsc + build + 1129 vitest).Operator enable (no approval wait)
After the api Wave 4b PR is merged + the operator sets
RAZORPAY_TEST_*on the api: set repo varE2E_RAZORPAY_TEST_MODE=1(+E2E_ACCOUNT_TOKENsecret already present) → the nightly card-entry leg goes live. Until then it's shipped + inert.🤖 Generated with Claude Code