Skip to content

test: add automated coverage for Stripe checkout flow (#153)#160

Merged
lfariabr merged 2 commits intomasterfrom
feat/tests-stripe-checkout-153
Mar 12, 2026
Merged

test: add automated coverage for Stripe checkout flow (#153)#160
lfariabr merged 2 commits intomasterfrom
feat/tests-stripe-checkout-153

Conversation

@lfariabr
Copy link
Owner

@lfariabr lfariabr commented Mar 12, 2026

Backend:

  • stripe.service.test.ts: test-mode stubs for coffee/meeting, StripeServiceError constructor, isStripeServiceError, mapStripeErrorCode (all 4 codes)
  • stripe.mutations.test.ts: extend with meeting product, returnUrl passthrough, INVALID_RETURN_URL → BAD_USER_INPUT mapping

Frontend:

  • useStripeCheckout.test.tsx: redirect on success, GraphQL/network error handling, missing URL guard, analytics tracking (checkout_started + checkout_error)
  • Stripe.test.tsx: meeting product selection, error alert rendering, loading state disables continue button

Summary by CodeRabbit

  • Tests
    • Expanded coverage for checkout flows, including meeting-product checkout and return-URL forwarding with invalid-return-url error mapping verified.
    • Added tests for service stubs (session creation, status as paid/complete, sessionId preservation).
    • Added UI tests for error alerts, toast messages, disabling the continue button while loading, and analytics events for checkout start and failures.

Backend:
- stripe.service.test.ts: test-mode stubs for coffee/meeting, StripeServiceError
  constructor, isStripeServiceError, mapStripeErrorCode (all 4 codes)
- stripe.mutations.test.ts: extend with meeting product, returnUrl passthrough,
  INVALID_RETURN_URL → BAD_USER_INPUT mapping

Frontend:
- useStripeCheckout.test.tsx: redirect on success, GraphQL/network error handling,
  missing URL guard, analytics tracking (checkout_started + checkout_error)
- Stripe.test.tsx: meeting product selection, error alert rendering, loading
  state disables continue button
@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d7cbfa72-0d0b-47a4-93d8-9865d26b927e

📥 Commits

Reviewing files that changed from the base of the PR and between a8b014f and f19d860.

📒 Files selected for processing (2)
  • backend/src/__tests__/unit/stripe.mutations.test.ts
  • frontend/src/__tests__/lib/hooks/useStripeCheckout.test.tsx

Walkthrough

Adds and expands unit tests across backend and frontend to validate Stripe checkout flows: createCheckoutSession behavior (including meeting product and returnUrl), Stripe service stubs and error mappings, hook behavior, async states, error handling, and analytics triggers.

Changes

Cohort / File(s) Summary
Backend — Stripe mutations tests
backend/src/__tests__/unit/stripe.mutations.test.ts
New/expanded tests for createCheckoutSession: meeting product, explicit returnUrl forwarding, and mapping INVALID_RETURN_URLBAD_USER_INPUT in GraphQL errors.
Backend — Stripe service tests
backend/src/__tests__/unit/stripe.service.test.ts
New tests for test-mode stubs: createCheckoutSession (coffee/meeting/extra fields), getCheckoutSessionStatus, StripeServiceError constructors, isStripeServiceError guard, and mapStripeErrorCode mappings.
Frontend — Stripe component tests
frontend/src/__tests__/components/Stripe.test.tsx
Reworked tests to use dynamic mockLoading, added beforeEach reset, and new cases: meeting selection calls startCheckout, error alert rendering, and continue button disabled while loading.
Frontend — useStripeCheckout hook tests
frontend/src/__tests__/lib/hooks/useStripeCheckout.test.tsx
Comprehensive hook tests: loading/redirect behavior, returnUrl capture, mutation params (email/product), GraphQL/network/missing-URL error handling, no-redirect assertions, analytics events, and extensive mocks for side effects.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Suggested labels

frontend

Poem

Tests march in, ruthless and precise, no slack —
Mocks lined up, errors mapped, returnUrl attacked.
Stripe flows inspected, edge cases crucified,
Weakness purged, hard guarantees verified.
Ship it with honor — and better mocks next time.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and directly describes the main change: adding automated test coverage for the Stripe checkout flow across backend and frontend.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/tests-stripe-checkout-153
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/src/__tests__/unit/stripe.mutations.test.ts (1)

4-14: ⚠️ Potential issue | 🟠 Major

Make the Stripe error mock stop lying.

This stub treats any object with a code field as a Stripe service error, but the real guard in backend/src/services/stripe.ts only returns true for instanceof StripeServiceError. That means these resolver tests can pass with dressed-up plain Error objects even if production would route them down the generic error path. Right now the suite is shadowboxing ghosts.

💡 Tighten the mock to match production semantics
-jest.mock('../../services/stripe', () => ({
-  createCheckoutSession: jest.fn(),
-  getCheckoutSessionStatus: jest.fn(),
-  isStripeServiceError: (error: unknown) => !!error && typeof error === 'object' && 'code' in error,
-  mapStripeErrorCode: (code: string) => {
+jest.mock('../../services/stripe', () => {
+  const actual = jest.requireActual('../../services/stripe');
+
+  return {
+    StripeServiceError: actual.StripeServiceError,
+    createCheckoutSession: jest.fn(),
+    getCheckoutSessionStatus: jest.fn(),
+    isStripeServiceError: (error: unknown) => error instanceof actual.StripeServiceError,
+    mapStripeErrorCode: (code: string) => {
       if (code === 'SESSION_NOT_FOUND') return 'NOT_FOUND';
       if (code === 'NOT_CONFIGURED' || code === 'MISSING_PRICE') return 'SERVICE_UNAVAILABLE';
       if (code === 'INVALID_RETURN_URL') return 'BAD_USER_INPUT';
       return 'INTERNAL_SERVER_ERROR';
-  },
-}));
+    },
+  };
+});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/src/__tests__/unit/stripe.mutations.test.ts` around lines 4 - 14, The
mock's isStripeServiceError currently treats any object with a code field as a
StripeServiceError, which diverges from the real guard (it checks instanceof
StripeServiceError); update the mock in the test to call the real constructor
check by using jest.requireActual('../../services/stripe') and returning (error:
unknown) => error instanceof actualModule.StripeServiceError so the mocked
isStripeServiceError mirrors production behavior; keep the rest of the mocked
exports (createCheckoutSession, getCheckoutSessionStatus, mapStripeErrorCode)
the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/src/__tests__/unit/stripe.mutations.test.ts`:
- Around line 141-145: The coffee-path unit test's expected call shape for
createCheckoutSession is missing the forwarded returnUrl field; update the
coffee-path assertion that calls
expect(createCheckoutSession).toHaveBeenCalledWith(...) to include returnUrl:
undefined so it matches the resolver's actual payload (i.e., ensure the expected
object contains productKey, email, and returnUrl: undefined for the
createCheckoutSession call).

In `@frontend/src/__tests__/lib/hooks/useStripeCheckout.test.tsx`:
- Around line 237-249: The test title overstates what it verifies; rename the
test case to remove the ordering claim or explicitly assert ordering. Easiest
fix: change the it(...) description from "tracks checkout_started event before
mutation" to something like "tracks stripe_checkout_started event" to match the
assertion (which only checks mockTrackClientEvent called), referencing the
useStripeCheckout hook, its startCheckout method, and the mockTrackClientEvent
spy; alternatively, if you want ordering enforced, add an explicit assertion
that mockTrackClientEvent was called prior to the network/mutation mock (e.g.,
verify mockTrackClientEvent.mock.invocation order relative to your mutation mock
such as successMock) after invoking result.current.startCheckout.
- Around line 83-84: Replace the ad-hoc typed error object in the test with a
properly constructed GraphQLError instance: remove the "errors: [{ message:
'Return URL must belong to the frontend origin' } as any]" escape hatch and
create new GraphQLError('Return URL must belong to the frontend origin', {
extensions: { /* include the same extension shape used in other tests (e.g.,
code, exception, path, etc.) to match expectations */ } }); this keeps
TypeScript strict mode happy and matches the pattern used in
AuthContext.test.tsx / GogginsDialog.rate-limit.test.tsx / Apod.test.tsx so the
GraphQL-error path is typed correctly.

