Summary
Four Playwright billing Stripe E2E tests in tests/e2e/web/specs/billing/billing-stripe.spec.ts are skipped on preview CI because the pre-run checkout probe fails with 401 unauthenticated from the billing-stripe Edge Function.
Observed behavior
[e2e] Stripe checkout probe: not ready — billing-stripe checkout failed (401): {"error":"unauthenticated"}
- Billing Stripe flows › upgrades Free to Pro via Stripe Checkout
- Billing Stripe flows › shows annual switch option for paid plan
- Billing Stripe flows › loads invoices page after upgrade
- Billing Stripe flows › schedules downgrade to Free after Pro subscription
4 skipped
15 passed
The spec uses probeStripeCheckoutReady() in beforeAll and skips all four tests when the probe is not ready (billing-stripe.spec.ts).
Expected behavior
When preview billing is configured (Stripe test keys, synced plans, BILLING_ALLOWED_ORIGINS, deployed billing-stripe), the probe should reach Stripe Checkout and the four tests should run in the shared-state Playwright project.
Likely investigation areas
- Auth session in reused CI artifacts —
shared-state runs after e2e-chromium with E2E_SKIP_GLOBAL_SETUP=1 and downloaded .auth/ storage state. The probe uses e2eStorageStatePath; the session JWT may be expired or not accepted by preview Supabase when the serial job starts.
- Edge anon key mismatch —
billing-stripe validates the caller via auth.getUser() using SUPABASE_ANON_KEY or BILLING_SUPABASE_ANON_KEY (supabase/functions/billing-stripe/index.ts). Confirm preview deploy sets BILLING_SUPABASE_ANON_KEY to match the web app VITE_SUPABASE_ANON_KEY.
- Authorization header on checkout invoke — Verify the web billing client sends the logged-in user's access token when POSTing to
billing-stripe from /billing/plans (Playwright sees the 401 on the network response).
- Preview billing deploy — Confirm
billing-stripe is deployed, plans are synced (npm run billing:sync-stripe), and BILLING_ALLOWED_ORIGINS includes the PR preview origin.
References
- Probe:
tests/e2e/web/fixtures/stripe-checkout.fixture.ts (probeStripeCheckoutReady)
- Edge auth gate:
supabase/functions/billing-stripe/index.ts (401 when auth.getUser() fails)
- Docs:
docs/stripe-billing-setup.md (401 troubleshooting), docs/TESTING.md (Stripe billing E2E section)
- CI:
.github/workflows/e2e-web-pr-approval.yml (e2e-serial job, shared-state project)
Acceptance criteria
Summary
Four Playwright billing Stripe E2E tests in
tests/e2e/web/specs/billing/billing-stripe.spec.tsare skipped on preview CI because the pre-run checkout probe fails with 401 unauthenticated from thebilling-stripeEdge Function.Observed behavior
The spec uses
probeStripeCheckoutReady()inbeforeAlland skips all four tests when the probe is not ready (billing-stripe.spec.ts).Expected behavior
When preview billing is configured (Stripe test keys, synced plans,
BILLING_ALLOWED_ORIGINS, deployedbilling-stripe), the probe should reach Stripe Checkout and the four tests should run in theshared-statePlaywright project.Likely investigation areas
shared-stateruns aftere2e-chromiumwithE2E_SKIP_GLOBAL_SETUP=1and downloaded.auth/storage state. The probe usese2eStorageStatePath; the session JWT may be expired or not accepted by preview Supabase when the serial job starts.billing-stripevalidates the caller viaauth.getUser()usingSUPABASE_ANON_KEYorBILLING_SUPABASE_ANON_KEY(supabase/functions/billing-stripe/index.ts). Confirm preview deploy setsBILLING_SUPABASE_ANON_KEYto match the web appVITE_SUPABASE_ANON_KEY.billing-stripefrom/billing/plans(Playwright sees the 401 on the network response).billing-stripeis deployed, plans are synced (npm run billing:sync-stripe), andBILLING_ALLOWED_ORIGINSincludes the PR preview origin.References
tests/e2e/web/fixtures/stripe-checkout.fixture.ts(probeStripeCheckoutReady)supabase/functions/billing-stripe/index.ts(401 whenauth.getUser()fails)docs/stripe-billing-setup.md(401 troubleshooting),docs/TESTING.md(Stripe billing E2E section).github/workflows/e2e-web-pr-approval.yml(e2e-serialjob,shared-stateproject)Acceptance criteria
billing-stripe.spec.ts(or documents an intentional skip with a separate env gate)Stripe checkout probe: ready