feat(billing): implement polling for balance update after payment#1975
feat(billing): implement polling for balance update after payment#1975
Conversation
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
Comment |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1975 +/- ##
==========================================
+ Coverage 45.14% 45.44% +0.29%
==========================================
Files 998 1003 +5
Lines 28224 28446 +222
Branches 7384 7451 +67
==========================================
+ Hits 12741 12926 +185
- Misses 14288 14312 +24
- Partials 1195 1208 +13
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (5)
apps/deploy-web/tests/seeders/managedWallet.ts (2)
7-7: Ensure lowercase address charactersAkash addresses are lowercase; enforce casing to avoid sporadic uppercase from faker.
Apply this diff:
- address: `akash${faker.string.alphanumeric({ length: 39 })}`, + address: `akash${faker.string.alphanumeric({ length: 39, casing: "lower" })}`,Based on learnings
10-10: Minor: drop unnecessary literal assertionThe target type already constrains this to the literal; the assertion isn’t needed.
- username: "Managed Wallet" as const, + username: "Managed Wallet",apps/deploy-web/src/queries/queryKeys.ts (1)
76-77: Return an empty key when userId is absent to match existing patternsUsing an empty string creates a cache entry for “no user”; prefer [] like getBalancesKey does.
- static getManagedWalletKey = (userId?: string) => ["MANAGED_WALLET", userId || ""]; + static getManagedWalletKey = (userId?: string) => (userId ? ["MANAGED_WALLET", userId] : []);apps/deploy-web/src/queries/useManagedWalletQuery.ts (1)
10-10: Avoid casting by tightening the key helper’s return typeIf getManagedWalletKey returns a readonly unknown[] (or QueryKey), you can drop the cast here.
Possible signature in queryKeys.ts:
static getManagedWalletKey = (userId?: string): readonly unknown[] => (userId ? ["MANAGED_WALLET", userId] : []);apps/deploy-web/src/pages/_app.tsx (1)
81-89: Avoid overlapping refetches inside the polling loopsetInterval without awaiting can stack concurrent requests; guard with an in‑flight flag and await both refetches.
Example change in PaymentPollingProvider:
const isTickingRef = useRef(false); pollingRef.current = setInterval(async () => { if (isTickingRef.current) return; isTickingRef.current = true; try { const elapsed = Date.now() - (startTimeRef.current || 0); if (elapsed >= MAX_POLLING_DURATION_MS) { stopPolling(); enqueueSnackbar(<d.Snackbar title="Payment processing timeout" subTitle="Please refresh the page to check your balance" iconVariant="warning" />, { variant: "warning" }); return; } await Promise.all([refetchBalance(), refetchManagedWallet()]); } finally { isTickingRef.current = false; } }, POLLING_INTERVAL_MS);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx(1 hunks)apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx(1 hunks)apps/deploy-web/src/context/PaymentPollingProvider/index.ts(1 hunks)apps/deploy-web/src/pages/_app.tsx(2 hunks)apps/deploy-web/src/pages/payment.tsx(5 hunks)apps/deploy-web/src/queries/queryKeys.ts(1 hunks)apps/deploy-web/src/queries/useManagedWalletQuery.ts(2 hunks)apps/deploy-web/src/services/analytics/analytics.service.ts(1 hunks)apps/deploy-web/tests/seeders/analytics.ts(1 hunks)apps/deploy-web/tests/seeders/index.ts(1 hunks)apps/deploy-web/tests/seeders/managedWallet.ts(1 hunks)apps/deploy-web/tests/seeders/snackbar.ts(1 hunks)apps/deploy-web/tests/seeders/walletBalance.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
Never use type any or cast to type any. Always define the proper TypeScript types.
Files:
apps/deploy-web/src/queries/queryKeys.tsapps/deploy-web/tests/seeders/analytics.tsapps/deploy-web/tests/seeders/index.tsapps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsxapps/deploy-web/src/queries/useManagedWalletQuery.tsapps/deploy-web/src/context/PaymentPollingProvider/index.tsapps/deploy-web/src/services/analytics/analytics.service.tsapps/deploy-web/tests/seeders/walletBalance.tsapps/deploy-web/tests/seeders/snackbar.tsapps/deploy-web/src/pages/payment.tsxapps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsxapps/deploy-web/src/pages/_app.tsxapps/deploy-web/tests/seeders/managedWallet.ts
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code
Files:
apps/deploy-web/src/queries/queryKeys.tsapps/deploy-web/tests/seeders/analytics.tsapps/deploy-web/tests/seeders/index.tsapps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsxapps/deploy-web/src/queries/useManagedWalletQuery.tsapps/deploy-web/src/context/PaymentPollingProvider/index.tsapps/deploy-web/src/services/analytics/analytics.service.tsapps/deploy-web/tests/seeders/walletBalance.tsapps/deploy-web/tests/seeders/snackbar.tsapps/deploy-web/src/pages/payment.tsxapps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsxapps/deploy-web/src/pages/_app.tsxapps/deploy-web/tests/seeders/managedWallet.ts
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()to mock dependencies in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under test.
**/*.spec.{ts,tsx}: Usesetupfunction instead ofbeforeEachin test files
setupfunction must be at the bottom of the rootdescribeblock in test files
setupfunction creates an object under test and returns it
setupfunction should accept a single parameter with inline type definition
Don't use shared state insetupfunction
Don't specify return type ofsetupfunction
Files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
apps/{deploy-web,provider-console}/**/*.spec.tsx
📄 CodeRabbit inference engine (.cursor/rules/query-by-in-tests.mdc)
Use
queryBymethods instead ofgetBymethods in test expectations in.spec.tsxfiles
Files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
🧬 Code graph analysis (9)
apps/deploy-web/src/queries/queryKeys.ts (1)
apps/notifications/src/interfaces/rest/services/auth/auth.service.ts (1)
userId(18-25)
apps/deploy-web/tests/seeders/analytics.ts (1)
apps/deploy-web/src/services/analytics/analytics.service.ts (1)
AnalyticsService(142-271)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx (1)
apps/deploy-web/src/services/analytics/analytics.service.ts (1)
analyticsService(278-295)
apps/deploy-web/src/queries/useManagedWalletQuery.ts (2)
apps/deploy-web/src/context/ServicesProvider/ServicesProvider.tsx (1)
useServices(27-29)apps/deploy-web/src/queries/queryKeys.ts (1)
QueryKeys(1-123)
apps/deploy-web/tests/seeders/walletBalance.ts (1)
apps/deploy-web/src/hooks/useWalletBalance.ts (1)
WalletBalance(14-26)
apps/deploy-web/src/pages/payment.tsx (1)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx (1)
usePaymentPolling(183-189)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx (6)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx (3)
PaymentPollingProvider(45-181)usePaymentPolling(183-189)DEPENDENCIES(14-21)apps/deploy-web/tests/seeders/analytics.ts (1)
buildAnalyticsService(5-8)apps/deploy-web/tests/seeders/snackbar.ts (1)
buildSnackbarService(6-10)apps/deploy-web/tests/seeders/wallet.ts (1)
buildWallet(7-25)apps/deploy-web/tests/seeders/managedWallet.ts (1)
buildManagedWallet(4-13)apps/deploy-web/tests/seeders/walletBalance.ts (1)
buildWalletBalance(5-18)
apps/deploy-web/src/pages/_app.tsx (1)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx (1)
PaymentPollingProvider(45-181)
apps/deploy-web/tests/seeders/managedWallet.ts (1)
packages/http-sdk/src/managed-wallet-http/managed-wallet-http.service.ts (1)
ApiManagedWalletOutput(59-59)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: validate / validate-app
- GitHub Check: test-build
🔇 Additional comments (8)
apps/deploy-web/tests/seeders/managedWallet.ts (1)
4-13: Seeder looks goodGood default shape and override precedence. Suits tests.
apps/deploy-web/src/queries/useManagedWalletQuery.ts (1)
10-10: Standardizing the query key via QueryKeys: LGTMConsistent key construction in query and cache update.
Also applies to: 30-30
apps/deploy-web/tests/seeders/walletBalance.ts (1)
5-18: LGTMRealistic ranges and override support look good for tests.
apps/deploy-web/src/services/analytics/analytics.service.ts (1)
72-72: LGTM: new event typeAdding "trial_completed" integrates cleanly; GA mapping safely falls back to the event name.
apps/deploy-web/src/pages/_app.tsx (1)
81-89: Provider placement looks correctWrapping with PaymentPollingProvider above CertificateProvider is sensible and preserves access to Services/Query/Snackbar providers from AppRoot.
apps/deploy-web/src/context/PaymentPollingProvider/index.ts (1)
1-2: Barrel re-exports: LGTMCorrectly exposes runtime and types for consumers.
apps/deploy-web/tests/seeders/index.ts (1)
2-2: Consolidated seeders export: LGTMCentralized imports improve test ergonomics.
Also applies to: 9-9, 14-14, 18-18
apps/deploy-web/src/pages/payment.tsx (1)
48-52: Nice touch wiring polling into the 3DS success flowTriggering
pollForPayment()straight from the 3DS success callback keeps the wallet refresh consistent with the immediate-success path. Looks solid.
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
Outdated
Show resolved
Hide resolved
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
Outdated
Show resolved
Hide resolved
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (6)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx (2)
101-105: Avoid hard‑coding polling durations in testsUsing literal
1000/30000couples tests to internal timings. PreferadvanceTimersToNextTimer()for intervals andrunOnlyPendingTimers()/runAllTimers()for timeouts to reduce brittleness.- jest.advanceTimersByTime(1000); + jest.advanceTimersToNextTimer(); - jest.advanceTimersByTime(30000); + jest.runAllTimers(); // or runOnlyPendingTimers(), depending on intentAlso applies to: 127-131, 167-169
139-153: Strengthen analytics assertionThis only checks the function exists. Consider simulating a balance increase and asserting
analyticsService.track("trial_completed", ...)is called for trial users.I can sketch a helper that updates the mocked
useWalletBalance()return to trigger the success path.apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx (4)
53-54: Use environment‑agnostic timer type
NodeJS.Timeoutcan clash in browser builds. PreferReturnType<typeof setInterval>.- const pollingRef = useRef<NodeJS.Timeout | null>(null); + const pollingRef = useRef<ReturnType<typeof setInterval> | null>(null);
4-4: Type snackbar keys explicitlyUse
SnackbarKeyfor better type safety.-import { useSnackbar } from "notistack"; +import { useSnackbar, type SnackbarKey } from "notistack"; @@ - const loadingSnackbarKeyRef = useRef<string | number | null>(null); + const loadingSnackbarKeyRef = useRef<SnackbarKey | null>(null);Also applies to: 58-58
113-118: Remove unusedwasTrialingRefand its effect
wasTrialingRefis written but never read. Drop it to reduce noise.- const wasTrialingRef = useRef<boolean>(wasTrialing); const initialTrialingRef = useRef<boolean>(wasTrialing); @@ - useEffect( - function updateWasTrialingRef() { - wasTrialingRef.current = wasTrialing; - }, - [wasTrialing] - );Also applies to: 56-56
96-96: Minor: prefer nullish coalescingAvoid treating
0specially;startTimeRefisnumber | null, so??better conveys intent.- const elapsed = Date.now() - (startTimeRef.current || 0); + const elapsed = Date.now() - (startTimeRef.current ?? 0);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx(1 hunks)apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx(1 hunks)apps/deploy-web/tests/seeders/analytics.ts(1 hunks)apps/deploy-web/tests/seeders/snackbar.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/deploy-web/tests/seeders/snackbar.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
Never use type any or cast to type any. Always define the proper TypeScript types.
Files:
apps/deploy-web/tests/seeders/analytics.tsapps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsxapps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code
Files:
apps/deploy-web/tests/seeders/analytics.tsapps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsxapps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()to mock dependencies in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under test.
**/*.spec.{ts,tsx}: Usesetupfunction instead ofbeforeEachin test files
setupfunction must be at the bottom of the rootdescribeblock in test files
setupfunction creates an object under test and returns it
setupfunction should accept a single parameter with inline type definition
Don't use shared state insetupfunction
Don't specify return type ofsetupfunction
Files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
apps/{deploy-web,provider-console}/**/*.spec.tsx
📄 CodeRabbit inference engine (.cursor/rules/query-by-in-tests.mdc)
Use
queryBymethods instead ofgetBymethods in test expectations in.spec.tsxfiles
Files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
🧠 Learnings (6)
📚 Learning: 2025-07-27T12:16:08.566Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/general.mdc:0-0
Timestamp: 2025-07-27T12:16:08.566Z
Learning: Applies to **/*.{ts,tsx} : Never use type any or cast to type any. Always define the proper TypeScript types.
Applied to files:
apps/deploy-web/tests/seeders/analytics.ts
📚 Learning: 2025-07-21T08:24:24.269Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/no-jest-mock.mdc:0-0
Timestamp: 2025-07-21T08:24:24.269Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use `jest.mock()` to mock dependencies in test files. Instead, use `jest-mock-extended` to create mocks and pass mocks as dependencies to the service under test.
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
📚 Learning: 2025-07-21T08:24:27.953Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/query-by-in-tests.mdc:0-0
Timestamp: 2025-07-21T08:24:27.953Z
Learning: Applies to apps/{deploy-web,provider-console}/**/*.spec.tsx : Use `queryBy` methods instead of `getBy` methods in test expectations in `.spec.tsx` files
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
📚 Learning: 2025-07-21T08:25:07.474Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-07-21T08:25:07.474Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `setup` function instead of `beforeEach` in test files
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
📚 Learning: 2025-07-21T08:25:07.474Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-07-21T08:25:07.474Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use shared state in `setup` function
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
📚 Learning: 2025-07-21T08:25:07.474Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-07-21T08:25:07.474Z
Learning: Applies to **/*.spec.{ts,tsx} : `setup` function must be at the bottom of the root `describe` block in test files
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
🧬 Code graph analysis (3)
apps/deploy-web/tests/seeders/analytics.ts (1)
apps/deploy-web/src/services/analytics/analytics.service.ts (1)
AnalyticsService(142-271)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx (1)
apps/deploy-web/src/services/analytics/analytics.service.ts (1)
analyticsService(278-295)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx (6)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx (3)
PaymentPollingProvider(45-181)usePaymentPolling(183-189)DEPENDENCIES(14-21)apps/deploy-web/tests/seeders/analytics.ts (1)
buildAnalyticsService(7-10)apps/deploy-web/tests/seeders/snackbar.ts (1)
buildSnackbarService(14-23)apps/deploy-web/tests/seeders/wallet.ts (1)
buildWallet(7-25)apps/deploy-web/tests/seeders/managedWallet.ts (1)
buildManagedWallet(4-13)apps/deploy-web/tests/seeders/walletBalance.ts (1)
buildWalletBalance(5-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
- GitHub Check: indexer-ci
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: validate / validate-app
- GitHub Check: test-build
🔇 Additional comments (1)
apps/deploy-web/tests/seeders/analytics.ts (1)
3-10: Typed mock looks solid; noanyusageThe seeder correctly types
trackagainst the real service and avoidsany. This keeps tests aligned with production overloads.If TS complains about overloads, I can adjust the mock to a concrete signature union for
track.
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
Show resolved
Hide resolved
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
Outdated
Show resolved
Hide resolved
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx
Show resolved
Hide resolved
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx
Outdated
Show resolved
Hide resolved
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx
Outdated
Show resolved
Hide resolved
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (5)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx (3)
99-109: Guard with ref to avoid start race.Checking only state can race on rapid double‑click before setState flush. Also check the ref which is synchronous.
- (initialBalance?: number | null) => { - if (isPolling) { + (initialBalance?: number | null) => { + if (isPolling || isPollingRef.current) { return; }
90-96: Refetch errors aren’t caught (async).refetchBalance/refetchManagedWallet likely return promises; calling without await makes try/catch ineffective. Consider an async poll that awaits both and handles rejections, then schedules the next tick.
- const executePoll = useCallback(() => { + const executePoll = useCallback(async () => { attemptCountRef.current++; @@ - try { - refetchBalance(); - refetchManagedWallet(); - } catch (error) { - console.error("Error during polling:", error); - } + try { + await Promise.allSettled([refetchBalance(), refetchManagedWallet()]); + } catch (error) { + console.error("Error during polling:", error); + } }, [stopPolling, enqueueSnackbar, refetchBalance, refetchManagedWallet, d]);And trigger it with void executePoll() where called. This also aligns with the earlier “recursive setTimeout waits for work” guidance.
58-59: Remove unused wasTrialingRef.The ref is written but never read; drop the ref and the effect to reduce noise.
- const wasTrialingRef = useRef<boolean>(wasTrialing); @@ - useEffect( - function updateWasTrialingRef() { - wasTrialingRef.current = wasTrialing; - }, - [wasTrialing] - );Also applies to: 124-129
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx (2)
270-293: Type the injected dependencies; remove the double cast.Avoid
unknown as. GivedependenciesandmockSnackbarconcrete types to satisfytypeof DEPENDENCIES.- const dependencies = { + const mockSnackbar: typeof DEPENDENCIES["Snackbar"] = ({ title, subTitle, iconVariant, showLoading }) => ( + <div data-testid="snackbar" data-title={title} data-subtitle={subTitle} data-icon-variant={iconVariant} data-show-loading={showLoading} /> + ); + + const dependencies: typeof DEPENDENCIES = { ...DEPENDENCIES, useWallet: jest.fn(() => wallet), @@ - useSnackbar: jest.fn(() => ({ + useSnackbar: jest.fn((): ReturnType<typeof DEPENDENCIES["useSnackbar"]> => ({ enqueueSnackbar: mockEnqueueSnackbar, closeSnackbar: mockCloseSnackbar })), - Snackbar: mockSnackbar - } as unknown as typeof DEPENDENCIES; + Snackbar: mockSnackbar + };As per coding guidelines.
23-43: Minor: align timer advance with polling interval.Advance by POLLING_INTERVAL_MS (2000) for clarity. Current 1000ms works only because of the immediate first poll.
- jest.advanceTimersByTime(1000); + jest.advanceTimersByTime(2000);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx(1 hunks)apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()to mock dependencies in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under test.
**/*.spec.{ts,tsx}: Usesetupfunction instead ofbeforeEachin test files
setupfunction must be at the bottom of the rootdescribeblock in test files
setupfunction creates an object under test and returns it
setupfunction should accept a single parameter with inline type definition
Don't use shared state insetupfunction
Don't specify return type ofsetupfunction
Files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
apps/{deploy-web,provider-console}/**/*.spec.tsx
📄 CodeRabbit inference engine (.cursor/rules/query-by-in-tests.mdc)
Use
queryBymethods instead ofgetBymethods in test expectations in.spec.tsxfiles
Files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
Never use type any or cast to type any. Always define the proper TypeScript types.
Files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsxapps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code
Files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsxapps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx
🧠 Learnings (5)
📚 Learning: 2025-07-21T08:24:24.269Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/no-jest-mock.mdc:0-0
Timestamp: 2025-07-21T08:24:24.269Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use `jest.mock()` to mock dependencies in test files. Instead, use `jest-mock-extended` to create mocks and pass mocks as dependencies to the service under test.
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
📚 Learning: 2025-07-21T08:24:27.953Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/query-by-in-tests.mdc:0-0
Timestamp: 2025-07-21T08:24:27.953Z
Learning: Applies to apps/{deploy-web,provider-console}/**/*.spec.tsx : Use `queryBy` methods instead of `getBy` methods in test expectations in `.spec.tsx` files
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
📚 Learning: 2025-07-21T08:25:07.474Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-07-21T08:25:07.474Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `setup` function instead of `beforeEach` in test files
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
📚 Learning: 2025-07-21T08:25:07.474Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-07-21T08:25:07.474Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use shared state in `setup` function
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
📚 Learning: 2025-07-21T08:25:07.474Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-07-21T08:25:07.474Z
Learning: Applies to **/*.spec.{ts,tsx} : `setup` function must be at the bottom of the root `describe` block in test files
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
🧬 Code graph analysis (1)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx (1)
apps/deploy-web/src/services/analytics/analytics.service.ts (1)
analyticsService(278-295)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: test-build
- GitHub Check: validate / validate-app
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: validate / validate-app
- GitHub Check: test-build
🔇 Additional comments (5)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx (2)
152-155: Good fix: zero balance guard.Switching to
initialBalanceRef.current == nullcorrectly allows an initial balance of 0.
160-173: Close the loading snackbar on success for both trial and non‑trial users.Today the spinner persists for trial users until trial status flips, showing success and loading together. Close it immediately on success, regardless of trial state.
if (currentTotalBalance > initialBalanceValue) { enqueueSnackbar(<d.Snackbar title="Payment successful!" subTitle="Your balance has been updated" iconVariant="success" />, { variant: "success" }); + if (loadingSnackbarKeyRef.current) { + closeSnackbar(loadingSnackbarKeyRef.current); + loadingSnackbarKeyRef.current = null; + } // If user was not trialing, we can stop polling immediately if (!initialTrialingRef.current) { stopPolling(); return; } analyticsService.track("trial_completed", { category: "user", label: "First payment completed" }); }apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx (3)
10-22: Ensure cleanup runs; restore timers deterministically.Some tests don’t call
cleanup(), leaving fake timers enabled across tests. Wrap each test that callssetup()in try/finally and always invoke cleanup.- it("provides polling context to children", () => { - setup({ ... }); - expect(screen.queryByTestId("is-polling")).toHaveTextContent("false"); - ... - }); + it("provides polling context to children", () => { + const { cleanup } = setup({ ... }); + try { + expect(screen.queryByTestId("is-polling")).toHaveTextContent("false"); + ... + } finally { + cleanup(); + } + });Apply similarly to other tests invoking
setup()without cleanup.
1-9: Good: module mocks removed; DI used instead.
This follows our “no jest.mock in specs” rule and prior feedback.
245-329: Good: timers are set up via setup; no beforeEach/afterEach.
Conforms to the testing guideline.
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx
Outdated
Show resolved
Hide resolved
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx
Show resolved
Hide resolved
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/deploy-web/src/hooks/useManagedWallet.ts (2)
75-81: Minor: simplify constant truths inside thewalletbranch.Inside the truthy
walletbranch,isConfiguredis always true. Consider setting these literals directly to match the API type and avoid boolean widening:- isWalletConnected: isConfigured, - isWalletLoaded: isConfigured, + isWalletConnected: true, + isWalletLoaded: true,This keeps the literal types aligned with
ApiManagedWalletOutputand reduces type friction for consumers.
84-85: AnnotateuseManagedWalletwith an explicit return type
Inapps/deploy-web/src/hooks/useManagedWallet.tsexport aUseManagedWalletResulttype (or interface) and update the hook signature to(): UseManagedWalletResultto lock down its return shape—this will catch future additions (likeisFetching) as type errors in all consumers.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx(1 hunks)apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx(1 hunks)apps/deploy-web/src/hooks/useManagedWallet.ts(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx
- apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
Never use type any or cast to type any. Always define the proper TypeScript types.
Files:
apps/deploy-web/src/hooks/useManagedWallet.ts
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code
Files:
apps/deploy-web/src/hooks/useManagedWallet.ts
🧬 Code graph analysis (1)
apps/deploy-web/src/hooks/useManagedWallet.ts (2)
apps/deploy-web/src/queries/useManagedWalletQuery.ts (2)
useManagedWalletQuery(7-20)useCreateManagedWalletMutation(22-34)packages/http-sdk/src/managed-wallet-http/managed-wallet-http.service.ts (1)
ApiManagedWalletOutput(59-59)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: validate / validate-app
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: test-build
🔇 Additional comments (3)
apps/deploy-web/src/hooks/useManagedWallet.ts (3)
38-38: Dependency array fix is correct.Including
setIsSignedInWithTrialremoves a potential stale-closure pitfall. LGTM.
88-88: Memo deps updated correctly.Including
isFetchingprevents stale values in the returned object. LGTM.
21-25: Semantics change — update callers that relied on isLoading to include background refetches.useManagedWallet now sets isLoading = isInitialLoading || isCreating; background refetches are available via isFetching. Update callers that need refetches counted as “loading” (apps/deploy-web/src/context/WalletProvider/WalletProvider.tsx currently destructures isLoading) — add isFetching and combine (e.g. const isManagedWalletLoading = isManagedWalletLoading || isManagedWalletFetching).
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx (3)
220-222: Remove double assertion; type dependencies and Snackbar precisely.Avoid
as unknown as typeof DEPENDENCIES. Provide correctly typed mocks and a typed dependencies object; type Snackbar via the real dependency type.As per coding guidelines
- const mockSnackbar = ({ title, subTitle, iconVariant, showLoading }: { title: string; subTitle: string; iconVariant?: string; showLoading?: boolean }) => ( + const mockSnackbar: typeof DEPENDENCIES["Snackbar"] = ({ title, subTitle, iconVariant, showLoading }) => ( <div data-testid="snackbar" data-title={title} data-subtitle={subTitle} data-icon-variant={iconVariant} data-show-loading={showLoading} /> ); @@ - const dependencies = { - ...DEPENDENCIES, - useWallet: jest.fn(() => wallet), - useWalletBalance: jest.fn(() => ({ - balance: walletBalance, - refetch: refetchBalance, - isLoading: input.isWalletBalanceLoading - })), - useManagedWallet: jest.fn(() => ({ - wallet: mockManagedWallet, - isLoading: false, - isFetching: false, - createError: null, - refetch: refetchManagedWallet, - create: jest.fn() - })), - useServices: jest.fn(() => ({ - analyticsService - })), - useSnackbar: jest.fn(() => ({ - enqueueSnackbar: mockEnqueueSnackbar, - closeSnackbar: mockCloseSnackbar - })), - Snackbar: mockSnackbar - } as unknown as typeof DEPENDENCIES; + const useWalletMock: typeof DEPENDENCIES["useWallet"] = jest.fn(() => wallet); + const useWalletBalanceMock: typeof DEPENDENCIES["useWalletBalance"] = jest.fn(() => ({ + balance: walletBalance, + refetch: refetchBalance, + isLoading: input.isWalletBalanceLoading + })); + const useManagedWalletMock: typeof DEPENDENCIES["useManagedWallet"] = jest.fn(() => ({ + wallet: mockManagedWallet, + isLoading: false, + isFetching: false, + createError: null, + refetch: refetchManagedWallet, + create: jest.fn() + })); + const useServicesMock: typeof DEPENDENCIES["useServices"] = jest.fn(() => ({ analyticsService })); + const useSnackbarMock: typeof DEPENDENCIES["useSnackbar"] = jest.fn(() => ({ + enqueueSnackbar: mockEnqueueSnackbar, + closeSnackbar: mockCloseSnackbar + })); + + const dependencies: typeof DEPENDENCIES = { + ...DEPENDENCIES, + useWallet: useWalletMock, + useWalletBalance: useWalletBalanceMock, + useManagedWallet: useManagedWalletMock, + useServices: useServicesMock, + useSnackbar: useSnackbarMock, + Snackbar: mockSnackbar + };Also applies to: 233-257
31-32: Optional: prefer userEvent over element.click for realistic interactions.Switching to userEvent improves fidelity and auto‑act behavior. Since fake timers are in use, initialize user with advanceTimers.
Example:
- await act(async () => { - screen.getByTestId("start-polling").click(); - }); + const user = userEvent.setup({ advanceTimers: jest.advanceTimersByTime }); + await user.click(screen.getByTestId("start-polling"));Add once at top:
+import userEvent from "@testing-library/user-event";Also applies to: 37-38, 51-52, 72-73, 94-95, 118-119, 158-159, 178-179
135-149: Increase behavioral coverage: assert analytics fires on balance increase for trial users.Add a test that starts polling with isTrialing=true and initial balance X, then re‑renders provider with balance > X; expect analyticsService.track("trial_completed", …) to be called.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.spec.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/no-jest-mock.mdc)
Don't use
jest.mock()to mock dependencies in test files. Instead, usejest-mock-extendedto create mocks and pass mocks as dependencies to the service under test.
**/*.spec.{ts,tsx}: Usesetupfunction instead ofbeforeEachin test files
setupfunction must be at the bottom of the rootdescribeblock in test files
setupfunction creates an object under test and returns it
setupfunction should accept a single parameter with inline type definition
Don't use shared state insetupfunction
Don't specify return type ofsetupfunction
Files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
apps/{deploy-web,provider-console}/**/*.spec.tsx
📄 CodeRabbit inference engine (.cursor/rules/query-by-in-tests.mdc)
Use
queryBymethods instead ofgetBymethods in test expectations in.spec.tsxfiles
Files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
Never use type any or cast to type any. Always define the proper TypeScript types.
Files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{js,ts,tsx}: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code
Files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
🧠 Learnings (5)
📚 Learning: 2025-07-21T08:24:24.269Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/no-jest-mock.mdc:0-0
Timestamp: 2025-07-21T08:24:24.269Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use `jest.mock()` to mock dependencies in test files. Instead, use `jest-mock-extended` to create mocks and pass mocks as dependencies to the service under test.
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
📚 Learning: 2025-07-21T08:24:27.953Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/query-by-in-tests.mdc:0-0
Timestamp: 2025-07-21T08:24:27.953Z
Learning: Applies to apps/{deploy-web,provider-console}/**/*.spec.tsx : Use `queryBy` methods instead of `getBy` methods in test expectations in `.spec.tsx` files
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
📚 Learning: 2025-07-21T08:25:07.474Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-07-21T08:25:07.474Z
Learning: Applies to **/*.spec.{ts,tsx} : Use `setup` function instead of `beforeEach` in test files
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
📚 Learning: 2025-07-21T08:25:07.474Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-07-21T08:25:07.474Z
Learning: Applies to **/*.spec.{ts,tsx} : Don't use shared state in `setup` function
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
📚 Learning: 2025-07-21T08:25:07.474Z
Learnt from: CR
PR: akash-network/console#0
File: .cursor/rules/setup-instead-of-before-each.mdc:0-0
Timestamp: 2025-07-21T08:25:07.474Z
Learning: Applies to **/*.spec.{ts,tsx} : `setup` function must be at the bottom of the root `describe` block in test files
Applied to files:
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx
🧬 Code graph analysis (1)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx (4)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.tsx (3)
PaymentPollingProvider(46-217)usePaymentPolling(219-225)DEPENDENCIES(15-22)apps/deploy-web/tests/seeders/wallet.ts (1)
buildWallet(7-25)apps/deploy-web/tests/seeders/managedWallet.ts (1)
buildManagedWallet(4-13)apps/deploy-web/tests/seeders/walletBalance.ts (1)
buildWalletBalance(5-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
- GitHub Check: test-build
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: validate / validate-app
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: test-build
- GitHub Check: test-build
🔇 Additional comments (2)
apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx (2)
10-21: Good structure: DI + setup + queryBy in expectations.
- Uses dependency injection and a bottom‑placed setup helper.
- No module‑level jest.mock.
- Expectations use queryBy*. Nice.
As per coding guidelines
11-21: Make timer cleanup deterministic; call cleanup() in every test using setup() and strengthen cleanup.Some tests call setup() but never invoke cleanup(), leaving fake timers active and the component mounted, which can cause cross‑test flakiness. Wrap each test body in try/finally and call cleanup(); also enhance setup’s cleanup to unmount and clear timers.
As per coding guidelines
Example fix for “provides polling context to children”:
- it("provides polling context to children", () => { - setup({ + it("provides polling context to children", () => { + const { cleanup } = setup({ isTrialing: false, balance: { totalUsd: 100 }, isWalletBalanceLoading: false }); - - expect(screen.queryByTestId("is-polling")).toHaveTextContent("false"); - expect(screen.queryByTestId("start-polling")).toBeInTheDocument(); - expect(screen.queryByTestId("stop-polling")).toBeInTheDocument(); + try { + expect(screen.queryByTestId("is-polling")).toHaveTextContent("false"); + expect(screen.queryByTestId("start-polling")).toBeInTheDocument(); + expect(screen.queryByTestId("stop-polling")).toBeInTheDocument(); + } finally { + cleanup(); + } });Repeat the pattern for the tests at these ranges: 23–41, 43–62, 64–84, 135–149.
Also upgrade setup’s cleanup to unmount and restore timers:
@@ - return { + return { refetchBalance, @@ - cleanup: () => { - jest.useRealTimers(); - } + cleanup: () => { + try { + unmount(); + } finally { + jest.clearAllTimers(); + jest.useRealTimers(); + } + } };Run to enumerate where setup() is used vs. cleanup() calls:
#!/bin/bash rg -n 'setup\(' apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsx rg -n 'cleanup\(\)' apps/deploy-web/src/context/PaymentPollingProvider/PaymentPollingProvider.spec.tsxAlso applies to: 23-41, 43-62, 64-84, 135-149
#1967
Summary by CodeRabbit
New Features
Tests
Chores
Quality