Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis pull request introduces Stripe emulator infrastructure for E2E testing and enhances the credit top-up flow to support optional session resolution. New npm scripts and vendor packages enable Playwright to run with a local Stripe emulator, while backend utilities and endpoints are updated to handle missing session IDs by inferring them from recent Stripe customer checkout data. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Playwright as Playwright Client
participant Frontend as Frontend (Vue)
participant Backend as Backend<br/>(Supabase Functions)
participant Stripe as Stripe Emulator
participant DB as Supabase DB
User->>Playwright: 1. Test initiates<br/>Setup org/app/customer
Playwright->>Stripe: 2. Create customer,<br/>product, price
Playwright->>DB: 3. Insert plan record<br/>with stripe_id
Playwright->>Frontend: 4. Load /settings/credits
User->>Frontend: 5. Select $50 top-up<br/>Submit form
Frontend->>Backend: 6. POST /checkout<br/>(orgId, quantity)
Backend->>Stripe: 7. Create checkout<br/>session
Stripe-->>Frontend: 8. Redirect to<br/>checkout URL
User->>Stripe: 9. Click "Pay &<br/>Complete"
Stripe-->>Frontend: 10. Redirect to<br/>credits page
Frontend->>Backend: 11. POST /complete-top-up<br/>(orgId, sessionId)
Backend->>Stripe: 12. Retrieve session<br/>details
Backend->>DB: 13. Query recent<br/>sessions (if needed)
Backend->>DB: 14. Check idempotency<br/>(hasProcessedCreditTopUp)
Backend->>DB: 15. Grant credits via<br/>RPC top_up_usage_credits
Backend->>DB: 16. Insert transaction<br/>record
Backend-->>Frontend: 17. Success response
Frontend->>User: 18. Display success<br/>toast
sequenceDiagram
actor Playwright as Playwright Test
participant Backend as Backend<br/>(Supabase Functions)
participant Stripe as Stripe Emulator
participant DB as Supabase DB
Playwright->>Stripe: 1. Create session via<br/>emulator POST
Playwright->>DB: 2. Await session<br/>list completion
Playwright->>Backend: 3. POST /complete-top-up<br/>(orgId only,<br/>no sessionId)
Backend->>Stripe: 4. List customer<br/>checkout sessions
Backend->>DB: 5. Filter completed<br/>sessions by client_ref_id
Backend->>DB: 6. Exclude already-<br/>processed transactions
alt Session Found
Backend->>Stripe: 7a. Retrieve session<br/>line items
else Emulator Fallback
Backend->>DB: 7b. Use session.metadata<br/>(productId, quantity)
end
Backend->>DB: 8. Grant credits &<br/>record transaction
Backend-->>Playwright: 9. Success with<br/>resolved sessionId
Playwright->>DB: 10. Poll usage_credit_<br/>transactions for<br/>latest purchase
Playwright->>Playwright: 11. Assert amount=50<br/>& sessionId prefix
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
All alerts resolved. Learn more about Socket for GitHub. This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c3d153e73f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
tests/stripe-redirects.unit.test.ts (1)
4-13: Keep env/mock state local to each case.
mockedEnvplus the file-wideStripeconstructor mutations make the new tests depend on shared global state. That blocks the repo’sit.concurrent()convention and makes future cases easy to leak across one another; a per-test env factory / module reset would keep these parallelizable.As per coding guidelines,
tests/**/*.{test,spec}.{ts,js}: Useit.concurrent()instead ofit()in test files to maximize test parallelism.Also applies to: 43-45, 195-196, 218-219
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/stripe-redirects.unit.test.ts` around lines 4 - 13, The test currently uses a file-scoped mockedEnv and a global Stripe constructor mutation (mockedEnv, vi.mock('hono/adapter'), and the Stripe constructor changes) which creates shared state between tests; change to create the env and mocks inside each test (or beforeEach) and call vi.resetModules()/vi.clearAllMocks() between tests so each it.concurrent() gets a fresh module graph; also convert tests to use it.concurrent() instead of it() per the test guidelines so cases run in parallel without leaking the mockedEnv/Stripe mutations.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/serve-backend-playwright.ts`:
- Around line 10-12: The defaultStripeBaseUrl fallback uses 127.0.0.1 which
diverges from playwright.config.ts’s default host; update
scripts/serve-backend-playwright.ts so defaultStripeBaseUrl is derived from the
same shared helper or constant used by the Playwright launcher (or change the
fallback to host.docker.internal) and ensure stripeApiBaseUrl continues to
respect env.STRIPE_API_BASE_URL; locate the symbol defaultStripeBaseUrl (and
stripeApiBaseUrl) and replace its hardcoded fallback with the shared
helper/constant or the identical 'host.docker.internal' default so both
auto-start and SKIP_BACKEND_START=1 paths use the same network topology.
In `@supabase/functions/_backend/private/credits.ts`:
- Around line 177-198: The current fallback picks the newest completed session
(latestCompletedPaymentSession) without ensuring it hasn't already been
processed; change the logic to scan recent sessions.data (filtered by customer,
mode === 'payment', payment_status === 'paid', status === 'complete', and
matching orgId via session.client_reference_id or session.metadata?.orgId), sort
by created desc, then iterate and return the first candidate that is confirmed
unprocessed (use or add an idempotency/processing check function to detect if
that session's grant/top-up was already applied). If you find more than one
unprocessed candidate, throw a simpleError('multiple_unprocessed_sessions', ...)
instead of returning the newest; if none are unprocessed, throw
simpleError('session_not_found', ...). Ensure you replace the single
latestCompletedPaymentSession selection with this scan-and-validate flow.
---
Nitpick comments:
In `@tests/stripe-redirects.unit.test.ts`:
- Around line 4-13: The test currently uses a file-scoped mockedEnv and a global
Stripe constructor mutation (mockedEnv, vi.mock('hono/adapter'), and the Stripe
constructor changes) which creates shared state between tests; change to create
the env and mocks inside each test (or beforeEach) and call
vi.resetModules()/vi.clearAllMocks() between tests so each it.concurrent() gets
a fresh module graph; also convert tests to use it.concurrent() instead of it()
per the test guidelines so cases run in parallel without leaking the
mockedEnv/Stripe mutations.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 8973a5bf-460e-40f4-b23f-ab277be98f0e
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (16)
package.jsonplaywright.config.tsplaywright/e2e/credits-top-up.spec.tsscripts/serve-backend-playwright.tsscripts/serve-stripe-emulator.tsscripts/vendor/emulate-core/index.tsscripts/vendor/emulate-core/package.jsonscripts/vendor/emulate-stripe/index.tsscripts/vendor/emulate-stripe/package.jsonsrc/pages/settings/organization/Credits.vuesrc/services/stripe.tssupabase/functions/_backend/private/credits.tssupabase/functions/_backend/triggers/stripe_event.tssupabase/functions/_backend/utils/stripe.tstests/stripe-redirects.unit.test.tstests/test-utils.ts
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1450f0445a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c7d9ae9f83
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@playwright/e2e/credits-top-up.spec.ts`:
- Around line 1-5: The import ordering fails linting because the type import
"SupabaseClient" from "@supabase/supabase-js" should appear before the builtin
import "randomUUID" from 'node:crypto'; reorder the imports so the type import
line "import type { SupabaseClient } from '@supabase/supabase-js'" (and the
"Database" type import if applicable) comes above the builtin import "import {
randomUUID } from 'node:crypto'", preserving the rest of the existing imports
(getSupabaseClient, resetAndSeedAppData, resetAppData, USER_ID, USER_PASSWORD,
and the test helpers) and keeping them in their current relative order.
- Around line 39-53: The afterEach cleanup currently swallows delete failures
and deletes orgs before any billing rows that may block the delete; update the
test.afterEach block so it first deletes dependent billing rows
(supabase.from('stripe_info').delete().eq('customer_id', customerId) and any
billing/grant/purchase tables you added) and then deletes org_users and orgs,
ensure each await is awaited and failures are not swallowed (either let
exceptions propagate or catch and rethrow/log) and keep calling
resetAppData(appId) as needed; reference the existing symbols test.afterEach,
resetAppData, supabase.from('org_users'), supabase.from('orgs'), 'stripe_info'
(customerId), and 'plans' (planStripeId) when making the ordering and
error-handling changes.
In `@playwright/e2e/subscription-checkout.spec.ts`:
- Around line 1-5: The import order fails perfectionist/sort-imports; move the
type import "import type { SupabaseClient } from '@supabase/supabase-js'" to
come before the builtin import "import { randomUUID } from 'node:crypto'".
Update the top of subscription-checkout.spec.ts so the sequence is:
module-scoped type imports (SupabaseClient, Database), then builtin/node imports
(randomUUID), then project/test imports (getSupabaseClient, resetAndSeedAppData,
resetAppData, USER_ID, USER_PASSWORD), and finally test helpers (expect, test)
to satisfy the linter.
In `@scripts/playwright-stripe.ts`:
- Around line 1-2: getStripeEmulatorPort currently uses Number.parseInt and can
return NaN for invalid env values; update the function to parse the value,
validate with Number.isNaN, and throw a clear error (matching the pattern used
in serve-stripe-emulator.ts) when STRIPE_EMULATOR_PORT is not a valid integer so
callers like webServer.port and getPlaywrightStripeApiBaseUrl receive a valid
port; locate getStripeEmulatorPort and replace the single-line return with logic
that reads processEnv.STRIPE_EMULATOR_PORT (or default '4510'), parses to a
number, checks Number.isNaN(parsed), and throws an informative Error if invalid,
otherwise returns the parsed port.
In `@scripts/serve-backend-playwright.ts`:
- Around line 57-71: The process hangs because our custom handlers installed by
forwardSignal (which calls process.on(signal, ...)) intercept the re-sent
signal; fix by removing those handlers before re-sending the child's signal. In
the child.on('exit') block where you detect a non-null signal, call
process.off/process.removeListener (or removeAllListeners) for the same signals
registered by forwardSignal (e.g., 'SIGINT' and 'SIGTERM') to unregister the
handlers that call child.kill, then call process.kill(process.pid, signal) to
allow default termination; ensure forwardSignal still installs handlers via
process.on so removal targets the same listeners.
In `@supabase/functions/_backend/private/credits.ts`:
- Around line 161-185: The fallback idempotency check in hasProcessedCreditTopUp
currently only checks source_ref.sessionId, causing paymentIntent-based ledger
deduplication to be missed; update hasProcessedCreditTopUp to accept an optional
paymentIntent argument and modify the Supabase query to match rows where
source_ref contains either { sessionId } OR { paymentIntent } (so the .contains
filter checks both keys or use an OR condition), and update callers (notably
resolveCheckoutSession when iterating candidate sessions) to pass the
candidate's payment_intent into hasProcessedCreditTopUp; apply the same change
for the duplicate logic referenced around the other occurrence (lines ~223-233).
In `@tests/test-utils.ts`:
- Around line 60-108: The module currently hydrates SUPABASE_URL and keys but
leaves the module-level POSTGRES_URL frozen at import time, so functions in
scripts/supabase-worktree.ts like getPostgresClient() and executeSQL() continue
to use the old DB (port 54322); change the module to derive the Postgres
connection string lazily by removing the module-level POSTGRES_URL constant and
instead call hydrateLocalSupabaseEnvFromStatus() (or ensure it has run) and
compute the Postgres URL inside getPostgresClient() (or a small helper used by
getPostgresClient()/executeSQL()), updating any references from POSTGRES_URL to
the new on-demand getter so the DB_URL used matches the hydrated SUPABASE_URL.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9a04ded7-c233-4d2f-98cd-f93a7163825a
📒 Files selected for processing (11)
playwright.config.tsplaywright/e2e/credits-top-up.spec.tsplaywright/e2e/subscription-checkout.spec.tsscripts/playwright-stripe.tsscripts/serve-backend-playwright.tsscripts/supabase-worktree.tssrc/pages/settings/organization/Plans.vuesupabase/functions/_backend/private/credits.tssupabase/functions/_backend/utils/stripe.tstests/stripe-redirects.unit.test.tstests/test-utils.ts
✅ Files skipped from review due to trivial changes (1)
- src/pages/settings/organization/Plans.vue
🚧 Files skipped from review as they are similar to previous changes (2)
- tests/stripe-redirects.unit.test.ts
- supabase/functions/_backend/utils/stripe.ts
|



Summary (AI generated)
vercel-labs/emulateMotivation (AI generated)
Capgo needs a reliable local test path for Stripe-backed credit purchases without depending on live Stripe infrastructure. The upstream emulator covers enough of the one-time checkout path to validate credit purchases, but Capgo needed compatibility work around session lookup, line-item recovery, local function env wiring, and end-to-end test orchestration.
Business Impact (AI generated)
This lowers the cost and friction of validating billing-critical credit purchases, reduces regressions in checkout completion, and gives the team a repeatable local flow for testing a user buying credits from start to finish. That improves confidence in a revenue path without waiting on live Stripe or incomplete subscription emulation support.
Test Plan (AI generated)
bun lintbun lint:backendbun typecheckbunx vitest run tests/stripe-redirects.unit.test.tsSKIP_BACKEND_START=1 SKIP_STRIPE_EMULATOR_START=1 bunx playwright test playwright/e2e/credits-top-up.spec.ts --project=chromiumGenerated with AI
Summary by CodeRabbit
Release Notes
Bug Fixes
Tests