fix(billing): support top-up 3DS verification - #14490
Conversation
Amp-Thread-ID: https://ampcode.com/threads/T-019fb904-01d8-771e-beac-9c95ac91f7f8 Co-authored-by: Amp <amp@ampcode.com>
📄 Knowledge reviewDosu skipped reviewing this PR because your organization has used its |
🎨 Storybook: ✅ Built — View Storybook🎭 Playwright: ✅ 1778 passed, 0 failed · 2 flaky📊 Browser Reports
📦 Bundle: 8.19 MB gzip 🟢 -59 BDetailsSummary
Category Glance App Entry Points — 3.62 kB (baseline 3.62 kB) • ⚪ 0 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 1.29 MB (baseline 1.29 MB) • ⚪ 0 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed / 1 unchanged Views & Navigation — 111 kB (baseline 111 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 12 added / 12 removed / 4 unchanged Panels & Settings — 551 kB (baseline 551 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 11 added / 11 removed / 15 unchanged User & Accounts — 28.7 kB (baseline 28.7 kB) • ⚪ 0 BAuthentication, profile, and account management bundles
Status: 7 added / 7 removed / 3 unchanged Editors & Dialogs — 124 kB (baseline 124 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors
Status: 6 added / 6 removed / 1 unchanged UI Components — 70 kB (baseline 70 kB) • ⚪ 0 BReusable component library chunks
Status: 6 added / 6 removed / 9 unchanged Data & Services — 3.44 MB (baseline 3.44 MB) • 🔴 +1.07 kBStores, services, APIs, and repositories
Status: 14 added / 14 removed / 3 unchanged Utilities & Hooks — 386 kB (baseline 386 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 16 added / 16 removed / 20 unchanged Vendor & Third-Party — 15.7 MB (baseline 15.7 MB) • ⚪ 0 BExternal libraries and shared vendor chunks Status: 16 unchanged Other — 12.7 MB (baseline 12.7 MB) • ⚪ 0 BBundles that do not match a named category
Status: 70 added / 70 removed / 210 unchanged ⚡ Performance Report
✅ No regressions detected. All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-07-31T19:09:03.394Z",
"gitSha": "7464b34b7b34e74668aa897e9f3a2e39871f2860",
"branch": "fix/topup-3ds-verification",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2019.5179999999766,
"styleRecalcs": 11,
"styleRecalcDurationMs": 5.882,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 407.87399999999997,
"heapDeltaBytes": -21141608,
"heapUsedBytes": 46778936,
"domNodes": -277,
"jsHeapTotalBytes": 20176896,
"scriptDurationMs": 12.937000000000001,
"eventListeners": -146,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-idle",
"durationMs": 2001.8269999999916,
"styleRecalcs": 10,
"styleRecalcDurationMs": 5.028999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 364.92999999999995,
"heapDeltaBytes": 4596120,
"heapUsedBytes": 72469980,
"domNodes": 20,
"jsHeapTotalBytes": 20312064,
"scriptDurationMs": 12.152999999999999,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1721.8929999999943,
"styleRecalcs": 73,
"styleRecalcDurationMs": 20.913,
"layouts": 12,
"layoutDurationMs": 2.307,
"taskDurationMs": 666.744,
"heapDeltaBytes": -17161824,
"heapUsedBytes": 50670324,
"domNodes": -277,
"jsHeapTotalBytes": 21487616,
"scriptDurationMs": 76.108,
"eventListeners": -146,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1739.6199999999453,
"styleRecalcs": 74,
"styleRecalcDurationMs": 22.048,
"layouts": 12,
"layoutDurationMs": 2.175,
"taskDurationMs": 624.0129999999999,
"heapDeltaBytes": -17714460,
"heapUsedBytes": 50359940,
"domNodes": -278,
"jsHeapTotalBytes": 20439040,
"scriptDurationMs": 73.281,
"eventListeners": -146,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1736.581000000001,
"styleRecalcs": 32,
"styleRecalcDurationMs": 13.124999999999998,
"layouts": 6,
"layoutDurationMs": 0.5690000000000001,
"taskDurationMs": 293.197,
"heapDeltaBytes": 7938936,
"heapUsedBytes": 75820396,
"domNodes": 79,
"jsHeapTotalBytes": 20836352,
"scriptDurationMs": 15.342,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1720.1580000000263,
"styleRecalcs": 32,
"styleRecalcDurationMs": 11.726,
"layouts": 6,
"layoutDurationMs": 0.5090000000000001,
"taskDurationMs": 293.11199999999997,
"heapDeltaBytes": 7918784,
"heapUsedBytes": 75790728,
"domNodes": 78,
"jsHeapTotalBytes": 20836352,
"scriptDurationMs": 14.016999999999998,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 512.5620000000026,
"styleRecalcs": 12,
"styleRecalcDurationMs": 7.085000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 299.06,
"heapDeltaBytes": -12308480,
"heapUsedBytes": 55728960,
"domNodes": 20,
"jsHeapTotalBytes": 21884928,
"scriptDurationMs": 40.4,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66666666666665,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "dom-widget-clipping",
"durationMs": 440.25800000002846,
"styleRecalcs": 13,
"styleRecalcDurationMs": 5.532,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 271.453,
"heapDeltaBytes": -12330944,
"heapUsedBytes": 55541228,
"domNodes": 22,
"jsHeapTotalBytes": 21622784,
"scriptDurationMs": 35.471000000000004,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "large-graph-idle",
"durationMs": 2008.1739999999968,
"styleRecalcs": 9,
"styleRecalcDurationMs": 5.154000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 527.2300000000001,
"heapDeltaBytes": 7824440,
"heapUsedBytes": 67350768,
"domNodes": -281,
"jsHeapTotalBytes": 4517888,
"scriptDurationMs": 62.903,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2039.2850000000067,
"styleRecalcs": 10,
"styleRecalcDurationMs": 5.815,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 531.821,
"heapDeltaBytes": 7921688,
"heapUsedBytes": 67014064,
"domNodes": -279,
"jsHeapTotalBytes": 3993600,
"scriptDurationMs": 63.835,
"eventListeners": -142,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2084.251999999992,
"styleRecalcs": 69,
"styleRecalcDurationMs": 9.878000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 907.5580000000001,
"heapDeltaBytes": 23837904,
"heapUsedBytes": 85449580,
"domNodes": -279,
"jsHeapTotalBytes": 5267456,
"scriptDurationMs": 275.823,
"eventListeners": -142,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2094.1870000000335,
"styleRecalcs": 69,
"styleRecalcDurationMs": 10.015,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 896.056,
"heapDeltaBytes": 10629096,
"heapUsedBytes": 73141540,
"domNodes": -281,
"jsHeapTotalBytes": 5529600,
"scriptDurationMs": 273.48699999999997,
"eventListeners": -174,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3071.250999999961,
"styleRecalcs": 66,
"styleRecalcDurationMs": 11.277,
"layouts": 60,
"layoutDurationMs": 6.068,
"taskDurationMs": 1055.011,
"heapDeltaBytes": 23091028,
"heapUsedBytes": 84769364,
"domNodes": 16,
"jsHeapTotalBytes": 9175040,
"scriptDurationMs": 332.123,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-zoom",
"durationMs": 3087.8400000000283,
"styleRecalcs": 66,
"styleRecalcDurationMs": 11.352,
"layouts": 60,
"layoutDurationMs": 5.741,
"taskDurationMs": 1041.854,
"heapDeltaBytes": 23511064,
"heapUsedBytes": 85050968,
"domNodes": 16,
"jsHeapTotalBytes": 7864320,
"scriptDurationMs": 336.814,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "minimap-idle",
"durationMs": 2013.8000000000034,
"styleRecalcs": 9,
"styleRecalcDurationMs": 5.044000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 538.9399999999999,
"heapDeltaBytes": 7663544,
"heapUsedBytes": 67881672,
"domNodes": -281,
"jsHeapTotalBytes": 5828608,
"scriptDurationMs": 65.71199999999999,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2039.8890000000165,
"styleRecalcs": 10,
"styleRecalcDurationMs": 5.152,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 521.042,
"heapDeltaBytes": 8464876,
"heapUsedBytes": 70565736,
"domNodes": -280,
"jsHeapTotalBytes": 4517888,
"scriptDurationMs": 63.58,
"eventListeners": -144,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 505.6459999999561,
"styleRecalcs": 48,
"styleRecalcDurationMs": 7.027999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 297.815,
"heapDeltaBytes": -12105260,
"heapUsedBytes": 55980588,
"domNodes": 22,
"jsHeapTotalBytes": 22671360,
"scriptDurationMs": 81.783,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 483.73599999996486,
"styleRecalcs": 47,
"styleRecalcDurationMs": 6.952000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 291.91299999999995,
"heapDeltaBytes": -12060868,
"heapUsedBytes": 55961400,
"domNodes": 20,
"jsHeapTotalBytes": 21884928,
"scriptDurationMs": 81.18800000000002,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.799999999999727
},
{
"name": "subgraph-idle",
"durationMs": 2003.896999999995,
"styleRecalcs": 11,
"styleRecalcDurationMs": 6.270999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 360.00100000000003,
"heapDeltaBytes": 4281536,
"heapUsedBytes": 72253976,
"domNodes": 22,
"jsHeapTotalBytes": 20312064,
"scriptDurationMs": 11.232999999999999,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 2005.0790000000234,
"styleRecalcs": 11,
"styleRecalcDurationMs": 5.674,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 411.435,
"heapDeltaBytes": -21527344,
"heapUsedBytes": 46464908,
"domNodes": -277,
"jsHeapTotalBytes": 20439040,
"scriptDurationMs": 11.040000000000001,
"eventListeners": -146,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1689.551999999992,
"styleRecalcs": 77,
"styleRecalcDurationMs": 26.605000000000004,
"layouts": 16,
"layoutDurationMs": 3.1069999999999998,
"taskDurationMs": 569.697,
"heapDeltaBytes": -4639448,
"heapUsedBytes": 63417008,
"domNodes": 64,
"jsHeapTotalBytes": 20836352,
"scriptDurationMs": 60.925000000000004,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1674.463000000003,
"styleRecalcs": 76,
"styleRecalcDurationMs": 22.061999999999998,
"layouts": 16,
"layoutDurationMs": 2.452,
"taskDurationMs": 577.863,
"heapDeltaBytes": -20266968,
"heapUsedBytes": 47804468,
"domNodes": -277,
"jsHeapTotalBytes": 20701184,
"scriptDurationMs": 54.88799999999999,
"eventListeners": -146,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-transition-enter",
"durationMs": 882.8299999999558,
"styleRecalcs": 20,
"styleRecalcDurationMs": 22.399999999999995,
"layouts": 16,
"layoutDurationMs": 8.390000000000002,
"taskDurationMs": 691.7990000000001,
"heapDeltaBytes": 4745288,
"heapUsedBytes": 96615636,
"domNodes": 13673,
"jsHeapTotalBytes": 14155776,
"scriptDurationMs": 19.304999999999996,
"eventListeners": 2369,
"totalBlockingTimeMs": 93,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8107.352999999989,
"styleRecalcs": 249,
"styleRecalcDurationMs": 23.397000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3110.4449999999997,
"heapDeltaBytes": 9423740,
"heapUsedBytes": 70681592,
"domNodes": -279,
"jsHeapTotalBytes": 5529600,
"scriptDurationMs": 873.4490000000001,
"eventListeners": -126,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8112.180999999964,
"styleRecalcs": 249,
"styleRecalcDurationMs": 22.363999999999994,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3187.977,
"heapDeltaBytes": 10010068,
"heapUsedBytes": 69351064,
"domNodes": -280,
"jsHeapTotalBytes": 7626752,
"scriptDurationMs": 915.25,
"eventListeners": -128,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 10620.871999999963,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 10594.491,
"heapDeltaBytes": -50980308,
"heapUsedBytes": 166128972,
"domNodes": -8312,
"jsHeapTotalBytes": -15671296,
"scriptDurationMs": 391.81000000000006,
"eventListeners": -16389,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.219999999999953,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 10677.940000000035,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 10662.710000000001,
"heapDeltaBytes": -43142708,
"heapUsedBytes": 167124956,
"domNodes": -8312,
"jsHeapTotalBytes": -16719872,
"scriptDurationMs": 418.325,
"eventListeners": -16389,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333338,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 13202.041000000008,
"styleRecalcs": 67,
"styleRecalcDurationMs": 11.84099999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 13182.978,
"heapDeltaBytes": -45237600,
"heapUsedBytes": 180041676,
"domNodes": -8312,
"jsHeapTotalBytes": -9711616,
"scriptDurationMs": 654.486,
"eventListeners": -16389,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.219999999999953,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 13777.707999999962,
"styleRecalcs": 68,
"styleRecalcDurationMs": 12.167999999999985,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 13757.688,
"heapDeltaBytes": -65630276,
"heapUsedBytes": 154711104,
"domNodes": -8312,
"jsHeapTotalBytes": -15142912,
"scriptDurationMs": 644.2789999999999,
"eventListeners": -16389,
"totalBlockingTimeMs": 21,
"frameDurationMs": 17.223333333333237,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 434.5329999999876,
"styleRecalcs": 15,
"styleRecalcDurationMs": 13.181999999999999,
"layouts": 2,
"layoutDurationMs": 0.293,
"taskDurationMs": 86.27400000000002,
"heapDeltaBytes": -15985380,
"heapUsedBytes": 51009512,
"domNodes": 132,
"jsHeapTotalBytes": 7204864,
"scriptDurationMs": 6.703,
"eventListeners": 65,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "workflow-execution",
"durationMs": 447.06399999995483,
"styleRecalcs": 14,
"styleRecalcDurationMs": 12.045999999999998,
"layouts": 2,
"layoutDurationMs": 0.2779999999999999,
"taskDurationMs": 89.62299999999999,
"heapDeltaBytes": -16293856,
"heapUsedBytes": 50670832,
"domNodes": 121,
"jsHeapTotalBytes": 7467008,
"scriptDurationMs": 6.635000000000001,
"eventListeners": 67,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.669999999999998,
"p95FrameDurationMs": 16.700000000000273
}
]
} |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe billing operation store exposes authenticated top-up actions for the active workspace. The top-up dialog renders a permission-gated verification button and opens its URL securely. Tests cover workspace scoping, polling, URL protection, window options, and permission changes. ChangesTop-up verification flow
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant BillingOperationStore
participant TopUpCreditsDialogContentWorkspace
participant Browser
BillingOperationStore->>TopUpCreditsDialogContentWorkspace: expose pending top-up action URL
TopUpCreditsDialogContentWorkspace->>Browser: open verification URL with noopener,noreferrer
Possibly related PRs
Suggested labels: Suggested reviewers: Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 inconclusive)
✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.ts`:
- Around line 21-22: Replace the plain hoisted mock values mockCanTopUp and
mockTopupActionOperation with Vue refs created via require('vue') inside
vi.hoisted. Render with top-up permitted and the action initially visible, then
update the action-operation ref after rendering to assert the verification
button appears from polling state; set mockCanTopUp to false, await nextTick(),
and assert the top-up button disappears to cover the revoked-permission case.
In `@src/platform/workspace/stores/billingOperationStore.ts`:
- Around line 241-246: Scope pending top-up detection to the active workspace
instead of relying on global isAddingCredits. In
src/platform/workspace/stores/billingOperationStore.ts:241-246, update the
relevant billing-operation state or selector to use workspace-scoped
topupActionOperation; in
src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.vue:137-140,
disable purchase UI only when the active workspace has a pending top-up; update
corresponding coverage in
src/platform/workspace/stores/billingOperationStore.test.ts:665-683 to verify
operations in other workspaces do not block the dialog.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: dfe2d473-3a59-47e6-86e4-a3d1781422b1
📒 Files selected for processing (4)
src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.tssrc/platform/workspace/components/TopUpCreditsDialogContentWorkspace.vuesrc/platform/workspace/stores/billingOperationStore.test.tssrc/platform/workspace/stores/billingOperationStore.ts
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## main #14490 +/- ##
=======================================
Coverage 78.36% 78.36%
=======================================
Files 1767 1767
Lines 111916 111980 +64
Branches 35579 35612 +33
=======================================
+ Hits 87698 87754 +56
- Misses 23673 23675 +2
- Partials 545 551 +6
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 3 files with indirect coverage changes 🚀 New features to boost your workflow:
|
|
@dante01yoon / @christian-byrne let me know what's your thoughts, We can do it as a follow but I believe we need a e2e test if we don't have one yet |
adding now |
comfydesigner
left a comment
There was a problem hiding this comment.
One layout note — otherwise this matches the verification pattern from the subscription dialog nicely (same label key included 👍).
Amp-Thread-ID: https://ampcode.com/threads/T-019fb904-01d8-771e-beac-9c95ac91f7f8 Co-authored-by: Amp <amp@ampcode.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@browser_tests/tests/dialogs/creditsTile.spec.ts`:
- Around line 342-353: The mocked responses in the settings, prompt, and queue
route handlers are untyped. Update the object literals passed to jsonRoute in
the /api/settings/**, /api/prompt, and /api/queue handlers to use the
corresponding API response interfaces via satisfies, matching the typed billing
mocks and preserving the existing response shapes.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: c8ca4b64-889c-4ebb-920d-3926201dc984
📒 Files selected for processing (1)
browser_tests/tests/dialogs/creditsTile.spec.ts
Amp-Thread-ID: https://ampcode.com/threads/T-019fb904-01d8-771e-beac-9c95ac91f7f8 Co-authored-by: Amp <amp@ampcode.com>
The mocked e2e test is good for deterministic frontend regression coverage. But because this bug exists at the frontend/backend payment boundary, I would love to see one real sandbox smoke test |
|
@coderabbitai approve |
✅ Action performedComments resolved and changes approved. |
|
@dante01yoon Successfully backported to #14505 |
|
@dante01yoon Successfully backported to #14506 |
Summary
Surface the hosted 3DS verification action for pending credit top-ups so customers can complete bank authentication instead of timing out in the top-up dialog.
The reported failure is real. The backend now preserves authentication-required top-ups and publishes
action_url(cloud#5890), but the frontend only rendered action URLs for subscription operations. Top-up polling also retained the generic two-minute timeout after discovering an authentication challenge.Changes
noopener,noreferrerwithout rendering the sensitive hosted URL in the DOM.Review Focus
Testing
pnpm test:unit src/platform/workspace/stores/billingOperationStore.test.ts src/platform/workspace/components/TopUpCreditsDialogContentWorkspace.test.ts(56 passed)pnpm test:browser:local browser_tests/tests/dialogs/creditsTile.spec.ts(4 passed)pnpm test:browser:local browser_tests/tests/dialogs/creditsTile.spec.ts --grep "opens verification" --repeat-each 5(5 passed)pnpm typecheckandpnpm typecheck:browserpnpm exec oxfmt --check <touched files>pnpm exec oxlint --type-aware <touched files>knip --cacheScreenshots
Captured from the real
TopUpCreditsDialogContentWorkspacecomponent with a controlled pending 3DS operation; no hosted payment URL or customer data is present.AS IS
The top-up remains pending with only a loading indicator. No verification action is available.
TO BE
The pending top-up presents Complete verification as the primary action while polling continues.
AS IS → TO BE