Feat: Separate Subscription management and Upgrade options#7419
Feat: Separate Subscription management and Upgrade options#7419christian-byrne merged 2 commits intomainfrom
Conversation
📝 WalkthroughWalkthroughAdds an "Upgrade Plan" localization string, introduces "Manage Subscription" and "Upgrade Plan" buttons to the subscription panel, and integrates Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant UI as SubscriptionPanel.vue
participant Auth as useFirebaseAuthActions
participant Dialog as SubscriptionDialog
participant Billing as Billing Portal
rect rgb(240,248,255)
User->>UI: Click "Manage Subscription"
UI->>Auth: authActions.accessBillingPortal()
Auth->>Billing: Request access / redirect token
Billing-->>User: Open billing portal (redirect)
end
rect rgb(255,250,240)
User->>UI: Click "Upgrade Plan"
UI->>Dialog: showSubscriptionDialog()
Dialog-->>User: Display upgrade dialog
end
Possibly related PRs
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
🎭 Playwright Test Results⏰ Completed at: 12/12/2025, 10:00:45 PM UTC 📈 Summary
📊 Test Reports by Browser
🎉 Click on the links above to view detailed test results for each browser configuration. |
🎨 Storybook Build Status✅ Build completed successfully! ⏰ Completed at: 12/12/2025, 09:51:42 PM UTC 🔗 Links🎉 Your Storybook is ready for review! |
Bundle Size ReportSummary
Category Glance Per-category breakdownApp Entry Points — 3.24 MB (baseline 3.24 MB) • 🔴 +31 BMain entry bundles and manifests
Status: 3 added / 3 removed Graph Workspace — 983 kB (baseline 983 kB) • ⚪ 0 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed Views & Navigation — 6.54 kB (baseline 6.54 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 1 added / 1 removed Panels & Settings — 298 kB (baseline 298 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 6 added / 6 removed UI Components — 178 kB (baseline 178 kB) • ⚪ 0 BReusable component library chunks
Status: 7 added / 7 removed Data & Services — 12.5 kB (baseline 12.5 kB) • ⚪ 0 BStores, services, APIs, and repositories
Status: 2 added / 2 removed Utilities & Hooks — 3.18 kB (baseline 3.18 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 1 added / 1 removed Vendor & Third-Party — 8.56 MB (baseline 8.56 MB) • ⚪ 0 BExternal libraries and shared vendor chunks
Other — 3.81 MB (baseline 3.81 MB) • ⚪ 0 BBundles that do not match a named category
Status: 18 added / 18 removed |
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
tests-ui/**/*.test.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (tests-ui/CLAUDE.md)
tests-ui/**/*.test.{js,ts,jsx,tsx}: Write tests for new features
Follow existing test patterns in the codebase
Use existing test utilities rather than writing custom utilities
Mock external dependencies in tests
Always prefer vitest mock functions over writing verbose manual mocks
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
**/*.{ts,tsx,js,jsx,vue,json}
📄 CodeRabbit inference engine (AGENTS.md)
Code style: Use 2-space indentation, single quotes, no trailing semicolons, and 80-character line width (see
.prettierrc)
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,vue}: Imports must be sorted and grouped by plugin; runpnpm formatbefore committing
Use TypeScript for type safety; never useanytype - use proper TypeScript types
Never useas anytype assertions; fix the underlying type issue instead
Use es-toolkit for utility functions
Write code that is expressive and self-documenting; avoid comments unless absolutely necessary; do not add or retain redundant comments
Keep functions short and functional
Minimize nesting in code (e.g., deeply nestediforforstatements); apply the Arrow Anti-Pattern principle
Avoid mutable state; prefer immutability and assignment at point of declaration
Favor pure functions, especially testable ones
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.ts: Write tests for all changes, especially bug fixes to catch future regressions
Unit/component test files must be named**/*.test.tsor intests-ui/directory
Do not write change detector tests that just assert default values
Do not write tests dependent on non-behavioral features like utility classes or styles
Be parsimonious in testing; do not write redundant tests; see composable tests approach
Follow 'Don't Mock What You Don't Own' principle - avoid mocking external dependencies
Do not write tests that just test the mocks; ensure tests fail when code behaves unexpectedly
Leverage Vitest's mocking utilities where possible for test mocking
Keep module mocks contained in test files; do not use global mutable state within test files; usevi.hoisted()if necessary
For Component testing, use Vue Test Utils and follow advice about making components easy to test
Aim for behavioral coverage of critical and new features in unit tests
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
🧠 Learnings (10)
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Mock external dependencies in tests
Applied to files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-12-09T20:22:23.620Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : Leverage Vitest's mocking utilities where possible for test mocking
Applied to files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Write tests for new features
Applied to files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-12-09T20:22:23.620Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : Keep module mocks contained in test files; do not use global mutable state within test files; use `vi.hoisted()` if necessary
Applied to files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Always prefer vitest mock functions over writing verbose manual mocks
Applied to files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-12-09T20:22:23.620Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : Follow 'Don't Mock What You Don't Own' principle - avoid mocking external dependencies
Applied to files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks
Applied to files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-12-09T03:39:54.501Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7169
File: src/platform/remote/comfyui/jobs/jobTypes.ts:1-107
Timestamp: 2025-12-09T03:39:54.501Z
Learning: In the ComfyUI_frontend project, Zod is on v3.x. Do not suggest Zod v4 standalone validators (z.uuid, z.ulid, z.cuid2, z.nanoid) until an upgrade to Zod 4 is performed. When reviewing TypeScript files (e.g., src/platform/remote/comfyui/jobs/jobTypes.ts) validate against Zod 3 capabilities and avoid introducing v4-specific features; flag any proposal to upgrade or incorporate v4-only validators and propose staying with compatible 3.x patterns.
Applied to files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-12-10T03:09:13.807Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7303
File: src/components/topbar/CurrentUserPopover.test.ts:199-205
Timestamp: 2025-12-10T03:09:13.807Z
Learning: In test files, prefer selecting or asserting on accessible properties (text content, aria-label, role, accessible name) over data-testid attributes. This ensures tests validate actual user-facing behavior and accessibility, reducing reliance on implementation details like test IDs.
Applied to files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
📚 Learning: 2025-12-11T12:25:15.470Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 7358
File: src/components/dialog/content/signin/SignUpForm.vue:45-54
Timestamp: 2025-12-11T12:25:15.470Z
Learning: This repository uses CI automation to format code (pnpm format). Do not include manual formatting suggestions in code reviews for Comfy-Org/ComfyUI_frontend. If formatting issues are detected, rely on the CI formatter or re-run pnpm format. Focus reviews on correctness, readability, performance, accessibility, and maintainability rather than style formatting.
Applied to files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
⏰ 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). (4)
- GitHub Check: test
- GitHub Check: setup
- GitHub Check: lint-and-format
- GitHub Check: collect
| vi.mock('@/composables/auth/useFirebaseAuthActions', () => ({ | ||
| useFirebaseAuthActions: vi.fn(() => ({ | ||
| authActions: vi.fn(() => ({ | ||
| accessBillingPortal: vi.fn() | ||
| })) | ||
| })) | ||
| })) | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find the composable definition
fd -e ts -e js "useFirebaseAuthActions" src/ --exec cat -n {} +Repository: Comfy-Org/ComfyUI_frontend
Length of output: 8410
🏁 Script executed:
find src -name "*useFirebaseAuthActions*" -type fRepository: Comfy-Org/ComfyUI_frontend
Length of output: 116
🏁 Script executed:
rg "useFirebaseAuthActions" --type ts -l | head -20Repository: Comfy-Org/ComfyUI_frontend
Length of output: 712
🏁 Script executed:
find src -path "*composables/auth*" -type f | head -20Repository: Comfy-Org/ComfyUI_frontend
Length of output: 155
🏁 Script executed:
cat -n tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts | head -100Repository: Comfy-Org/ComfyUI_frontend
Length of output: 3639
🏁 Script executed:
rg "export.*function.*useFirebaseAuthActions|export.*const.*useFirebaseAuthActions" -A 15 --type tsRepository: Comfy-Org/ComfyUI_frontend
Length of output: 1375
🏁 Script executed:
rg "useFirebaseAuthActions" -A 20 --type ts --max-count 5Repository: Comfy-Org/ComfyUI_frontend
Length of output: 27592
🏁 Script executed:
wc -l tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tsRepository: Comfy-Org/ComfyUI_frontend
Length of output: 153
🏁 Script executed:
cat -n tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tsRepository: Comfy-Org/ComfyUI_frontend
Length of output: 13161
🏁 Script executed:
cat -n src/platform/cloud/subscription/components/SubscriptionPanel.vue 2>/dev/null | head -150Repository: Comfy-Org/ComfyUI_frontend
Length of output: 6460
🏁 Script executed:
find . -path "*/composables/auth/*" -type f 2>/dev/null | grep -v node_modulesRepository: Comfy-Org/ComfyUI_frontend
Length of output: 159
🏁 Script executed:
git ls-files "src/**/composables/**" | grep -i authRepository: Comfy-Org/ComfyUI_frontend
Length of output: 52
🏁 Script executed:
git ls-files "src/**" | grep -i firebaseRepository: Comfy-Org/ComfyUI_frontend
Length of output: 171
🏁 Script executed:
ls -la src/ 2>/dev/null | head -20Repository: Comfy-Org/ComfyUI_frontend
Length of output: 1179
🏁 Script executed:
git ls-files | grep -E "(useFirebaseAuthActions|SubscriptionPanel)" | head -20Repository: Comfy-Org/ComfyUI_frontend
Length of output: 261
🏁 Script executed:
sed -n '60,70p' src/platform/cloud/subscription/components/SubscriptionPanel.vueRepository: Comfy-Org/ComfyUI_frontend
Length of output: 446
🏁 Script executed:
grep -n "authActions\|useFirebaseAuthActions" src/platform/cloud/subscription/components/SubscriptionPanel.vueRepository: Comfy-Org/ComfyUI_frontend
Length of output: 268
🏁 Script executed:
grep -A 50 "<script" src/platform/cloud/subscription/components/SubscriptionPanel.vue | head -60Repository: Comfy-Org/ComfyUI_frontend
Length of output: 1969
🏁 Script executed:
wc -l src/platform/cloud/subscription/components/SubscriptionPanel.vueRepository: Comfy-Org/ComfyUI_frontend
Length of output: 138
🏁 Script executed:
cat src/platform/cloud/subscription/components/SubscriptionPanel.vueRepository: Comfy-Org/ComfyUI_frontend
Length of output: 16203
🏁 Script executed:
grep -n "authActions\|useFirebaseAuthActions" src/platform/cloud/subscription/composables/useSubscriptionActions.ts -A 3 | head -30Repository: Comfy-Org/ComfyUI_frontend
Length of output: 732
🏁 Script executed:
wc -l src/platform/cloud/subscription/composables/useSubscriptionActions.tsRepository: Comfy-Org/ComfyUI_frontend
Length of output: 142
🏁 Script executed:
cat src/platform/cloud/subscription/composables/useSubscriptionActions.tsRepository: Comfy-Org/ComfyUI_frontend
Length of output: 1999
🏁 Script executed:
grep -B 10 -A 10 "authActions" src/platform/cloud/subscription/components/SubscriptionPanel.vueRepository: Comfy-Org/ComfyUI_frontend
Length of output: 1287
🏁 Script executed:
sed -n '200,300p' src/platform/cloud/subscription/components/SubscriptionPanel.vueRepository: Comfy-Org/ComfyUI_frontend
Length of output: 3579
🏁 Script executed:
file src/platform/cloud/subscription/components/SubscriptionPanel.vueRepository: Comfy-Org/ComfyUI_frontend
Length of output: 114
🏁 Script executed:
tail -100 src/platform/cloud/subscription/components/SubscriptionPanel.vueRepository: Comfy-Org/ComfyUI_frontend
Length of output: 2561
Fix mock shape to match real composable return type and add behavioral test for "Manage Subscription" click.
The mock incorrectly wraps accessBillingPortal in a nested authActions function. The real useFirebaseAuthActions() returns an object with methods directly ({ logout, sendPasswordReset, purchaseCredits, accessBillingPortal, ... }), not nested under a function.
+const accessBillingPortalMock = vi.fn()
+
vi.mock('@/composables/auth/useFirebaseAuthActions', () => ({
- useFirebaseAuthActions: vi.fn(() => ({
- authActions: vi.fn(() => ({
- accessBillingPortal: vi.fn()
- }))
- }))
+ useFirebaseAuthActions: () => ({
+ logout: vi.fn(),
+ sendPasswordReset: vi.fn(),
+ purchaseCredits: vi.fn(),
+ accessBillingPortal: accessBillingPortalMock,
+ fetchBalance: vi.fn(),
+ signInWithGoogle: vi.fn(),
+ signInWithGithub: vi.fn(),
+ signInWithEmail: vi.fn(),
+ signUpWithEmail: vi.fn(),
+ updatePassword: vi.fn(),
+ deleteAccount: vi.fn(),
+ accessError: ref(false),
+ reportError: vi.fn()
+ })
}))Add test for the "Manage Subscription" button click:
it('shows correct UI for active subscription', () => {
mockIsActiveSubscription.value = true
const wrapper = createWrapper()
expect(wrapper.text()).toContain('Manage Subscription')
expect(wrapper.text()).toContain('Add Credits')
})
+
+ it('calls accessBillingPortal when Manage Subscription button is clicked', async () => {
+ mockIsActiveSubscription.value = true
+ const wrapper = createWrapper()
+ const manageButton = wrapper.find('[data-testid="Manage Subscription"]')
+ expect(manageButton.exists()).toBe(true)
+ await manageButton.trigger('click')
+ expect(accessBillingPortalMock).toHaveBeenCalledOnce()
+ })🤖 Prompt for AI Agents
In
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
around lines 78 to 85, the vi.mock currently nests accessBillingPortal under
authActions() but the real useFirebaseAuthActions() returns an object whose
methods are top-level; change the mock to return an object with
accessBillingPortal: vi.fn() (and any other used methods) directly instead of
authActions: vi.fn(...). Then add a behavioral test that renders
SubscriptionPanel, finds the "Manage Subscription" button (by role or text),
simulates a user click (userEvent.click) and asserts that the mocked
accessBillingPortal was called once. Ensure the mock is reset between tests
(vi.clearAllMocks or similar) so the call assertion is reliable.
There was a problem hiding this comment.
Nah, keep the mock simple until we have a real reusable mock.
There was a problem hiding this comment.
@DrJKL, understood! We'll keep the mock simple as-is for now. 👍
🧠 Learnings used
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Mock external dependencies in tests
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : Keep module mocks contained in test files; do not use global mutable state within test files; use `vi.hoisted()` if necessary
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : Leverage Vitest's mocking utilities where possible for test mocking
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Always prefer vitest mock functions over writing verbose manual mocks
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{composables,components}/**/*.{ts,tsx,vue} : Clean up subscriptions in state management to prevent memory leaks
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : For Component testing, use Vue Test Utils and follow advice about making components easy to test
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Write tests for new features
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : Do not write tests that just test the mocks; ensure tests fail when code behaves unexpectedly
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T20:22:23.620Z
Learning: Applies to **/*.test.ts : Follow 'Don't Mock What You Don't Own' principle - avoid mocking external dependencies
## Summary Manage Subscription vs Upgrade Plan ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7419-Feat-Separate-Subscription-management-and-Upgrade-options-2c76d73d36508191a16dd3a25817826f) by [Unito](https://www.unito.io)
Summary
Manage Subscription vs Upgrade Plan
┆Issue is synchronized with this Notion page by Unito