---

Outside diff comments:
In `@backend/src/__tests__/unit/stripe.mutations.test.ts`:
- Around line 4-14: The mock's isStripeServiceError currently treats any object
with a code field as a StripeServiceError, which diverges from the real guard
(it checks instanceof StripeServiceError); update the mock in the test to call
the real constructor check by using jest.requireActual('../../services/stripe')
and returning (error: unknown) => error instanceof
actualModule.StripeServiceError so the mocked isStripeServiceError mirrors
production behavior; keep the rest of the mocked exports (createCheckoutSession,
getCheckoutSessionStatus, mapStripeErrorCode) the same.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bd7eafe3-4145-4479-82fb-5e922c7da2af

📥 Commits

Reviewing files that changed from the base of the PR and between b07e882 and a8b014f.

📒 Files selected for processing (4)
  • backend/src/__tests__/unit/stripe.mutations.test.ts
  • backend/src/__tests__/unit/stripe.service.test.ts
  • frontend/src/__tests__/components/Stripe.test.tsx
  • frontend/src/__tests__/lib/hooks/useStripeCheckout.test.tsx

- Add returnUrl: undefined to coffee test assertion for explicit coverage
- Use new GraphQLError() instead of as-any cast in hook test
- Rename test to 'tracks stripe_checkout_started event when checkout starts'
@lfariabr lfariabr merged commit d9fd417 into master Mar 12, 2026
8 checks passed
@lfariabr lfariabr deleted the feat/tests-stripe-checkout-153 branch March 12, 2026 19:39
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