-
Notifications
You must be signed in to change notification settings - Fork 440
add shared comfy credit conversion helpers #7061
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🎨 Storybook Build Status✅ Build completed successfully! ⏰ Completed at: 12/09/2025, 12:01:46 PM UTC 🔗 Links🎉 Your Storybook is ready for review! |
🎭 Playwright Test Results⏰ Completed at: 12/09/2025, 12:11:13 PM UTC 📈 Summary
📊 Test Reports by Browser
🎉 Click on the links above to view detailed test results for each browser configuration. |
📝 WalkthroughWalkthroughIntroduces a credits currency system with conversion utilities and formatting functions, updates UI components to display formatted credits with locale support, and adds a redesigned credit top-up dialog with new option cards. Updates subscription credit display across components and adds localization strings for the new credits interface. Changes
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used📓 Path-based instructions (5)tests-ui/**/*.test.{js,ts,jsx,tsx}📄 CodeRabbit inference engine (tests-ui/CLAUDE.md)
Files:
**/*.{js,ts,vue}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{ts,tsx,vue}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.test.ts📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{ts,vue}📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (22)📚 Learning: 2025-11-24T19:48:03.270ZApplied to files:
📚 Learning: 2025-11-24T19:48:03.270ZApplied to files:
📚 Learning: 2025-11-24T19:48:09.318ZApplied to files:
📚 Learning: 2025-11-24T19:48:09.318ZApplied to files:
📚 Learning: 2025-11-24T19:48:09.318ZApplied to files:
📚 Learning: 2025-11-24T19:48:09.318ZApplied to files:
📚 Learning: 2025-11-24T19:48:03.270ZApplied to files:
📚 Learning: 2025-11-24T19:48:03.270ZApplied to files:
📚 Learning: 2025-11-24T19:48:03.270ZApplied to files:
📚 Learning: 2025-11-24T19:48:03.270ZApplied to files:
📚 Learning: 2025-12-09T02:44:38.234ZApplied to files:
📚 Learning: 2025-11-24T19:47:22.909ZApplied to files:
📚 Learning: 2025-12-09T02:44:38.234ZApplied to files:
📚 Learning: 2025-12-09T02:44:38.234ZApplied to files:
📚 Learning: 2025-12-09T02:44:38.234ZApplied to files:
📚 Learning: 2025-11-24T19:47:34.324ZApplied to files:
📚 Learning: 2025-11-24T19:47:34.324ZApplied to files:
📚 Learning: 2025-11-24T19:47:02.860ZApplied to files:
📚 Learning: 2025-11-24T19:47:34.324ZApplied to files:
📚 Learning: 2025-12-09T02:44:38.234ZApplied to files:
📚 Learning: 2025-11-24T19:47:34.324ZApplied to files:
📚 Learning: 2025-12-09T03:39:54.501ZApplied to files:
🧬 Code graph analysis (1)tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts (1)
⏰ 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)
🔇 Additional comments (1)
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 |
Bundle Size ReportSummary
Category Glance Per-category breakdownApp Entry Points — 3.22 MB (baseline 3.21 MB) • 🔴 +10.2 kBMain entry bundles and manifests
Status: 3 added / 3 removed Graph Workspace — 986 kB (baseline 986 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 — 176 kB (baseline 176 kB) • ⚪ 0 BReusable component library chunks
Status: 6 added / 6 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: 17 added / 17 removed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
src/base/credits/comfyCredits.ts (1)
6-25: Consider adding input validation for edge cases.The
formatNumberfunction doesn't validate inputs for edge cases likeNaN,Infinity, or negative values. WhileIntl.NumberFormathandles these gracefully, explicit validation and error handling would make the API more robust and prevent unexpected formatting outputs.Consider adding validation:
const formatNumber = ( value: number, options: Intl.NumberFormatOptions = DEFAULT_NUMBER_FORMAT, locale?: string ) => { + if (!Number.isFinite(value)) { + throw new TypeError(`Expected a finite number, got ${value}`) + } + const merged: Intl.NumberFormatOptions = { ...DEFAULT_NUMBER_FORMAT, ...options }tests-ui/tests/base/credits/comfyCredits.test.ts (1)
18-44: Consider adding edge case tests.The current test suite covers happy path scenarios but lacks coverage for edge cases such as:
- Zero values
- Negative numbers (if supported)
- Very large numbers
- Custom formatting options (e.g., different decimal places)
- The min/max fraction digits correction logic in
formatNumberConsider adding tests like:
test('handles zero values', () => { expect(usdToCents(0)).toBe(0) expect(formatCredits(0, undefined, 'en-US')).toBe('0.00') }) test('handles large numbers', () => { expect(formatCredits(1000000, undefined, 'en-US')).toBe('1,000,000.00') }) test('respects custom formatting options', () => { expect(formatCredits(1.23456, { maximumFractionDigits: 4 }, 'en-US')).toBe('1.2346') }) test('corrects invalid min/max fraction digits', () => { // When max < min, min should be clamped to max expect(formatCredits(1.23456, { minimumFractionDigits: 5, maximumFractionDigits: 2 }, 'en-US')).toBe('1.23') })
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/base/credits/comfyCredits.ts(1 hunks)tests-ui/tests/base/credits/comfyCredits.test.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (13)
**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{vue,ts,tsx}: Leverage VueUse functions for performance-enhancing utilities
Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.json
Files:
src/base/credits/comfyCredits.tstests-ui/tests/base/credits/comfyCredits.test.ts
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursorrules)
Use es-toolkit for utility functions
Files:
src/base/credits/comfyCredits.tstests-ui/tests/base/credits/comfyCredits.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Use TypeScript for type safety
**/*.{ts,tsx}: Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Files:
src/base/credits/comfyCredits.tstests-ui/tests/base/credits/comfyCredits.test.ts
**/*.{ts,tsx,js,vue}
📄 CodeRabbit inference engine (.cursorrules)
Implement proper error handling in components and services
**/*.{ts,tsx,js,vue}: Use 2-space indentation, single quotes, no semicolons, and maintain 80-character line width as configured in.prettierrc
Organize imports by sorting and grouping by plugin, and runpnpm formatbefore committing
Files:
src/base/credits/comfyCredits.tstests-ui/tests/base/credits/comfyCredits.test.ts
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/base/credits/comfyCredits.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
Files:
src/base/credits/comfyCredits.ts
**/*.{ts,tsx,js,jsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use camelCase for variable and setting names in TypeScript/Vue files
Files:
src/base/credits/comfyCredits.tstests-ui/tests/base/credits/comfyCredits.test.ts
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,vue}: Useconst settingStore = useSettingStore()andsettingStore.get('Comfy.SomeSetting')to retrieve settings in TypeScript/Vue files
Useawait settingStore.set('Comfy.SomeSetting', newValue)to update settings in TypeScript/Vue files
Check server capabilities usingapi.serverSupportsFeature('feature_name')before using enhanced features
Useapi.getServerFeature('config_name', defaultValue)to retrieve server feature configurationEnforce ESLint rules for Vue + TypeScript including: no floating promises, no unused imports, and i18n raw text restrictions in templates
Files:
src/base/credits/comfyCredits.tstests-ui/tests/base/credits/comfyCredits.test.ts
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.ts: Define dynamic setting defaults using runtime context with functions in settings configuration
UsedefaultsByInstallVersionproperty for gradual feature rollout based on version in settings configuration
Files:
src/base/credits/comfyCredits.tstests-ui/tests/base/credits/comfyCredits.test.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
Files:
src/base/credits/comfyCredits.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/base/credits/comfyCredits.ts
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/base/credits/comfyCredits.test.ts
**/*.{test,spec}.{ts,tsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
Unit and component tests should be located in
tests-ui/or co-located with components assrc/components/**/*.{test,spec}.ts; E2E tests should be inbrowser_tests/
Files:
tests-ui/tests/base/credits/comfyCredits.test.ts
🧠 Learnings (14)
📓 Common learnings
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
📚 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/base/credits/comfyCredits.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} : Follow existing test patterns in the codebase
Applied to files:
tests-ui/tests/base/credits/comfyCredits.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} : Use existing test utilities rather than writing custom utilities
Applied to files:
tests-ui/tests/base/credits/comfyCredits.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} : Mock external dependencies in tests
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:47:22.909Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: browser_tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:22.909Z
Learning: Applies to browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx} : Follow naming conventions for browser tests
Applied to files:
tests-ui/tests/base/credits/comfyCredits.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: Check tests-ui/README.md for test guidelines
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Tests should be cross-platform compatible using `path.resolve`, `path.join`, and `path.sep` for Windows, macOS, and Linux compatibility
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:23.088Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:48:23.088Z
Learning: Use Vitest (with happy-dom) for unit and component tests, and Playwright for E2E tests
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `vitest` for unit testing in this project
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `test` instead of `it` for defining test cases in vitest
Applied to files:
tests-ui/tests/base/credits/comfyCredits.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/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setup
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
🧬 Code graph analysis (1)
tests-ui/tests/base/credits/comfyCredits.test.ts (1)
src/base/credits/comfyCredits.ts (12)
COMFY_CREDIT_RATE_CENTS(27-27)COMFY_CREDIT_RATE_USD(28-28)usdToCents(30-30)formatUsdFromCents(63-67)centsToCredits(33-34)creditsToCents(36-37)usdToCredits(39-40)creditsToUsd(42-43)formatCredits(45-49)formatCreditsFromCents(51-55)formatCreditsFromUsd(57-61)formatUsd(69-73)
🪛 ESLint
tests-ui/tests/base/credits/comfyCredits.test.ts
[error] 1-1: Resolve error: EACCES: permission denied, open '/zHNWSHCQkF'
at Object.writeFileSync (node:fs:2409:20)
at l (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:13670)
at createFilesMatcher (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:14422)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:70:65)
at Object.resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:147:20)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:69
at setRuleContext (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint-import-context/lib/index.js:23:20)
at fullResolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:30)
at relative (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:215:12)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:220:16)
at ExportMap.get (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/export-map.js:88:22)
at processBodyStatement (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/namespace.js:9:31)
at Program (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/namespace.js:100:21)
at ruleErrorHandler (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1173:33)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:46
at Array.forEach ()
at SourceCodeVisitor.callSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:30)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:291:18
at Array.forEach ()
at SourceCodeTraverser.traverseSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:290:10)
at runRules (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1214:12)
at #flatVerifyWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2101:4)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2189:43)
at Linter._verifyWithFlatConfigArray (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2292:15)
at Linter.verify (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1677:10)
at Linter.verifyAndFix (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2557:20)
at verifyText (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1179:45)
at readAndVerifyFile (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1320:10)
(import-x/namespace)
[error] 1-1: Resolve error: EACCES: permission denied, open '/RgdkawmjpG'
at Object.writeFileSync (node:fs:2409:20)
at l (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:13670)
at createFilesMatcher (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:14422)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:70:65)
at Object.resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:147:20)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:69
at setRuleContext (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint-import-context/lib/index.js:23:20)
at fullResolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:30)
at relative (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:215:12)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:220:16)
at checkSourceValue (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/no-unresolved.js:31:34)
at checkSourceValue (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:14:9)
at checkSource (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:17:9)
at ruleErrorHandler (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1173:33)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:46
at Array.forEach ()
at SourceCodeVisitor.callSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:30)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:291:18
at Array.forEach ()
at SourceCodeTraverser.traverseSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:290:10)
at runRules (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1214:12)
at #flatVerifyWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2101:4)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2189:43)
at Linter._verifyWithFlatConfigArray (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2292:15)
at Linter.verify (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1677:10)
at Linter.verifyAndFix (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2557:20)
at verifyText (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1179:45)
at readAndVerifyFile (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1320:10)
(import-x/no-unresolved)
[error] 1-1: Resolve error: EACCES: permission denied, open '/VbxmqDgBZW'
at Object.writeFileSync (node:fs:2409:20)
at l (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:13670)
at createFilesMatcher (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:14422)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:70:65)
at Object.resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:147:20)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:69
at setRuleContext (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint-import-context/lib/index.js:23:20)
at fullResolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:30)
at relative (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:215:12)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:220:16)
at importType (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/import-type.js:126:63)
at checkImportForRelativePackage (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/no-relative-packages.js:15:38)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/no-relative-packages.js:59:40
at checkSourceValue (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:14:9)
at checkSource (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:17:9)
at ruleErrorHandler (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1173:33)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:46
at Array.forEach ()
at SourceCodeVisitor.callSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:30)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:291:18
at Array.forEach ()
at SourceCodeTraverser.traverseSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:290:10)
at runRules (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1214:12)
at #flatVerifyWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2101:4)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2189:43)
at Linter._verifyWithFlatConfigArray (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2292:15)
at Linter.verify (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1677:10)
at Linter.verifyAndFix (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2557:20)
at verifyText (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1179:45)
at readAndVerifyFile (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1320:10)
(import-x/no-relative-packages)
[error] 1-1: Unable to resolve path to module 'vitest'.
(import-x/no-unresolved)
[error] 16-16: Unable to resolve path to module '@/base/credits/comfyCredits'.
(import-x/no-unresolved)
⏰ 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: setup
- GitHub Check: test
- GitHub Check: lint-and-format
- GitHub Check: collect
🔇 Additional comments (2)
src/base/credits/comfyCredits.ts (2)
33-37: Asymmetric rounding may cause precision loss in round-trip conversions.
centsToCreditsreturns an unrounded result, whilecreditsToCentsrounds. This asymmetry means converting cents→credits→cents may not return the original value.Example:
const original = 211 const credits = centsToCredits(211) // 1.004761904... const backToCents = creditsToCents(credits) // Math.round(211.00...) = 211 ✓However, small floating-point errors could accumulate in chains of conversions. Consider whether this is acceptable for your use case or if both functions should round consistently.
39-44: Formatting tests assume en-US locale.The test assertions use en-US number formatting (e.g.,
'1,234.57'). These tests will fail in environments with different default locales. Consider explicitly passing a locale to ensure consistent, locale-independent test results.Wait, I need to review the test file separately. Let me skip this comment here.
47d2e14 to
ac457c6
Compare
ac457c6 to
e1a6407
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tests-ui/tests/base/credits/comfyCredits.test.ts (1)
18-46: Consider adding edge case tests.While the current test coverage is adequate, consider adding tests for edge cases to improve robustness:
- Zero values (0 credits, 0 USD, 0 cents)
- Very large numbers (to verify no overflow issues)
- Rounding behavior at boundaries (e.g., values that round up vs down)
- Negative values (if applicable to your domain)
Example additions:
test('handles edge cases correctly', () => { const locale = 'en-US' expect(usdToCents(0)).toBe(0) expect(centsToCredits(0)).toBe(0) expect(formatUsd(0, locale)).toBe('0.00') // Test rounding behavior expect(usdToCents(1.235)).toBe(124) // rounds to nearest cent expect(usdToCents(1.234)).toBe(123) })
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/base/credits/comfyCredits.ts(1 hunks)tests-ui/tests/base/credits/comfyCredits.test.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/base/credits/comfyCredits.ts
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{vue,ts,tsx}: Leverage VueUse functions for performance-enhancing utilities
Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.json
Files:
tests-ui/tests/base/credits/comfyCredits.test.ts
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursorrules)
Use es-toolkit for utility functions
Files:
tests-ui/tests/base/credits/comfyCredits.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Use TypeScript for type safety
**/*.{ts,tsx}: Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Files:
tests-ui/tests/base/credits/comfyCredits.test.ts
**/*.{ts,tsx,js,vue}
📄 CodeRabbit inference engine (.cursorrules)
Implement proper error handling in components and services
**/*.{ts,tsx,js,vue}: Use 2-space indentation, single quotes, no semicolons, and maintain 80-character line width as configured in.prettierrc
Organize imports by sorting and grouping by plugin, and runpnpm formatbefore committing
Files:
tests-ui/tests/base/credits/comfyCredits.test.ts
**/*.{ts,tsx,js,jsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use camelCase for variable and setting names in TypeScript/Vue files
Files:
tests-ui/tests/base/credits/comfyCredits.test.ts
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,vue}: Useconst settingStore = useSettingStore()andsettingStore.get('Comfy.SomeSetting')to retrieve settings in TypeScript/Vue files
Useawait settingStore.set('Comfy.SomeSetting', newValue)to update settings in TypeScript/Vue files
Check server capabilities usingapi.serverSupportsFeature('feature_name')before using enhanced features
Useapi.getServerFeature('config_name', defaultValue)to retrieve server feature configurationEnforce ESLint rules for Vue + TypeScript including: no floating promises, no unused imports, and i18n raw text restrictions in templates
Files:
tests-ui/tests/base/credits/comfyCredits.test.ts
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.ts: Define dynamic setting defaults using runtime context with functions in settings configuration
UsedefaultsByInstallVersionproperty for gradual feature rollout based on version in settings configuration
Files:
tests-ui/tests/base/credits/comfyCredits.test.ts
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/base/credits/comfyCredits.test.ts
**/*.{test,spec}.{ts,tsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
Unit and component tests should be located in
tests-ui/or co-located with components assrc/components/**/*.{test,spec}.ts; E2E tests should be inbrowser_tests/
Files:
tests-ui/tests/base/credits/comfyCredits.test.ts
🧠 Learnings (14)
📓 Common learnings
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-24T19:46:52.279Z
Learning: Applies to **/*.{ts,tsx,js} : Use es-toolkit for utility functions
📚 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/base/credits/comfyCredits.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} : Follow existing test patterns in the codebase
Applied to files:
tests-ui/tests/base/credits/comfyCredits.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} : Use existing test utilities rather than writing custom utilities
Applied to files:
tests-ui/tests/base/credits/comfyCredits.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} : Mock external dependencies in tests
Applied to files:
tests-ui/tests/base/credits/comfyCredits.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: Check tests-ui/README.md for test guidelines
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Tests should be cross-platform compatible using `path.resolve`, `path.join`, and `path.sep` for Windows, macOS, and Linux compatibility
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `test` instead of `it` for defining test cases in vitest
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `vitest` for unit testing in this project
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`
Applied to files:
tests-ui/tests/base/credits/comfyCredits.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/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:47:22.909Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: browser_tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:22.909Z
Learning: Applies to browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx} : Follow naming conventions for browser tests
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:23.088Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:48:23.088Z
Learning: Use Vitest (with happy-dom) for unit and component tests, and Playwright for E2E tests
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setup
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
🧬 Code graph analysis (1)
tests-ui/tests/base/credits/comfyCredits.test.ts (1)
src/base/credits/comfyCredits.ts (12)
COMFY_CREDIT_RATE_CENTS(27-27)COMFY_CREDIT_RATE_USD(28-28)usdToCents(30-30)formatUsdFromCents(63-67)centsToCredits(33-34)creditsToCents(36-37)usdToCredits(39-40)creditsToUsd(42-43)formatCredits(45-49)formatCreditsFromCents(51-55)formatCreditsFromUsd(57-61)formatUsd(69-73)
🪛 ESLint
tests-ui/tests/base/credits/comfyCredits.test.ts
[error] 1-1: Resolve error: EACCES: permission denied, open '/XSWPeiGcoH'
at Object.writeFileSync (node:fs:2409:20)
at l (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:13670)
at createFilesMatcher (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:14422)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:70:65)
at Object.resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:147:20)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:69
at setRuleContext (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint-import-context/lib/index.js:23:20)
at fullResolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:30)
at relative (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:215:12)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:220:16)
at ExportMap.get (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/export-map.js:88:22)
at processBodyStatement (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/namespace.js:9:31)
at Program (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/namespace.js:100:21)
at ruleErrorHandler (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1173:33)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:46
at Array.forEach ()
at SourceCodeVisitor.callSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:30)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:291:18
at Array.forEach ()
at SourceCodeTraverser.traverseSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:290:10)
at runRules (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1214:12)
at #flatVerifyWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2101:4)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2189:43)
at Linter._verifyWithFlatConfigArray (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2292:15)
at Linter.verify (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1677:10)
at Linter.verifyAndFix (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2557:20)
at verifyText (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1179:45)
at readAndVerifyFile (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1320:10)
(import-x/namespace)
[error] 1-1: Resolve error: EACCES: permission denied, open '/bQNEyktcgu'
at Object.writeFileSync (node:fs:2409:20)
at l (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:13670)
at createFilesMatcher (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:14422)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:70:65)
at Object.resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:147:20)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:69
at setRuleContext (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint-import-context/lib/index.js:23:20)
at fullResolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:30)
at relative (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:215:12)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:220:16)
at checkSourceValue (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/no-unresolved.js:31:34)
at checkSourceValue (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:14:9)
at checkSource (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:17:9)
at ruleErrorHandler (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1173:33)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:46
at Array.forEach ()
at SourceCodeVisitor.callSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:30)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:291:18
at Array.forEach ()
at SourceCodeTraverser.traverseSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:290:10)
at runRules (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1214:12)
at #flatVerifyWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2101:4)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2189:43)
at Linter._verifyWithFlatConfigArray (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2292:15)
at Linter.verify (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1677:10)
at Linter.verifyAndFix (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2557:20)
at verifyText (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1179:45)
at readAndVerifyFile (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1320:10)
(import-x/no-unresolved)
[error] 1-1: Resolve error: EACCES: permission denied, open '/bmbDktuJVY'
at Object.writeFileSync (node:fs:2409:20)
at l (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:13670)
at createFilesMatcher (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:14422)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:70:65)
at Object.resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:147:20)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:69
at setRuleContext (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint-import-context/lib/index.js:23:20)
at fullResolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:30)
at relative (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:215:12)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:220:16)
at importType (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/import-type.js:126:63)
at checkImportForRelativePackage (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/no-relative-packages.js:15:38)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/no-relative-packages.js:59:40
at checkSourceValue (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:14:9)
at checkSource (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:17:9)
at ruleErrorHandler (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1173:33)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:46
at Array.forEach ()
at SourceCodeVisitor.callSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:30)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:291:18
at Array.forEach ()
at SourceCodeTraverser.traverseSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:290:10)
at runRules (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1214:12)
at #flatVerifyWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2101:4)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2189:43)
at Linter._verifyWithFlatConfigArray (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2292:15)
at Linter.verify (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1677:10)
at Linter.verifyAndFix (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2557:20)
at verifyText (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1179:45)
at readAndVerifyFile (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1320:10)
(import-x/no-relative-packages)
[error] 1-1: Unable to resolve path to module 'vitest'.
(import-x/no-unresolved)
[error] 16-16: Unable to resolve path to module '@/base/credits/comfyCredits'.
(import-x/no-unresolved)
⏰ 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). (5)
- GitHub Check: deploy-and-comment
- GitHub Check: test
- GitHub Check: setup
- GitHub Check: collect
- GitHub Check: lint-and-format
🔇 Additional comments (5)
tests-ui/tests/base/credits/comfyCredits.test.ts (5)
1-16: Imports look good.The imports follow project guidelines by using
testfrom vitest and correctly import all necessary functions from the comfyCredits module.
19-22: Constant verification is correct.The test properly verifies both conversion rate constants and uses
toBeCloseTofor floating-point comparison.
29-32: Conversion logic is verified correctly.The tests properly verify bidirectional conversion between cents and credits with appropriate assertions.
34-37: USD/credits conversions are correct.The bidirectional conversion tests properly verify the math: 2.1 USD = 210 cents = 1 credit, and 3.5 credits = 735 cents = 7.35 USD.
39-45: Formatting tests with explicit locale look good.The explicit
'en-US'locale parameter ensures consistent test results across different environments, addressing previous review feedback.
e1a6407 to
ca13f55
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
src/base/credits/comfyCredits.ts (1)
1-29: formatNumber guard may surprise callers when minFractionDigits > default maxThe min/max guard prevents Intl from throwing, which is good, but in the case where a caller sets
minimumFractionDigitshigher than the defaultmaximumFractionDigits, the current fix (minimum = maximum) silently drops the requested precision. You may want to instead raisemaximumFractionDigitstominimumFractionDigits(or let Intl throw) so that explicit caller intent for more decimals is preserved.- if ( - typeof merged.maximumFractionDigits === 'number' && - typeof merged.minimumFractionDigits === 'number' && - merged.maximumFractionDigits < merged.minimumFractionDigits - ) { - merged.minimumFractionDigits = merged.maximumFractionDigits - } + if ( + typeof merged.maximumFractionDigits === 'number' && + typeof merged.minimumFractionDigits === 'number' && + merged.maximumFractionDigits < merged.minimumFractionDigits + ) { + merged.maximumFractionDigits = merged.minimumFractionDigits + }src/components/common/UserCredit.vue (1)
35-38: Confirm units foramount_microsand consider localizing the"credits"suffixThis computed assumes
authStore.balance?.amount_microsis already in cents. If it is still in micros (as the name suggests), this will inflate displayed credits by 10,000×. Please double‑check the backend/SDK type foramount_microsand, if it’s micros, convert to cents before callingformatCreditsFromCents.Also, per the project i18n guidelines, the
'credits'suffix should ideally come from vue‑i18n rather than being hard‑coded in the computed string (e.g., use a translation likecredits.balanceLabelwith the formatted number as an interpolation parameter).src/components/dialog/content/credit/CreditTopUpOption.vue (1)
9-28: Tighten display amount handling and centralize USD/credits labelingThe editable/non‑editable display logic is generally solid, but a few details are worth tightening up:
displayUsdAmountusesMath.max(1, editable ? customAmount.value : amount). In edge cases whereamountorcustomAmountcould be0or negative (e.g., transient InputNumber states), the displayed USD/credits would be clamped to1whilehandleBuyNowstill uses the rawamount/customAmount. If that’s a realistic scenario, consider aligning the purchase amount withdisplayUsdAmountor clamping earlier (e.g., in the ref) so display and behavior always match.formattedUsdmanually builds a$${...toFixed(2)}string usingusdToCents. Since you already haveformatUsd/formatUsdFromCentsincomfyCredits.ts, it may be cleaner and more consistent to use those helpers for USD formatting instead of re‑implementing the pattern here.- As in other files, the
"credits"suffix is hard‑coded informattedCredits. To follow the i18n guidance, consider moving this to a vue‑i18n key (e.g.,credits.topUp.optionLabel) and interpolating the formatted numeric part.Also applies to: 72-83
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (1)
3-14: Verify balance units and consider i18n for the"credits"suffix
formatBalanceassumes the*_microsfields fromauthStore.balanceare already in cents (maybeCents). If those fields are still micros, this will vastly overstate the user’s credit amounts. Please confirm the unit ofamount_micros,cloud_credit_balance_micros, andprepaid_balance_microsand, if needed, convert micros → cents before callingformatCreditsFromCents.Since
formatBalanceproduces user-facing strings (including' credits'), it would also be more in line with the i18n guidelines to move the suffix into a vue‑i18n translation (e.g.,credits.subscription.balance) and let components or composables interpolate the numeric portion.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
src/base/credits/comfyCredits.ts(1 hunks)src/components/common/UserCredit.vue(3 hunks)src/components/dialog/content/credit/CreditTopUpOption.vue(3 hunks)src/platform/cloud/subscription/composables/useSubscriptionCredits.ts(1 hunks)tests-ui/tests/base/credits/comfyCredits.test.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- tests-ui/tests/base/credits/comfyCredits.test.ts
🧰 Additional context used
📓 Path-based instructions (21)
**/*.vue
📄 CodeRabbit inference engine (.cursorrules)
**/*.vue: Use setup() function for component logic in Vue 3 Composition API
Utilize ref and reactive for reactive state in Vue 3
Implement computed properties with computed() function
Use watch and watchEffect for side effects in Vue 3
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection in Vue 3
Use Vue 3.5 style of default prop declaration with defineProps()
Organize Vue components in <script> <style> order
Use Tailwind CSS for styling Vue components
Implement responsive design with Tailwind CSS
Do not use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage). Use replacements: Select, Popover, DatePicker, ToggleSwitch, Drawer, AutoComplete, Tabs, Stepper, Message respectively
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components in Vue 3
Follow Vue 3 style guide and naming conventions
Never use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage)Never use
:class="[]"to merge class names - always useimport { cn } from '@/utils/tailwindUtil'for class merging in Vue templates
**/*.vue: Use TypeScript with Vue 3 Single File Components (.vuefiles)
Name Vue components in PascalCase (e.g.,MenuHamburger.vue)Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vue**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{vue,ts,tsx}: Leverage VueUse functions for performance-enhancing utilities
Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.jsonFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.ts**/*.{ts,tsx,js,vue}
📄 CodeRabbit inference engine (.cursorrules)
Implement proper error handling in components and services
**/*.{ts,tsx,js,vue}: Use 2-space indentation, single quotes, no semicolons, and maintain 80-character line width as configured in.prettierrc
Organize imports by sorting and grouping by plugin, and runpnpm formatbefore committingFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.tssrc/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventionsFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.jsonFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.ts**/*.{ts,tsx,js,jsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use camelCase for variable and setting names in TypeScript/Vue files
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.ts**/*.{vue,html}
📄 CodeRabbit inference engine (CLAUDE.md)
Never use
dark:ordark-theme:Tailwind variants - instead use semantic values fromstyle.csstheme, e.g.bg-node-component-surfaceFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vue**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,vue}: Useconst settingStore = useSettingStore()andsettingStore.get('Comfy.SomeSetting')to retrieve settings in TypeScript/Vue files
Useawait settingStore.set('Comfy.SomeSetting', newValue)to update settings in TypeScript/Vue files
Check server capabilities usingapi.serverSupportsFeature('feature_name')before using enhanced features
Useapi.getServerFeature('config_name', defaultValue)to retrieve server feature configurationEnforce ESLint rules for Vue + TypeScript including: no floating promises, no unused imports, and i18n raw text restrictions in templates
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.tssrc/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebaseFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.tssrc/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.tssrc/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.jsonFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/components/**/*.vue
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue componentsFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/components/**/*.{vue,css}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system packageFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/components/**/*.{vue,ts,js}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI stringsFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vue**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursorrules)
Use es-toolkit for utility functions
Files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.ts**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Use TypeScript for type safety
**/*.{ts,tsx}: Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issueFiles:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.tssrc/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safetyFiles:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.ts**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.ts: Define dynamic setting defaults using runtime context with functions in settings configuration
UsedefaultsByInstallVersionproperty for gradual feature rollout based on version in settings configurationFiles:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.tssrc/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directlyFiles:
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts**/composables/use*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables in the format
useXyz.tsFiles:
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts🧠 Learnings (12)
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitchApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Replace PrimeVue Calendar component with DatePickerApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.vue : Do not use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage). Use replacements: Select, Popover, DatePicker, ToggleSwitch, Drawer, AutoComplete, Tabs, Stepper, Message respectivelyApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vue📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.vue : Never use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage)Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.vue : Utilize ref and reactive for reactive state in Vue 3Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.{vue,ts,tsx} : Leverage VueUse functions for performance-enhancing utilitiesApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vue📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .github/copilot-instructions.md:0-0 Timestamp: 2025-11-24T19:47:02.860Z Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive stateApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition APIApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panelsApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .github/copilot-instructions.md:0-0 Timestamp: 2025-11-24T19:47:02.860Z Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing stylesApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vue📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.vue : Implement computed properties with computed() functionApplied to files:
src/components/common/UserCredit.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition APIApplied to files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts🧬 Code graph analysis (1)
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (2)
src/stores/firebaseAuthStore.ts (1)
useFirebaseAuthStore(53-473)src/base/credits/comfyCredits.ts (1)
formatCreditsFromCents(61-74)⏰ 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: setup
- GitHub Check: lint-and-format
- GitHub Check: collect
- GitHub Check: test
🔇 Additional comments (5)
src/base/credits/comfyCredits.ts (2)
31-47: Conversion helpers look consistent and numerically saneThe cents↔USD↔credits helpers (
usdToCents,centsToCredits,creditsToCents,usdToCredits,creditsToUsd) are internally consistent, use integer cents as the base, and correctly apply rounding where needed. This should give stable round‑trips at cent precision for realistic values.
48-115: Formatting wrappers provide a clean, typed surface over Intl
FormatOptionsplus theformatCredits*/formatUsd*functions are nicely typed and keep formatting concerns (locale, options) decoupled from conversion concerns. The sharedformatNumbercore should make future tweaks to default fraction digits or locales straightforward.src/components/common/UserCredit.vue (1)
10-15: Wallet icon change is consistent with credit semanticsSwitching the Tag icon to
pi pi-walletbetter matches the credit/balance concept and keeps visuals aligned with the other updated credit UIs.src/components/dialog/content/credit/CreditTopUpOption.vue (1)
3-8: Wallet icon matches other credit-related componentsThe Tag icon update to
pi pi-walletkeeps this top-up option visually in sync with the rest of the credit UI.src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (1)
15-49: Computed credit strings with fallback behavior look goodThe three computed values (
totalCredits,monthlyBonusCredits,prepaidCredits) consistently useformatBalance, catch formatting errors, log a descriptive message, and fall back to formatting0credits. This should make the UI resilient to missing/invalid balance data while still surfacing issues in the console.
ca13f55 to
d1006dd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts (1)
1-3: Prefertestoveritin new Vitest suitesProject unit-test guidelines call for
testinstead ofit. For consistency with other updated specs (e.g., comfyCredits tests), consider importingtestfromvitestand renaming these cases accordingly.Also applies to: 53-66
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts (1)
2-2: Align ontestinstead ofitfor Vitest casesThis spec still imports and uses
iteven though the project test rules prefertest. For consistency withcomfyCredits.test.tsand future maintenance, consider switching to:-import { beforeEach, describe, expect, it, vi } from 'vitest' +import { beforeEach, describe, expect, test, vi } from 'vitest'and renaming each
it(totest(.Also applies to: 78-147
🧹 Nitpick comments (1)
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts (1)
80-96: Avoidas anyon mocked balances where possibleSeveral expectations rely on
authStore.balance = { ... } as any. If there’s a balance type exported from the store (or a shared interface), consider using a more specific type (e.g.,Partial<BalanceType>) instead ofas anyto keep these tests type-safe while still minimal.Also applies to: 111-121, 125-135
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
src/base/credits/comfyCredits.ts(1 hunks)src/components/common/UserCredit.vue(2 hunks)src/components/dialog/content/credit/CreditTopUpOption.vue(3 hunks)src/platform/cloud/subscription/composables/useSubscriptionCredits.ts(1 hunks)tests-ui/tests/base/credits/comfyCredits.test.ts(1 hunks)tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts(1 hunks)tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts(2 hunks)tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/base/credits/comfyCredits.ts
- src/platform/cloud/subscription/composables/useSubscriptionCredits.ts
🧰 Additional context used
📓 Path-based instructions (21)
**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{vue,ts,tsx}: Leverage VueUse functions for performance-enhancing utilities
Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.json
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/components/dialog/content/credit/CreditTopUpOption.vuetests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tssrc/components/common/UserCredit.vue
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursorrules)
Use es-toolkit for utility functions
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Use TypeScript for type safety
**/*.{ts,tsx}: Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts
**/*.{ts,tsx,js,vue}
📄 CodeRabbit inference engine (.cursorrules)
Implement proper error handling in components and services
**/*.{ts,tsx,js,vue}: Use 2-space indentation, single quotes, no semicolons, and maintain 80-character line width as configured in.prettierrc
Organize imports by sorting and grouping by plugin, and runpnpm formatbefore committing
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/components/dialog/content/credit/CreditTopUpOption.vuetests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tssrc/components/common/UserCredit.vue
**/*.{ts,tsx,js,jsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use camelCase for variable and setting names in TypeScript/Vue files
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/components/dialog/content/credit/CreditTopUpOption.vuetests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tssrc/components/common/UserCredit.vue
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,vue}: Useconst settingStore = useSettingStore()andsettingStore.get('Comfy.SomeSetting')to retrieve settings in TypeScript/Vue files
Useawait settingStore.set('Comfy.SomeSetting', newValue)to update settings in TypeScript/Vue files
Check server capabilities usingapi.serverSupportsFeature('feature_name')before using enhanced features
Useapi.getServerFeature('config_name', defaultValue)to retrieve server feature configurationEnforce ESLint rules for Vue + TypeScript including: no floating promises, no unused imports, and i18n raw text restrictions in templates
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/components/dialog/content/credit/CreditTopUpOption.vuetests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tssrc/components/common/UserCredit.vue
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.ts: Define dynamic setting defaults using runtime context with functions in settings configuration
UsedefaultsByInstallVersionproperty for gradual feature rollout based on version in settings configuration
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts
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.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts
**/*.{test,spec}.{ts,tsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
Unit and component tests should be located in
tests-ui/or co-located with components assrc/components/**/*.{test,spec}.ts; E2E tests should be inbrowser_tests/
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts
**/*.vue
📄 CodeRabbit inference engine (.cursorrules)
**/*.vue: Use setup() function for component logic in Vue 3 Composition API
Utilize ref and reactive for reactive state in Vue 3
Implement computed properties with computed() function
Use watch and watchEffect for side effects in Vue 3
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection in Vue 3
Use Vue 3.5 style of default prop declaration with defineProps()
Organize Vue components in <script> <style> order
Use Tailwind CSS for styling Vue components
Implement responsive design with Tailwind CSS
Do not use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage). Use replacements: Select, Popover, DatePicker, ToggleSwitch, Drawer, AutoComplete, Tabs, Stepper, Message respectively
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components in Vue 3
Follow Vue 3 style guide and naming conventions
Never use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage)Never use
:class="[]"to merge class names - always useimport { cn } from '@/utils/tailwindUtil'for class merging in Vue templates
**/*.vue: Use TypeScript with Vue 3 Single File Components (.vuefiles)
Name Vue components in PascalCase (e.g.,MenuHamburger.vue)Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventionsFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.jsonFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vue**/*.{vue,html}
📄 CodeRabbit inference engine (CLAUDE.md)
Never use
dark:ordark-theme:Tailwind variants - instead use semantic values fromstyle.csstheme, e.g.bg-node-component-surfaceFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebaseFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.jsonFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/components/**/*.vue
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue componentsFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/components/**/*.{vue,css}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system packageFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/components/**/*.{vue,ts,js}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI stringsFiles:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vue**/composables/use*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables in the format
useXyz.tsFiles:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts🧠 Learnings (32)
📓 Common learnings
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📚 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 featuresApplied to files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.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} : Follow existing test patterns in the codebaseApplied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/base/credits/comfyCredits.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} : Mock external dependencies in testsApplied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.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} : Use existing test utilities rather than writing custom utilitiesApplied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.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 mocksApplied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.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: Check tests-ui/README.md for test guidelinesApplied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/base/credits/comfyCredits.test.ts📚 Learning: 2025-11-24T19:48:23.088Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: AGENTS.md:0-0 Timestamp: 2025-11-24T19:48:23.088Z Learning: Applies to **/*.{test,spec}.{ts,tsx,js} : Unit and component tests should be located in `tests-ui/` or co-located with components as `src/components/**/*.{test,spec}.ts`; E2E tests should be in `browser_tests/`Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `vitest` for unit testing in this projectApplied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts📚 Learning: 2025-11-24T19:48:09.318Z
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 possibleApplied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts📚 Learning: 2025-11-24T19:48:23.088Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: AGENTS.md:0-0 Timestamp: 2025-11-24T19:48:23.088Z Learning: Use Vitest (with happy-dom) for unit and component tests, and Playwright for E2E testsApplied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.{vue,ts,tsx} : Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.jsonApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 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/**/{components,composables}/**/*.{ts,tsx,vue} : Use vue-i18n for ALL user-facing strings by adding them to `src/locales/en/main.json`Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitchApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.vue : Do not use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage). Use replacements: Select, Popover, DatePicker, ToggleSwitch, Drawer, AutoComplete, Tabs, Stepper, Message respectivelyApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.vue : Never use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage)Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.{vue,ts,tsx} : Leverage VueUse functions for performance-enhancing utilitiesApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.vue : Utilize ref and reactive for reactive state in Vue 3Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .github/copilot-instructions.md:0-0 Timestamp: 2025-11-24T19:47:02.860Z Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive stateApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Replace PrimeVue Calendar component with DatePickerApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panelsApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition APIApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Replace PrimeVue Dropdown component with SelectApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:48:09.318Z
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} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `test` instead of `it` for defining test cases in vitestApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/lib/litegraph/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:56.371Z Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{js,ts,jsx,tsx} : When adding features, always write vitest unit tests using cursor rules in @.cursorApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts📚 Learning: 2025-11-24T19:48:23.088Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: AGENTS.md:0-0 Timestamp: 2025-11-24T19:48:23.088Z Learning: Vitest test files should use coverage enabled with text, json, and html reporters as configured in `vitest.config.ts`Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts📚 Learning: 2025-11-24T19:47:22.909Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: browser_tests/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:22.909Z Learning: Applies to browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx} : Follow naming conventions for browser testsApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts📚 Learning: 2025-11-24T19:48:09.318Z
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} : Tests should be cross-platform compatible using `path.resolve`, `path.join`, and `path.sep` for Windows, macOS, and Linux compatibilityApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/lib/litegraph/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:56.371Z Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setupApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.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 leaksApplied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.{vue,ts,js} : Use vue-i18n for ALL UI stringsApplied to files:
src/components/common/UserCredit.vue🧬 Code graph analysis (2)
tests-ui/tests/base/credits/comfyCredits.test.ts (1)
src/base/credits/comfyCredits.ts (12)
COMFY_CREDIT_RATE_CENTS(31-31)COMFY_CREDIT_RATE_USD(32-32)usdToCents(34-34)formatUsdFromCents(102-115)centsToCredits(36-37)creditsToCents(39-40)usdToCredits(42-43)creditsToUsd(45-46)formatCredits(54-59)formatCreditsFromCents(61-74)formatCreditsFromUsd(76-89)formatUsd(91-100)tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts (1)
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (1)
useSubscriptionCredits(10-65)⏰ 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). (5)
- GitHub Check: deploy-and-comment
- GitHub Check: setup
- GitHub Check: test
- GitHub Check: collect
- GitHub Check: lint-and-format
🔇 Additional comments (5)
src/components/common/UserCredit.vue (1)
12-17: Credits formatting + i18n usage looks solidUsing
formatCreditsFromCentswith a safe?? 0default and appendingt('credits.credits')gives consistent, localized"0.00 Credits"-style output and avoids balance null/undefined pitfalls. The wallet icon change also matches the new credits-focused UX.Also applies to: 24-27, 35-42
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (1)
20-24: Mocks and expectations aligned with new credits formattingUpdating
mockCreditsDataand assertions to"10.00 Credits"/"5.00 Credits"keeps this suite consistent with the centralized credits formatter and suffix semantics.Also applies to: 155-159
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts (1)
53-66: Coverage for credit/USD display behavior looks goodThe tests exercise both preset and editable flows, verifying
"1.00 Credits"/"$2.10"as well as the recomputed"2.00 Credits"label whencustomAmountchanges, which matches the comfyCredits helpers’ behavior.tests-ui/tests/base/credits/comfyCredits.test.ts (1)
1-46: Comprehensive, locale-stable coverage for comfyCreditsThese tests thoroughly cover conversion helpers and formatting, and the explicit
'en-US'locale on formatting calls prevents locale-dependent flakiness. This gives strong confidence in the new credits utilities.tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts (1)
4-16: Tests accurately mirror credits formatting and fallback behaviorThe new cases around
"0.00 Credits"defaults, specific cent values (210/420/630), and theformatCreditsFromCentserror spy all line up withuseSubscriptionCredits’sformatBalanceand try/catch fallback, giving good regression coverage for the new credits-domain logic.Also applies to: 78-107, 111-121, 125-135
d1006dd to
7c43bf4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/dialog/content/credit/CreditTopUpOption.vue (1)
98-106: GuardpurchaseCreditswith try/finally so loading state can’t get stuckIf
authActions.purchaseCreditsrejects,loading.valuestaystrue, the spinner never clears, anddidClickBuyNowis never set (so no balance refresh on unmount). Wrapping the call in try/finally (and optionally logging) keeps the UI resilient:-const handleBuyNow = async () => { - const creditAmount = displayUsdAmount.value - telemetry?.trackApiCreditTopupButtonPurchaseClicked(creditAmount) - - loading.value = true - await authActions.purchaseCredits(creditAmount) - loading.value = false - didClickBuyNow.value = true -} +const handleBuyNow = async () => { + const creditAmount = displayUsdAmount.value + telemetry?.trackApiCreditTopupButtonPurchaseClicked(creditAmount) + + loading.value = true + try { + await authActions.purchaseCredits(creditAmount) + didClickBuyNow.value = true + } catch (error) { + console.error('[CreditTopUpOption] Failed to purchase credits:', error) + // Optionally surface a toast here if desired. + } finally { + loading.value = false + } +}
🧹 Nitpick comments (5)
src/base/credits/comfyCredits.ts (1)
1-115: Credit conversion and formatting helpers look consistent; minor DRY opportunityThe conversion + formatting pipeline is coherent (usd↔cents↔credits, shared
DEFAULT_NUMBER_FORMAT, and the min/max-fraction guard). If you want to pare things down further, you could derive small helper types fromFormatOptionsfor the “from cents/usd” helpers instead of repeating inline{ cents|usd; locale?; numberOptions? }shapes, but that’s purely optional.tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts (1)
1-67: Usetestinstead ofitand be mindful of locale‑dependent formattingThe behavior under test looks correct, but per project test guidelines you should prefer
testoverit, and the numeric assertions assume an en‑US number format.You can address both by:
- Switching to
test:-import { describe, expect, it, vi } from 'vitest' +import { describe, expect, test, vi } from 'vitest' @@ -describe('CreditTopUpOption', () => { - it('renders converted credit price for preset amounts', () => { +describe('CreditTopUpOption', () => { + test('renders converted credit price for preset amounts', () => { @@ - it('updates credit label when editable amount changes', async () => { + test('updates credit label when editable amount changes', async () => {
- If these tests ever need to run under non‑en‑US locales, consider either passing an explicit locale into the comfyCredits helpers (via vue‑i18n’s current locale) or mocking
Intl.NumberFormatin the test setup so'1.00'/'$2.10'remain stable across environments.Based on learnings, the vitest style guidance applies here.
src/components/common/UserCredit.vue (1)
12-42: Pass vue‑i18n locale intoformatCreditsFromCentsfor consistent formattingThe balance calculation itself is sound, but
formatCreditsFromCentscurrently relies on the environment default locale, while labels come from vue‑i18n. To keep digits/grouping aligned with the active app locale, consider:-const { t } = useI18n() +const { t, locale } = useI18n() @@ - const cents = authStore.balance?.amount_micros ?? 0 - const amount = formatCreditsFromCents({ cents }) + const cents = authStore.balance?.amount_micros ?? 0 + const amount = formatCreditsFromCents({ cents, locale: locale.value }) return `${amount} ${t('credits.credits')}`This makes the numeric format follow the same locale as your translations.
As per coding guidelines, vue‑i18n should drive user‑visible formatting.
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (1)
2-5: Use vue‑i18n locale when formatting subscription credit balances
formatBalancecorrectly handles undefined balances and error fallbacks, but likeUserCredit.vueit letsformatCreditsFromCentspick the environment locale while labels come from vue‑i18n.To keep number formatting aligned with your active app locale, you could do:
-export function useSubscriptionCredits() { - const authStore = useFirebaseAuthStore() - const { t } = useI18n() +export function useSubscriptionCredits() { + const authStore = useFirebaseAuthStore() + const { t, locale } = useI18n() @@ - const cents = maybeCents ?? 0 - const amount = formatCreditsFromCents({ cents }) + const cents = maybeCents ?? 0 + const amount = formatCreditsFromCents({ + cents, + locale: locale.value + })That ensures balances render with the same locale settings as the rest of the subscription UI.
As per coding guidelines, vue‑i18n should be the source of truth for user‑visible formatting.
Also applies to: 14-19, 21-55
src/components/dialog/content/credit/CreditTopUpOption.vue (1)
79-96: Wire vue‑i18n locale into credits/USD formatting for consistent output
formattedCreditsandformattedUsduse comfyCredits helpers but don’t pass a locale, so formatting may not follow the current vue‑i18n locale.You can align them with the rest of the app like this:
-const { t } = useI18n() +const { t, locale } = useI18n() @@ -const formattedCredits = computed( - () => - `${formatCreditsFromUsd({ usd: displayUsdAmount.value })} ${t('credits.credits')}` -) +const formattedCredits = computed( + () => + `${formatCreditsFromUsd({ + usd: displayUsdAmount.value, + locale: locale.value + })} ${t('credits.credits')}` +) @@ -const formattedUsd = computed( - () => `$${formatUsd({ value: displayUsdAmount.value })}` -) +const formattedUsd = computed( + () => `$${formatUsd({ value: displayUsdAmount.value, locale: locale.value })}` +)This keeps the number formatting (decimal separator, grouping, etc.) in sync with the active translation locale.
As per coding guidelines, vue‑i18n should drive localized formatting in components.
7c43bf4 to
b23ab6b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (8)
src/base/credits/comfyCredits.ts(1 hunks)src/components/common/UserCredit.vue(2 hunks)src/components/dialog/content/credit/CreditTopUpOption.vue(3 hunks)src/platform/cloud/subscription/composables/useSubscriptionCredits.ts(1 hunks)tests-ui/tests/base/credits/comfyCredits.test.ts(1 hunks)tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts(1 hunks)tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts(2 hunks)tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (23)
**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{vue,ts,tsx}: Leverage VueUse functions for performance-enhancing utilities
Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.json
Files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tssrc/components/common/UserCredit.vuetests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tssrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/base/credits/comfyCredits.ts
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursorrules)
Use es-toolkit for utility functions
Files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tssrc/platform/cloud/subscription/composables/useSubscriptionCredits.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/base/credits/comfyCredits.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Use TypeScript for type safety
**/*.{ts,tsx}: Never useanytype - use proper TypeScript types
Never useas anytype assertions - fix the underlying type issue
Files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tssrc/platform/cloud/subscription/composables/useSubscriptionCredits.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/base/credits/comfyCredits.ts
**/*.{ts,tsx,js,vue}
📄 CodeRabbit inference engine (.cursorrules)
Implement proper error handling in components and services
**/*.{ts,tsx,js,vue}: Use 2-space indentation, single quotes, no semicolons, and maintain 80-character line width as configured in.prettierrc
Organize imports by sorting and grouping by plugin, and runpnpm formatbefore committing
Files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tssrc/components/common/UserCredit.vuetests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tssrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/base/credits/comfyCredits.ts
**/*.{ts,tsx,js,jsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
Use camelCase for variable and setting names in TypeScript/Vue files
Files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tssrc/components/common/UserCredit.vuetests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tssrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/base/credits/comfyCredits.ts
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,vue}: Useconst settingStore = useSettingStore()andsettingStore.get('Comfy.SomeSetting')to retrieve settings in TypeScript/Vue files
Useawait settingStore.set('Comfy.SomeSetting', newValue)to update settings in TypeScript/Vue files
Check server capabilities usingapi.serverSupportsFeature('feature_name')before using enhanced features
Useapi.getServerFeature('config_name', defaultValue)to retrieve server feature configurationEnforce ESLint rules for Vue + TypeScript including: no floating promises, no unused imports, and i18n raw text restrictions in templates
Files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tssrc/components/common/UserCredit.vuetests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tssrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/base/credits/comfyCredits.ts
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.ts: Define dynamic setting defaults using runtime context with functions in settings configuration
UsedefaultsByInstallVersionproperty for gradual feature rollout based on version in settings configuration
Files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tssrc/platform/cloud/subscription/composables/useSubscriptionCredits.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/base/credits/comfyCredits.ts
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/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts
**/*.{test,spec}.{ts,tsx,js}
📄 CodeRabbit inference engine (AGENTS.md)
Unit and component tests should be located in
tests-ui/or co-located with components assrc/components/**/*.{test,spec}.ts; E2E tests should be inbrowser_tests/
Files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts
**/composables/use*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables in the format
useXyz.ts
Files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tssrc/platform/cloud/subscription/composables/useSubscriptionCredits.ts
**/*.vue
📄 CodeRabbit inference engine (.cursorrules)
**/*.vue: Use setup() function for component logic in Vue 3 Composition API
Utilize ref and reactive for reactive state in Vue 3
Implement computed properties with computed() function
Use watch and watchEffect for side effects in Vue 3
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection in Vue 3
Use Vue 3.5 style of default prop declaration with defineProps()
Organize Vue components in <script> <style> order
Use Tailwind CSS for styling Vue components
Implement responsive design with Tailwind CSS
Do not use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage). Use replacements: Select, Popover, DatePicker, ToggleSwitch, Drawer, AutoComplete, Tabs, Stepper, Message respectively
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components in Vue 3
Follow Vue 3 style guide and naming conventions
Never use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage)Never use
:class="[]"to merge class names - always useimport { cn } from '@/utils/tailwindUtil'for class merging in Vue templates
**/*.vue: Use TypeScript with Vue 3 Single File Components (.vuefiles)
Name Vue components in PascalCase (e.g.,MenuHamburger.vue)Files:
src/components/common/UserCredit.vuesrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventionsFiles:
src/components/common/UserCredit.vuesrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.jsonFiles:
src/components/common/UserCredit.vuesrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.ts**/*.{vue,html}
📄 CodeRabbit inference engine (CLAUDE.md)
Never use
dark:ordark-theme:Tailwind variants - instead use semantic values fromstyle.csstheme, e.g.bg-node-component-surfaceFiles:
src/components/common/UserCredit.vuesrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebaseFiles:
src/components/common/UserCredit.vuesrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.tssrc/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/components/common/UserCredit.vuesrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/components/common/UserCredit.vuesrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.tssrc/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.jsonFiles:
src/components/common/UserCredit.vuesrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/components/**/*.vue
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue componentsFiles:
src/components/common/UserCredit.vuesrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/**/*.{vue,css}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system packageFiles:
src/components/common/UserCredit.vuesrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/**/*.{vue,ts,js}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI stringsFiles:
src/components/common/UserCredit.vuesrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safetyFiles:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.tssrc/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directlyFiles:
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts🧠 Learnings (35)
📓 Common learnings
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📚 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 featuresApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.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} : Follow existing test patterns in the codebaseApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `vitest` for unit testing in this projectApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.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} : Use existing test utilities rather than writing custom utilitiesApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts📚 Learning: 2025-11-24T19:48:09.318Z
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} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `test` instead of `it` for defining test cases in vitestApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.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 mocksApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.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: Check tests-ui/README.md for test guidelinesApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts📚 Learning: 2025-11-24T19:48:23.088Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: AGENTS.md:0-0 Timestamp: 2025-11-24T19:48:23.088Z Learning: Vitest test files should use coverage enabled with text, json, and html reporters as configured in `vitest.config.ts`Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/lib/litegraph/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:56.371Z Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{js,ts,jsx,tsx} : When adding features, always write vitest unit tests using cursor rules in @.cursorApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts📚 Learning: 2025-11-24T19:47:22.909Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: browser_tests/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:22.909Z Learning: Applies to browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx} : Follow naming conventions for browser testsApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts📚 Learning: 2025-11-24T19:48:09.318Z
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} : Tests should be cross-platform compatible using `path.resolve`, `path.join`, and `path.sep` for Windows, macOS, and Linux compatibilityApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts📚 Learning: 2025-11-24T19:48:23.088Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: AGENTS.md:0-0 Timestamp: 2025-11-24T19:48:23.088Z Learning: Use Vitest (with happy-dom) for unit and component tests, and Playwright for E2E testsApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/lib/litegraph/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:56.371Z Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setupApplied to files:
tests-ui/tests/base/credits/comfyCredits.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.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} : Mock external dependencies in testsApplied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.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 leaksApplied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts📚 Learning: 2025-11-24T19:48:09.318Z
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 possibleApplied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.{vue,ts,tsx} : Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.jsonApplied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.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/**/{components,composables}/**/*.{ts,tsx,vue} : Use vue-i18n for ALL user-facing strings by adding them to `src/locales/en/main.json`Applied to files:
src/components/common/UserCredit.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.{vue,ts,js} : Use vue-i18n for ALL UI stringsApplied to files:
src/components/common/UserCredit.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitchApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.vue : Do not use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage). Use replacements: Select, Popover, DatePicker, ToggleSwitch, Drawer, AutoComplete, Tabs, Stepper, Message respectivelyApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.vue : Never use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage)Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.{vue,ts,tsx} : Leverage VueUse functions for performance-enhancing utilitiesApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.ts📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.vue : Utilize ref and reactive for reactive state in Vue 3Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .github/copilot-instructions.md:0-0 Timestamp: 2025-11-24T19:47:02.860Z Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive stateApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Replace PrimeVue Calendar component with DatePickerApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panelsApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition APIApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Replace PrimeVue Dropdown component with SelectApplied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: src/components/CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:45.616Z Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition APIApplied to files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts📚 Learning: 2025-11-24T19:47:14.779Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: CLAUDE.md:0-0 Timestamp: 2025-11-24T19:47:14.779Z Learning: Applies to **/*.{ts,tsx,vue} : Use `const settingStore = useSettingStore()` and `settingStore.get('Comfy.SomeSetting')` to retrieve settings in TypeScript/Vue filesApplied to files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: .cursorrules:0-0 Timestamp: 2025-11-24T19:46:52.279Z Learning: Applies to **/*.vue : Implement computed properties with computed() functionApplied to files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts📚 Learning: 2025-11-24T19:48:23.088Z
Learnt from: CR Repo: Comfy-Org/ComfyUI_frontend PR: 0 File: AGENTS.md:0-0 Timestamp: 2025-11-24T19:48:23.088Z Learning: Applies to **/*.{test,spec}.{ts,tsx,js} : Unit and component tests should be located in `tests-ui/` or co-located with components as `src/components/**/*.{test,spec}.ts`; E2E tests should be in `browser_tests/`Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts🧬 Code graph analysis (3)
tests-ui/tests/base/credits/comfyCredits.test.ts (1)
src/base/credits/comfyCredits.ts (11)
COMFY_CREDIT_RATE_CENTS(31-31)COMFY_CREDIT_RATE_USD(32-32)usdToCents(34-34)centsToCredits(36-37)creditsToCents(39-40)usdToCredits(42-43)creditsToUsd(45-46)formatCredits(54-59)formatCreditsFromCents(61-74)formatCreditsFromUsd(76-89)formatUsd(91-100)tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts (1)
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (1)
useSubscriptionCredits(10-68)src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (2)
src/stores/firebaseAuthStore.ts (1)
useFirebaseAuthStore(53-473)src/base/credits/comfyCredits.ts (1)
formatCreditsFromCents(61-74)⏰ 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
🔇 Additional comments (18)
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (1)
154-159: LGTM: Tests correctly validate formatted credit display.The expectations properly verify that the component displays formatted credit values with the localized suffix.
src/components/common/UserCredit.vue (3)
12-12: LGTM: Icon updated to better represent credits.The change from
pi-dollartopi-walletbetter reflects the shift from USD to credits-based display.
37-45: LGTM: Proper i18n integration for credit formatting.The implementation correctly uses
formatCreditsFromCentswith locale-aware formatting and appends the translated credits label viat('credits.credits'). The fallback to 0 when balance is undefined is appropriate.As per coding guidelines, using vue-i18n in Composition API for user-facing strings.
37-45: Clarify the units ofamount_microswith the backend team.The field is documented as microamount (1/1,000,000 of currency unit) in the API schema, yet the frontend code treats it as cents by passing it directly to
formatCreditsFromCents()which divides by 210 (the cent-to-credit rate). The test case confirms 210 units map to 1 credit, consistent with cent units. Verify with the backend team whetheramount_microsactually contains cents (1/100) or true micros (1/1,000,000), or if the field should be renamed for clarity.tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts (1)
5-25: LGTM: Clean mock setup following project patterns.The mocks for Firebase auth actions and telemetry are concise and use vitest mock functions appropriately. The i18n setup is minimal but sufficient for testing credit formatting.
Based on learnings, using existing test utilities and vitest mock functions.
tests-ui/tests/base/credits/comfyCredits.test.ts (1)
1-46: LGTM: Comprehensive test coverage with proper locale handling.The test suite correctly:
- Uses
testinstead ofitper project guidelines- Passes explicit locale (
'en-US') to all formatting functions, preventing flakiness- Covers all core conversion functions (USD↔cents↔credits)
- Validates both conversion rates and formatting output
- Uses appropriate assertions (
toBefor exact matches,toBeCloseTofor floating-point comparisons)Based on learnings, following existing test patterns and addressing locale-dependent formatting concerns from past reviews.
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts (3)
8-17: LGTM: Proper i18n mock setup.The vue-i18n mock correctly returns the translation token and locale, allowing tests to verify the complete formatted output including the translated suffix.
98-108: LGTM: Excellent error handling test.The test properly uses a spy to simulate formatting errors and verifies that the composable falls back gracefully to formatting
0. The spy is restored after the test, preventing interference with other tests.Based on learnings, using vitest mock functions appropriately.
92-96: Test values correctly demonstrate credit conversion.The test uses
amount_micros: 210which, given the conversion rate of 210 cents per credit, correctly results in'1.00 Credits'. The test values (210, 420, 630) are well-chosen multiples that produce clean decimal outputs (1.00, 2.00, 3.00).src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (3)
14-22: LGTM: Clean formatting helper with proper i18n.The
formatBalancehelper effectively centralizes the formatting logic:
- Handles undefined values gracefully with nullish coalescing
- Uses locale-aware formatting via
formatCreditsFromCents- Appends translated credits suffix using
t('credits.credits')As per coding guidelines, using vue-i18n for user-facing strings.
24-58: LGTM: Robust error handling with consistent fallback.All three credit computeds (
totalCredits,monthlyBonusCredits,prepaidCredits) follow the same pattern:
- Try to format the balance value
- Catch any formatting errors
- Log the error for debugging
- Return a safe fallback (
formatBalance(0))This ensures the UI never breaks due to formatting errors.
60-67: LGTM: Added loading state to public API.The addition of
isLoadingBalanceto the return value allows consumers to show appropriate loading states while balance data is being fetched.src/components/dialog/content/credit/CreditTopUpOption.vue (3)
5-5: LGTM: Icon updated for consistency.The change from
pi-dollartopi-walletaligns with the shift to credits-based display and matches the icon change inUserCredit.vue.
9-34: LGTM: Clear separation of editable and non-editable modes.The restructured template provides distinct UX for each mode:
- Editable: InputNumber with USD prefix and inline credits label
- Non-editable: Two-line display with emphasized credits and supporting USD
The layout is clear and appropriate for each use case.
80-99: LGTM: Robust clamping and locale-aware formatting.The implementation correctly:
- Clamps values between $1 and $1000, handling NaN cases
- Uses
displayUsdAmountto ensure editable and non-editable paths use the same clamped value- Formats credits and USD with locale-aware helpers
- Appends translated credits label
The clamping on input/blur (lines 20-27) addresses the past review comment about keeping input, labels, and purchase amount in sync.
As per coding guidelines, using vue-i18n for user-facing strings and proper computed properties for derived state.
src/base/credits/comfyCredits.ts (3)
20-26: LGTM: Defensive handling of conflicting fraction digit options.The logic prevents
Intl.NumberFormatfrom throwing whenmaximumFractionDigits < minimumFractionDigitsby adjustingminimumFractionDigitsdown to match. This ensures formatting never fails due to misconfigured options.
1-115: LGTM: Well-structured credit conversion and formatting module.The module provides:
- Clear separation between conversion (USD↔cents↔credits) and formatting
- Type-safe public API with exported types
- Consistent 2-decimal formatting via
DEFAULT_NUMBER_FORMAT- Locale-aware formatting through
Intl.NumberFormat- Defensive option handling to prevent formatting errors
The structure is clean, testable, and provides all necessary utilities for the credit system.
As per coding guidelines, using proper TypeScript types and avoiding
any.
31-46: Add documentation explaining the 210-cent credit rate.The conversion rate ($2.10 per 1 credit) is mathematically correct and well-tested, but lacks any comment explaining the business rationale. This unusual rate (roughly 0.476 credits per $1 USD) differs from typical SaaS platforms that use larger, rounder scales. Add a comment above
COMFY_CREDIT_RATE_CENTSclarifying whether this rate is final, approved, or subject to change—this helps future maintainers understand the intended pricing model.
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts
Show resolved
Hide resolved
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts
Outdated
Show resolved
Hide resolved
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts
Show resolved
Hide resolved
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts (1)
3-3: Usetestinstead ofitper project guidelines.The coding guidelines require using
testinstead ofitfor Vitest test cases.Apply this diff:
-import { describe, expect, it } from 'vitest' +import { describe, expect, test } from 'vitest' describe('CreditTopUpOption', () => { - it('renders credit amount and description', () => { + test('renders credit amount and description', () => { const wrapper = mountOption({ credits: 5000, description: '~500 videos*' }) expect(wrapper.text()).toContain('5,000') expect(wrapper.text()).toContain('~500 videos*') }) - it('applies selected styling when selected', () => { + test('applies selected styling when selected', () => { const wrapper = mountOption({ selected: true }) expect(wrapper.find('div').classes()).toContain('bg-surface-secondary') expect(wrapper.find('div').classes()).toContain('border-primary') }) - it('applies unselected styling when not selected', () => { + test('applies unselected styling when not selected', () => { const wrapper = mountOption({ selected: false }) expect(wrapper.find('div').classes()).toContain('bg-surface-tertiary') expect(wrapper.find('div').classes()).toContain('border-border-primary') }) - it('emits select event when clicked', async () => { + test('emits select event when clicked', async () => { const wrapper = mountOption() await wrapper.find('div').trigger('click') expect(wrapper.emitted('select')).toHaveLength(1) }) })Based on learnings and coding guidelines for tests-ui/**/*.test.{js,ts,jsx,tsx}.
Also applies to: 29-52
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (7)
src/components/dialog/content/TopUpCreditsDialogContent.stories.ts(1 hunks)src/components/dialog/content/TopUpCreditsDialogContent.vue(2 hunks)src/components/dialog/content/credit/CreditTopUpOption.vue(1 hunks)src/components/dialog/content/credit/LegacyCreditTopUpOption.vue(1 hunks)src/locales/en/main.json(1 hunks)src/platform/cloud/subscription/components/SubscriptionPanel.vue(3 hunks)tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (16)
src/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Write expressive and self-documenting code to reduce the need for comments; clean redundant comments as you go
Consider if there is a simpler way to introduce functionality before writing code; choose the simpler approach when possible
Use refactoring to make complex code simpler
Keep functions short and functional
Minimize nesting in code (e.g.,if () { ... }orfor () { ... }) to avoid arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Favor pure functions (especially testable ones)
Watch out for code smells and refactor to avoid them
Implement proper error handling in code
If a complex type definition is inlined in multiple related places, extract and name it for reuse
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
src/components/**/*.vue
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue componentsName Vue components in PascalCase (e.g.,
MenuHamburger.vue)
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
src/components/**/*.{vue,css}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
src/components/**/*.{vue,ts,js}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
**/*.{js,ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript exclusively (no new JavaScript)
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuetests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
**/*.vue
📄 CodeRabbit inference engine (AGENTS.md)
**/*.vue: Use Vue 3 SFCs with Composition API only (.vuefiles)
Use Tailwind 4 styling and avoid<style>blocks in Vue components
Use<script setup lang="ts">for component logic in Vue components
Use Vue 3.5 TypeScript style of default prop declaration with reactive props destructuring
Do not usewithDefaultsor runtime props declaration in Vue components
PreferuseModelto separately defining a prop and emit in Vue components
Usereffor reactive state in Vue components
Implement computed properties withcomputed()instead of usingrefandwatch
UsewatchandwatchEffectfor side effects in Vue components
Useprovide/injectfor dependency injection only when simpler alternatives (Store or composable) are not suitable
Do not use thedark:Tailwind variant; use semantic values fromstyle.csstheme instead (e.g.,bg-node-component-surface)
Useimport { cn } from '@/utils/tailwindUtil'to merge class names instead of:class="[]"
Avoid new usage of PrimeVue components
Use VueUse functions for performance-enhancing styles in Vue components
Do not import Vue macros unnecessarily in components
Be judicious with addition of new refs or other state; prefer using props or composables when possible
Do not add acomputedif it's possible to use arefor prop directly
Do not use awatchif acomputedwould work instead
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,vue}: Do not useanytype in TypeScript code
Do not useas anytype assertions in TypeScript code; fix the underlying type issue
Style formatting: 2 space indent, single quotes, no trailing semicolons, 80 character width
Import statements should be sorted and grouped by plugin; runpnpm formatbefore committing
ESLint rules: no floating promises, no unused imports, i18n raw text restrictions in templates
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuetests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
Use vue-i18n in Composition API for string literals and place new translation entries in
src/locales/en/main.json
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuetests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tssrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Minimize the surface area (exported values) of each module and composable
Use es-toolkit for utility functions
Files:
src/components/dialog/content/TopUpCreditsDialogContent.stories.ts
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/components/dialog/content/credit/CreditTopUpOption.test.ts
**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.ts: Write unit and component tests in**/*.test.ts
Use Vitest with happy-dom for unit and component tests
Files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts
🧠 Learnings (27)
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Define proper props and emits definitions in Vue components
Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Dropdown component with Select
Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.vue : Implement proper props and emits definitions in Vue components
Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Implement proper props and emits definitions
Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Prefer emit/event-name for state changes over other communication patterns
Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vue
📚 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:
src/platform/cloud/subscription/components/SubscriptionPanel.vue
📚 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/components/dialog/content/credit/CreditTopUpOption.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} : Follow existing test patterns in the codebase
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.test.ts : Write unit and component tests in `**/*.test.ts`
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.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} : Use existing test utilities rather than writing custom utilities
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.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: Check tests-ui/README.md for test guidelines
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.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} : Mock external dependencies in tests
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.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/components/dialog/content/credit/CreditTopUpOption.test.ts
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.test.ts : Use Vitest with happy-dom for unit and component tests
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `vitest` for unit testing in this project
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `test` instead of `it` for defining test cases in vitest
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts
📚 Learning: 2025-11-24T19:47:22.909Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: browser_tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:22.909Z
Learning: Applies to browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx} : Follow naming conventions for browser tests
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Applied to files:
src/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 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/**/*.{vue,ts,tsx} : Follow Vue 3 composition API style guide
Applied to files:
src/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.vue : Use Vue 3.5 TypeScript style of default prop declaration with reactive props destructuring
Applied to files:
src/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 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/**/{components,composables}/**/*.{ts,tsx,vue} : Use vue-i18n for ALL user-facing strings by adding them to `src/locales/en/main.json`
Applied to files:
src/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.vue : Follow Vue 3 style guide and naming conventions
Applied to files:
src/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Follow Vue 3 style guide and naming conventions
Applied to files:
src/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Use vue 3.5 style of default prop declaration
Applied to files:
src/components/dialog/content/credit/LegacyCreditTopUpOption.vue
🧬 Code graph analysis (1)
src/components/dialog/content/TopUpCreditsDialogContent.stories.ts (1)
src/components/input/SingleSelect.stories.ts (1)
Story(40-40)
⏰ 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: lint-and-format
- GitHub Check: setup
- GitHub Check: test
- GitHub Check: collect
🔇 Additional comments (2)
src/components/dialog/content/credit/LegacyCreditTopUpOption.vue (1)
111-116: Consider the implications of fire-and-forget balance refresh.The
onBeforeUnmounthook callsfetchBalance()without awaiting, usingvoidto suppress the floating promise warning. While this prevents blocking unmount, it means the balance refresh may not complete if the component unmounts during navigation, potentially leaving stale data.If immediate balance consistency is important, consider refreshing the balance in the parent component after the dialog closes, or document that this is a best-effort refresh that may not complete.
// Current approach (fire-and-forget): void authActions.fetchBalance() // Alternative: Let parent handle refresh after dialog closes // Remove onBeforeUnmount and emit an event for parent to handleThis pattern is acceptable if the balance will be refreshed through other means (e.g., when the user returns to a view that displays the balance), but it's worth documenting the intent.
src/platform/cloud/subscription/components/SubscriptionPanel.vue (1)
124-124: No action needed: composable returns formatted values with units.The
useSubscriptionCreditscomposable returns formatted strings that include units. TheformatBalancefunction (line 14-22 in useSubscriptionCredits.ts) appends the i18n-translated "credits" unit to the formatted amount:return '${amount} ${t('credits.credits')}'. Removing the dollar sign prefix is appropriate since the composable already provides the full formatted value with unit label.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/components/dialog/content/TopUpCreditsDialogContent.vue (2)
151-168: MakecreditOptionsreactive to locale changes.The
creditOptionsarray is initialized once witht()calls, so descriptions won't update if the user changes locale at runtime. This issue was flagged in a previous review and remains unresolved.Convert to a computed property:
-const creditOptions: CreditOption[] = [ +const creditOptions = computed<CreditOption[]>(() => [ { credits: 1000, description: t('credits.topUp.videosEstimate', { count: 100 }) }, { credits: 5000, description: t('credits.topUp.videosEstimate', { count: 500 }) }, { credits: 10000, description: t('credits.topUp.videosEstimate', { count: 1000 }) }, { credits: 20000, description: t('credits.topUp.videosEstimate', { count: 2000 }) } -] +])As per coding guidelines, this ensures descriptions update immediately when locale changes, improving the i18n user experience.
170-186: Replace placeholder conversion logic and complete success handling.Multiple issues remain in this function:
- Line 178: The conversion uses placeholder logic (
selectedCredits.value / 100). According to the PR description, this PR introduces conversion helpers that should be used here.- Line 180: The TODO comment indicates incomplete success handling (no event emission or dialog close).
- Line 182: Error handling only logs to console without user-facing feedback.
The conversion logic issue was flagged in a previous review. Import and use the proper conversion utilities from the comfy-credits domain:
+import { creditsToUsd } from '@/utils/comfyCredits' + const handleBuy = async () => { if (!selectedCredits.value) return - telemetry?.trackApiCreditTopupButtonPurchaseClicked(selectedCredits.value) - loading.value = true try { - // Convert credits to USD (this would need to be implemented based on your conversion rate) - const usdAmount = selectedCredits.value / 100 // Example conversion, adjust as needed + const usdAmount = creditsToUsd(selectedCredits.value) + telemetry?.trackApiCreditTopupButtonPurchaseClicked(usdAmount) await authActions.purchaseCredits(usdAmount) - // Optionally emit success event or close dialog + // TODO: Emit success event or close dialog on successful purchase } catch (error) { console.error('Purchase failed:', error) + // TODO: Show user-facing error message (e.g., toast notification) } finally { loading.value = false } }The placeholder conversion logic must be fixed before production as it will cause incorrect charges.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
src/components/dialog/content/TopUpCreditsDialogContent.stories.ts(1 hunks)src/components/dialog/content/TopUpCreditsDialogContent.vue(2 hunks)src/composables/useFeatureFlags.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (16)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/composables/useFeatureFlags.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Minimize the surface area (exported values) of each module and composable
Use es-toolkit for utility functions
Files:
src/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/composables/useFeatureFlags.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Write expressive and self-documenting code to reduce the need for comments; clean redundant comments as you go
Consider if there is a simpler way to introduce functionality before writing code; choose the simpler approach when possible
Use refactoring to make complex code simpler
Keep functions short and functional
Minimize nesting in code (e.g.,if () { ... }orfor () { ... }) to avoid arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Favor pure functions (especially testable ones)
Watch out for code smells and refactor to avoid them
Implement proper error handling in code
If a complex type definition is inlined in multiple related places, extract and name it for reuse
Files:
src/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/composables/useFeatureFlags.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/composables/useFeatureFlags.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/composables/useFeatureFlags.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/composables/useFeatureFlags.ts
src/components/**/*.{vue,ts,js}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings
Files:
src/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/components/dialog/content/TopUpCreditsDialogContent.vue
**/*.{js,ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript exclusively (no new JavaScript)
Files:
src/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/composables/useFeatureFlags.ts
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,vue}: Do not useanytype in TypeScript code
Do not useas anytype assertions in TypeScript code; fix the underlying type issue
Style formatting: 2 space indent, single quotes, no trailing semicolons, 80 character width
Import statements should be sorted and grouped by plugin; runpnpm formatbefore committing
ESLint rules: no floating promises, no unused imports, i18n raw text restrictions in templates
Files:
src/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/composables/useFeatureFlags.ts
**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
Use vue-i18n in Composition API for string literals and place new translation entries in
src/locales/en/main.json
Files:
src/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/composables/useFeatureFlags.ts
src/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
Files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
src/components/**/*.vue
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue componentsName Vue components in PascalCase (e.g.,
MenuHamburger.vue)
Files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
src/components/**/*.{vue,css}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package
Files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
**/*.vue
📄 CodeRabbit inference engine (AGENTS.md)
**/*.vue: Use Vue 3 SFCs with Composition API only (.vuefiles)
Use Tailwind 4 styling and avoid<style>blocks in Vue components
Use<script setup lang="ts">for component logic in Vue components
Use Vue 3.5 TypeScript style of default prop declaration with reactive props destructuring
Do not usewithDefaultsor runtime props declaration in Vue components
PreferuseModelto separately defining a prop and emit in Vue components
Usereffor reactive state in Vue components
Implement computed properties withcomputed()instead of usingrefandwatch
UsewatchandwatchEffectfor side effects in Vue components
Useprovide/injectfor dependency injection only when simpler alternatives (Store or composable) are not suitable
Do not use thedark:Tailwind variant; use semantic values fromstyle.csstheme instead (e.g.,bg-node-component-surface)
Useimport { cn } from '@/utils/tailwindUtil'to merge class names instead of:class="[]"
Avoid new usage of PrimeVue components
Use VueUse functions for performance-enhancing styles in Vue components
Do not import Vue macros unnecessarily in components
Be judicious with addition of new refs or other state; prefer using props or composables when possible
Do not add acomputedif it's possible to use arefor prop directly
Do not use awatchif acomputedwould work instead
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
Files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/composables/useFeatureFlags.ts
src/composables/use*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables as
useXyz.ts
Files:
src/composables/useFeatureFlags.ts
🧠 Learnings (6)
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.{ts,vue} : Use vue-i18n in Composition API for string literals and place new translation entries in `src/locales/en/main.json`
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
📚 Learning: 2025-12-05T20:35:28.330Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7137
File: src/locales/en/main.json:2257-2272
Timestamp: 2025-12-05T20:35:28.330Z
Learning: In the Comfy-Org/ComfyUI_frontend repository, vue-i18n pluralization uses a two-parameter pattern: `t('key', { count: value })` where the `count` property in the interpolation object automatically triggers plural selection from pipe-separated locale strings (e.g., "no items | 1 item | {count} items"). This is the correct pattern used throughout the codebase, as validated by Playwright tests.
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
📚 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/**/{components,composables}/**/*.{ts,tsx,vue} : Use vue-i18n for ALL user-facing strings by adding them to `src/locales/en/main.json`
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Implement computed properties with computed()
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.vue : Implement computed properties with `computed()` instead of using `ref` and `watch`
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
🧬 Code graph analysis (2)
src/components/dialog/content/TopUpCreditsDialogContent.stories.ts (1)
src/components/input/SingleSelect.stories.ts (1)
Story(40-40)
src/composables/useFeatureFlags.ts (1)
src/scripts/api.ts (1)
api(1289-1289)
🔇 Additional comments (3)
src/composables/useFeatureFlags.ts (1)
12-13: LGTM!The new
SUBSCRIPTION_TIERS_ENABLEDfeature flag is implemented consistently with existing flags and properly defaults totruefor the new design.Also applies to: 35-41
src/components/dialog/content/TopUpCreditsDialogContent.stories.ts (1)
1-41: LGTM!The Storybook setup is well-structured with proper TypeScript typing, clear documentation, and coverage of both
refreshDatestates (present and undefined).src/components/dialog/content/TopUpCreditsDialogContent.vue (1)
110-138: LGTM!The imports, interface definition, and props destructuring follow Vue 3.5 Composition API patterns correctly. The
CreditOptioninterface is well-defined, and the newrefreshDateprop is properly typed as optional.
- Add new credit selection UI matching Figma design (1k, 5k, 10k, 20k credits) - Remove manual input, use predefined amounts with video estimates - Integrate with subscription_tiers_enabled feature flag (defaults to true) - Fix credit to USD conversion using proper comfyCredits utilities - Add user-facing error handling with toast notifications - Extract shared parameter types in comfyCredits.ts for better DRY - Add reactive feature flag support with computed() - Create Storybook stories for easy testing - Maintain backward compatibility with legacy design 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Add formatCreditsFromSubscriptionMicros for special backend format - Update useSubscriptionCredits to use subscription-specific conversion - Fix test mocking to use new function - Keep standard credit conversion unchanged (210 credits per USD) - Backend sends subscription data in format where 210 units = 1 credit 🤖 Generated with Claude Code Co-Authored-By: Claude <[email protected]>
- Replace inline formatting with shared formatters in TopUpCreditsDialogContent - Fix error handling in LegacyCreditTopUpOption to prevent stuck loading state - Extract clampUsd function to shared utilities for reuse - Replace local Intl.NumberFormat with shared formatCredits utility - Remove accidentally committed markdown file
Return 0 immediately for NaN values instead of clamping NaN->0->1, making the actual behavior consistent with the documented behavior.
- Update CREDITS_PER_USD constant and all dependent calculations - Update test expectations to match new conversion rate - Update subscription conversion comments and test values
715b539 to
3cf8c9d
Compare
The test was failing because subscriptionTiersEnabled defaults to true, causing isCreditsBadge to check for componentIconSvg instead of unicode. Mock the feature flag to false to test legacy badge behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
♻️ Duplicate comments (4)
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (1)
19-24: Mock data still hardcodes formatted strings instead of raw values.The mock now returns fully formatted strings like
'10.00 Credits'matching the updated composable output. However, this still tightly couples the test to the formatting implementation as previously noted. If the formatting logic changes, both the composable and these mocks must be updated.tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts (1)
1-52: Usetestinstead ofitper project guidelines.Based on the coding guidelines, test cases should use
testinstead ofitin Vitest. This has been noted in previous reviews.tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts (1)
2-2: Usetestinstead ofitper project guidelines.The test cases use
itbut project guidelines requiretestin Vitest. This has been noted in previous reviews.Also applies to: 80-140
src/components/dialog/content/TopUpCreditsDialogContent.vue (1)
158-175: MakecreditOptionsreactive to locale changes.The
creditOptionsarray is initialized once witht()calls, so descriptions won't update if the user changes locale at runtime. Convert to a computed property.-const creditOptions: CreditOption[] = [ +const creditOptions = computed<CreditOption[]>(() => [ { credits: 1000, description: t('credits.topUp.videosEstimate', { count: 100 }) }, // ... other options -] +])Then update the template to use
creditOptions.valuein thev-for.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (14)
src/base/credits/comfyCredits.ts(1 hunks)src/components/common/UserCredit.vue(2 hunks)src/components/dialog/content/TopUpCreditsDialogContent.stories.ts(1 hunks)src/components/dialog/content/TopUpCreditsDialogContent.vue(2 hunks)src/components/dialog/content/credit/CreditTopUpOption.vue(1 hunks)src/components/dialog/content/credit/LegacyCreditTopUpOption.vue(1 hunks)src/composables/useFeatureFlags.ts(1 hunks)src/locales/en/main.json(1 hunks)src/platform/cloud/subscription/components/SubscriptionPanel.vue(3 hunks)src/platform/cloud/subscription/composables/useSubscriptionCredits.ts(1 hunks)tests-ui/tests/base/credits/comfyCredits.test.ts(1 hunks)tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.ts(1 hunks)tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts(2 hunks)tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (18)
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.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.test.ts
**/*.{js,ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript exclusively (no new JavaScript)
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tssrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuetests-ui/tests/base/credits/comfyCredits.test.tssrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/base/credits/comfyCredits.tssrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/composables/useFeatureFlags.ts
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,vue}: Do not useanytype in TypeScript code
Do not useas anytype assertions in TypeScript code; fix the underlying type issue
Style formatting: 2 space indent, single quotes, no trailing semicolons, 80 character width
Import statements should be sorted and grouped by plugin; runpnpm formatbefore committing
ESLint rules: no floating promises, no unused imports, i18n raw text restrictions in templates
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tssrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuetests-ui/tests/base/credits/comfyCredits.test.tssrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/base/credits/comfyCredits.tssrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/composables/useFeatureFlags.ts
**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.ts: Write unit and component tests in**/*.test.ts
Use Vitest with happy-dom for unit and component tests
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.test.ts
**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
Use vue-i18n in Composition API for string literals and place new translation entries in
src/locales/en/main.json
Files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tssrc/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuetests-ui/tests/base/credits/comfyCredits.test.tssrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/base/credits/comfyCredits.tssrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/composables/useFeatureFlags.ts
src/**/*.vue
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.vue: Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/base/credits/comfyCredits.tssrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/composables/useFeatureFlags.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Write expressive and self-documenting code to reduce the need for comments; clean redundant comments as you go
Consider if there is a simpler way to introduce functionality before writing code; choose the simpler approach when possible
Use refactoring to make complex code simpler
Keep functions short and functional
Minimize nesting in code (e.g.,if () { ... }orfor () { ... }) to avoid arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Favor pure functions (especially testable ones)
Watch out for code smells and refactor to avoid them
Implement proper error handling in code
If a complex type definition is inlined in multiple related places, extract and name it for reuse
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/base/credits/comfyCredits.tssrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/composables/useFeatureFlags.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/composables/useFeatureFlags.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/base/credits/comfyCredits.tssrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/composables/useFeatureFlags.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vuesrc/composables/useFeatureFlags.ts
src/components/**/*.vue
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue componentsName Vue components in PascalCase (e.g.,
MenuHamburger.vue)
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
src/components/**/*.{vue,css}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
src/components/**/*.{vue,ts,js}
📄 CodeRabbit inference engine (src/components/CLAUDE.md)
src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
**/*.vue
📄 CodeRabbit inference engine (AGENTS.md)
**/*.vue: Use Vue 3 SFCs with Composition API only (.vuefiles)
Use Tailwind 4 styling and avoid<style>blocks in Vue components
Use<script setup lang="ts">for component logic in Vue components
Use Vue 3.5 TypeScript style of default prop declaration with reactive props destructuring
Do not usewithDefaultsor runtime props declaration in Vue components
PreferuseModelto separately defining a prop and emit in Vue components
Usereffor reactive state in Vue components
Implement computed properties withcomputed()instead of usingrefandwatch
UsewatchandwatchEffectfor side effects in Vue components
Useprovide/injectfor dependency injection only when simpler alternatives (Store or composable) are not suitable
Do not use thedark:Tailwind variant; use semantic values fromstyle.csstheme instead (e.g.,bg-node-component-surface)
Useimport { cn } from '@/utils/tailwindUtil'to merge class names instead of:class="[]"
Avoid new usage of PrimeVue components
Use VueUse functions for performance-enhancing styles in Vue components
Do not import Vue macros unnecessarily in components
Be judicious with addition of new refs or other state; prefer using props or composables when possible
Do not add acomputedif it's possible to use arefor prop directly
Do not use awatchif acomputedwould work instead
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions
Files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Minimize the surface area (exported values) of each module and composable
Use es-toolkit for utility functions
Files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/base/credits/comfyCredits.tssrc/composables/useFeatureFlags.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/composables/useFeatureFlags.ts
src/composables/use*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Name composables as
useXyz.ts
Files:
src/composables/useFeatureFlags.ts
🧠 Learnings (41)
📚 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.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.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.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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
Applied to files:
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.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.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.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.tstests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.test.tssrc/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/components/dialog/content/TopUpCreditsDialogContent.stories.tssrc/base/credits/comfyCredits.tssrc/composables/useFeatureFlags.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} : Follow existing test patterns in the codebase
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.test.ts : Write unit and component tests in `**/*.test.ts`
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/base/credits/comfyCredits.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} : Use existing test utilities rather than writing custom utilities
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.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: Check tests-ui/README.md for test guidelines
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.test.ts : Use Vitest with happy-dom for unit and component tests
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `vitest` for unit testing in this project
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:47:22.909Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: browser_tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:22.909Z
Learning: Applies to browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx} : Follow naming conventions for browser tests
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `test` instead of `it` for defining test cases in vitest
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`
Applied to files:
tests-ui/tests/components/dialog/content/credit/CreditTopUpOption.test.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setup
Applied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch
Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-12-05T20:35:28.330Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7137
File: src/locales/en/main.json:2257-2272
Timestamp: 2025-12-05T20:35:28.330Z
Learning: In the Comfy-Org/ComfyUI_frontend repository, vue-i18n pluralization uses a two-parameter pattern: `t('key', { count: value })` where the `count` property in the interpolation object automatically triggers plural selection from pipe-separated locale strings (e.g., "no items | 1 item | {count} items"). This is the correct pattern used throughout the codebase, as validated by Playwright tests.
Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vuetests-ui/tests/base/credits/comfyCredits.test.tssrc/components/dialog/content/TopUpCreditsDialogContent.vue
📚 Learning: 2025-12-09T03:49:52.828Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/platform/updates/components/WhatsNewPopup.vue:5-13
Timestamp: 2025-12-09T03:49:52.828Z
Learning: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML <button> elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.
Applied to files:
src/components/dialog/content/credit/CreditTopUpOption.vuesrc/components/common/UserCredit.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/platform/cloud/subscription/components/SubscriptionPanel.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 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/**/{components,composables}/**/*.{ts,tsx,vue} : Use vue-i18n for ALL user-facing strings by adding them to `src/locales/en/main.json`
Applied to files:
src/components/common/UserCredit.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Applied to files:
src/components/common/UserCredit.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.{ts,vue} : Use vue-i18n in Composition API for string literals and place new translation entries in `src/locales/en/main.json`
Applied to files:
src/components/common/UserCredit.vuesrc/components/dialog/content/TopUpCreditsDialogContent.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.{vue,ts,js} : Use vue-i18n for ALL UI strings
Applied to files:
src/components/common/UserCredit.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Leverage VueUse functions for performance-enhancing styles
Applied to files:
src/components/common/UserCredit.vue
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.vue : Avoid new usage of PrimeVue components
Applied to files:
src/components/common/UserCredit.vue
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Tests should be cross-platform compatible using `path.resolve`, `path.join`, and `path.sep` for Windows, macOS, and Linux compatibility
Applied to files:
tests-ui/tests/base/credits/comfyCredits.test.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition API
Applied to files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Implement computed properties with computed()
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.vue : Implement computed properties with `computed()` instead of using `ref` and `watch`
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Utilize ref and reactive for reactive state
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use ref/reactive for state management in Vue 3 Composition API
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.vue : Be judicious with addition of new refs or other state; prefer using props or composables when possible
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.vue : Use `ref` for reactive state in Vue components
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vue
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Implement proper error handling
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Implement proper error handling in code
Applied to files:
src/components/dialog/content/TopUpCreditsDialogContent.vuesrc/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-12-09T04:35:40.491Z
Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 6300
File: src/locales/en/main.json:774-780
Timestamp: 2025-12-09T04:35:40.491Z
Learning: In the Comfy-Org/ComfyUI_frontend repository, locale files other than `src/locales/en/main.json` are generated automatically on every release. Developers only need to add English (en) key/values in `src/locales/en/main.json` when making PRs; manual updates to other locale files (fr, ja, ko, ru, zh, zh-TW, es, ar, tr, etc.) are not required and should not be suggested in reviews.
Applied to files:
src/locales/en/main.json
📚 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:
src/platform/cloud/subscription/components/SubscriptionPanel.vue
📚 Learning: 2025-12-08T01:21:41.351Z
Learnt from: jtydhr88
Repo: Comfy-Org/ComfyUI_frontend PR: 7214
File: src/i18n.ts:97-98
Timestamp: 2025-12-08T01:21:41.351Z
Learning: In src/i18n.ts and related i18n code, use `Record<string, unknown>` for locale data structures (including custom nodes i18n data) to maintain consistency with existing patterns used in localeLoaders, nodeDefsLoaders, commandsLoaders, and settingsLoaders.
Applied to files:
src/base/credits/comfyCredits.ts
📚 Learning: 2025-11-24T19:47:02.860Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)
Applied to files:
src/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.vue : Use Vue 3.5 TypeScript style of default prop declaration with reactive props destructuring
Applied to files:
src/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 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/**/*.{vue,ts,tsx} : Follow Vue 3 composition API style guide
Applied to files:
src/components/dialog/content/credit/LegacyCreditTopUpOption.vue
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.vue : Implement proper props and emits definitions in Vue components
Applied to files:
src/components/dialog/content/credit/LegacyCreditTopUpOption.vue
🧬 Code graph analysis (3)
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts (1)
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (1)
useSubscriptionCredits(10-69)
tests-ui/tests/base/credits/comfyCredits.test.ts (1)
src/base/credits/comfyCredits.ts (12)
CREDITS_PER_USD(31-31)COMFY_CREDIT_RATE_CENTS(32-32)usdToCents(34-34)formatUsdFromCents(123-132)centsToCredits(36-37)creditsToCents(39-40)usdToCredits(42-43)creditsToUsd(45-46)formatCredits(66-71)formatCreditsFromCents(73-82)formatCreditsFromUsd(84-93)formatUsd(112-121)
src/components/dialog/content/TopUpCreditsDialogContent.stories.ts (1)
src/components/input/SingleSelect.stories.ts (1)
Story(40-40)
⏰ 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
🔇 Additional comments (13)
tests-ui/tests/platform/cloud/subscription/components/SubscriptionPanel.test.ts (1)
157-158: LGTM: Assertions align with updated mock data.The assertions correctly verify the formatted credit values with the " Credits" suffix, consistent with the new formatting approach.
src/platform/cloud/subscription/components/SubscriptionPanel.vue (1)
124-124: LGTM: Credit display now uses composable-formatted values.The component correctly removes the dollar sign prefix and displays the formatted values from
useSubscriptionCredits, which include the " Credits" suffix per the new formatting approach. This aligns with the PR's goal of standardizing credit display across the UI.Also applies to: 137-137, 165-165
tests-ui/tests/base/credits/comfyCredits.test.ts (1)
1-46: LGTM: Comprehensive test coverage with proper locale handling.The tests correctly use
testinstead ofit, pass explicit locale to all formatting functions for deterministic results, and cover the full range of conversion and formatting utilities. Previous review comments have been addressed.src/components/dialog/content/credit/CreditTopUpOption.vue (1)
1-43: LGTM: Component simplified to passive option card with proper formatting.The component has been successfully refactored from an interactive purchase component to a passive selectable option card. Key improvements:
- Uses shared
formatCreditsutility for consistent formatting- Locale-aware via vue-i18n
- Clear separation of concerns (presentation only, no business logic)
- Previous review comments regarding clamping and formatting have been addressed
Note: This is a breaking API change (props and emits changed), but tests have been updated accordingly.
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts (1)
8-17: LGTM: Clean mock strategy and comprehensive error handling tests.The vue-i18n mock is well-structured and the error handling test properly uses a spy on
formatCreditsFromSubscriptionMicrosto verify fallback behavior. The test coverage effectively validates that the composable returns formatted strings with the expected " Credits" suffix.Also applies to: 99-111
src/composables/useFeatureFlags.ts (1)
60-69: The feature flag default change is intentional and properly coordinated.The
subscriptionTiersEnableddefault is documented inTopUpCreditsDialogContent.stories.tsas "(defaults to new design)" and is backed by complete backend support for subscription tier APIs. The feature flag can still be overridden via remote config if needed, making this a safe, controlled rollout.src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (1)
14-23: LGTM on the formatBalance helper.The inline comment clarifies the non-standard unit conversion (211 units = 1 credit), addressing the previous concern about the
*_microsnaming convention. The implementation correctly uses the shared formatter with locale support.src/components/dialog/content/TopUpCreditsDialogContent.vue (2)
146-148: LGTM on reactive feature flag.The
useNewDesignis now correctly wrapped incomputed(), ensuring the UI updates if the feature flag changes at runtime.
177-212: LGTM on purchase handler with comprehensive error handling.The
handleBuyfunction properly handles the purchase flow with:
- Loading state management via try/finally
- Success toast with formatted credits and amount
- Error toast with extracted error message
- Telemetry tracking
This addresses the previous feedback about user-facing error handling.
src/components/dialog/content/TopUpCreditsDialogContent.stories.ts (1)
1-41: LGTM on Storybook stories.The story file follows standard Storybook conventions with appropriate coverage for the
refreshDateprop variations. The documentation clearly explains the feature flag behavior.src/locales/en/main.json (1)
1847-1861: LGTM on new locale entries.The new credit-related locale keys follow established patterns with proper interpolation syntax for dynamic values (
{count},{credits},{amount},{error},{date}).src/base/credits/comfyCredits.ts (2)
6-29: Shared formatter helper is cohesive and defensive.Centralizing locale-aware formatting in
formatNumberwith default+override merging and a min/max fraction guard keeps all public formatters consistent without mutating caller options. No changes needed here.
134-142:clampUsdbehavior and JSDoc are now consistent.Early NaN handling with
return 0plus clamping numeric inputs into[1, 1000]matches the documentation and gives a clear, safe contract for caller code.
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts
Outdated
Show resolved
Hide resolved
1. Fix critical business logic inconsistency: - Both UserCredit.vue and useSubscriptionCredits use same backend field (amount_micros) - Field contains cents despite *_micros naming convention - Unified to use formatCreditsFromCents for consistent conversion 2. Remove duplicate try/catch blocks in computed properties: - formatBalance handles undefined values safely via ?? operator - Simplified computed properties to direct function calls - Updated error handling test to expect errors to propagate 3. Remove unused formatCreditsFromSubscriptionMicros function
- Remove unused context parameter - Add required currency field to mock balance data - Use proper typing for Firebase auth store balance object
|
Due to the deadline, I really need to merge this. Future PRs will be fixing the style to make it match the designs exactly. Please leave reviews still and I will implement changes tomorrow. |
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (2)
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts (1)
2-2: Usetestinstead ofitper project guidelines.This was already flagged in a previous review. Replace
itwithtestthroughout the file.src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (1)
14-22: API naming discrepancy persists.The comment on line 15 documents that the backend returns cents despite the
*_microsnaming convention. This was flagged in a previous review regarding the mismatch between backend schema documentation (claiming "microamount 1/1,000,000") and actual values (cents 1/100).While the comment helps, this should be tracked for resolution with the backend team to ensure the API contract is correctly documented.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (5)
.storybook/preview.ts(1 hunks)src/base/credits/comfyCredits.ts(1 hunks)src/platform/cloud/subscription/composables/useSubscriptionCredits.ts(1 hunks)tests-ui/tests/composables/node/useCreditsBadge.test.ts(1 hunks)tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (12)
src/**/*.{vue,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
Files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.ts
src/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety
src/**/*.ts: Minimize the surface area (exported values) of each module and composable
Use es-toolkit for utility functions
Files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.ts
src/**/{services,composables}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/{services,composables}/**/*.{ts,tsx}: Useapi.apiURL()for backend endpoints instead of constructing URLs directly
Useapi.fileURL()for static file access instead of constructing URLs directly
Files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts
src/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase
src/**/*.{ts,tsx,vue}: Write expressive and self-documenting code to reduce the need for comments; clean redundant comments as you go
Consider if there is a simpler way to introduce functionality before writing code; choose the simpler approach when possible
Use refactoring to make complex code simpler
Keep functions short and functional
Minimize nesting in code (e.g.,if () { ... }orfor () { ... }) to avoid arrow anti-pattern
Avoid mutable state; prefer immutability and assignment at point of declaration
Favor pure functions (especially testable ones)
Watch out for code smells and refactor to avoid them
Implement proper error handling in code
If a complex type definition is inlined in multiple related places, extract and name it for reuse
Files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.ts
src/**/{composables,components}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Clean up subscriptions in state management to prevent memory leaks
Files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts
src/**/*.{vue,ts,tsx}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Follow Vue 3 composition API style guide
Files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tssrc/base/credits/comfyCredits.ts
src/**/{components,composables}/**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (src/CLAUDE.md)
Use vue-i18n for ALL user-facing strings by adding them to
src/locales/en/main.json
Files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts
**/*.{js,ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript exclusively (no new JavaScript)
Files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/composables/node/useCreditsBadge.test.tssrc/base/credits/comfyCredits.ts
**/*.{ts,tsx,vue}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,vue}: Do not useanytype in TypeScript code
Do not useas anytype assertions in TypeScript code; fix the underlying type issue
Style formatting: 2 space indent, single quotes, no trailing semicolons, 80 character width
Import statements should be sorted and grouped by plugin; runpnpm formatbefore committing
ESLint rules: no floating promises, no unused imports, i18n raw text restrictions in templates
Files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/composables/node/useCreditsBadge.test.tssrc/base/credits/comfyCredits.ts
**/*.{ts,vue}
📄 CodeRabbit inference engine (AGENTS.md)
Use vue-i18n in Composition API for string literals and place new translation entries in
src/locales/en/main.json
Files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/composables/node/useCreditsBadge.test.tssrc/base/credits/comfyCredits.ts
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/composables/useSubscriptionCredits.test.tstests-ui/tests/composables/node/useCreditsBadge.test.ts
**/*.test.ts
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.ts: Write unit and component tests in**/*.test.ts
Use Vitest with happy-dom for unit and component tests
Files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/composables/node/useCreditsBadge.test.ts
🧠 Learnings (18)
📚 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/**/{components,composables}/**/*.{ts,tsx,vue} : Use vue-i18n for ALL user-facing strings by adding them to `src/locales/en/main.json`
Applied to files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts.storybook/preview.ts
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition API
Applied to files:
src/platform/cloud/subscription/composables/useSubscriptionCredits.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:
src/platform/cloud/subscription/composables/useSubscriptionCredits.tstests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/composables/node/useCreditsBadge.test.tssrc/base/credits/comfyCredits.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} : Mock external dependencies in tests
Applied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/composables/node/useCreditsBadge.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/composables/useSubscriptionCredits.test.tstests-ui/tests/composables/node/useCreditsBadge.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/composables/useSubscriptionCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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
Applied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.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/composables/useSubscriptionCredits.test.tstests-ui/tests/composables/node/useCreditsBadge.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `test` instead of `it` for defining test cases in vitest
Applied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Use `vitest` for unit testing in this project
Applied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
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} : Prefer the use of `test.extend` over loose variables; import `test as baseTest` from `vitest`
Applied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.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} : Follow existing test patterns in the codebase
Applied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.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} : Use existing test utilities rather than writing custom utilities
Applied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/composables/node/useCreditsBadge.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: Check tests-ui/README.md for test guidelines
Applied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts
📚 Learning: 2025-12-09T02:44:38.234Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T02:44:38.234Z
Learning: Applies to **/*.test.ts : Use Vitest with happy-dom for unit and component tests
Applied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts
📚 Learning: 2025-11-24T19:47:22.909Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: browser_tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:22.909Z
Learning: Applies to browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx} : Follow naming conventions for browser tests
Applied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts
📚 Learning: 2025-11-24T19:47:56.371Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/lib/litegraph/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:56.371Z
Learning: Applies to src/lib/litegraph/**/*.{test,spec}.{ts,tsx} : Use provided test helpers `createTestSubgraph` and `createTestSubgraphNode` from `./fixtures/subgraphHelpers` for consistent subgraph test setup
Applied to files:
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.tstests-ui/tests/composables/node/useCreditsBadge.test.ts
📚 Learning: 2025-12-08T01:21:41.351Z
Learnt from: jtydhr88
Repo: Comfy-Org/ComfyUI_frontend PR: 7214
File: src/i18n.ts:97-98
Timestamp: 2025-12-08T01:21:41.351Z
Learning: In src/i18n.ts and related i18n code, use `Record<string, unknown>` for locale data structures (including custom nodes i18n data) to maintain consistency with existing patterns used in localeLoaders, nodeDefsLoaders, commandsLoaders, and settingsLoaders.
Applied to files:
src/base/credits/comfyCredits.ts
🧬 Code graph analysis (2)
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (1)
src/base/credits/comfyCredits.ts (1)
formatCreditsFromCents(73-82)
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts (1)
src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (1)
useSubscriptionCredits(10-44)
⏰ 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: setup
- GitHub Check: lint-and-format
- GitHub Check: test
- GitHub Check: collect
🔇 Additional comments (8)
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts (1)
139-148: LGTM!The
isLoadingBalancetest correctly verifies the computed property reflects the store'sisFetchingBalancestate reactively.tests-ui/tests/composables/node/useCreditsBadge.test.ts (1)
20-26: LGTM!The mock correctly isolates the legacy badge behavior by disabling
subscriptionTiersEnabled. The inline comment clearly documents the test intent.src/platform/cloud/subscription/composables/useSubscriptionCredits.ts (1)
10-43: Well-structured composable with clean formatting logic.The
formatBalancehelper centralizes the formatting logic effectively. The composable correctly:
- Uses
computed()for derived state- Leverages i18n for user-facing strings
- Provides a clean public API surface
The simplification of error handling (removing try/catch) aligns with the previous review feedback.
src/base/credits/comfyCredits.ts (5)
1-29: Well-implemented number formatting with defensive validation.The
formatNumberhelper correctly:
- Provides sensible defaults (2 decimal places)
- Validates that
maximumFractionDigits >= minimumFractionDigitsto prevent Intl.NumberFormat errors- Uses proper locale-aware formatting
This is a solid foundation for the credit formatting utilities.
31-46: Conversion functions are mathematically sound.The rounding strategies are appropriate:
Math.round()for integer conversions (cents, credits)- Two-step rounding in
creditsToUsd(* 100 / 100) ensures USD precision to 2 decimal placesThe functions maintain consistency across the conversion chain.
48-64: LGTM!The exported types are clean and provide good API documentation. This addresses the prior review suggestion about extracting shared parameter types.
95-115: Note:formatUsdproduces plain numbers, not currency-formatted strings.
formatUsdformats the numeric value without a currency symbol (e.g., "10.00" not "$10.00"). This appears intentional for flexibility, but verify this matches the expected usage in UI components that consume this function.If currency symbols are needed in some contexts, consider either:
- Adding a separate
formatUsdCurrencyvariant usingstyle: 'currency'- Documenting this behavior in a JSDoc comment
117-125: LGTM!The
clampUsdimplementation correctly handles:
- NaN input → returns 0 (early exit)
- Valid numbers → clamped to [1, 1000]
The JSDoc accurately describes this behavior. This addresses the prior review concern about documentation mismatch.
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts
Outdated
Show resolved
Hide resolved
tests-ui/tests/platform/cloud/subscription/composables/useSubscriptionCredits.test.ts
Show resolved
Hide resolved
- Remove unused __STORYBOOK__ global declaration and assignment - Fix vi.mock importOriginal parameter typing to use proper module type - Replace 'as any' type assertions with proper GetCustomerBalanceResponse type - Import and use typed GetCustomerBalanceResponse from comfyRegistryTypes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
|
Will implement designs properly in followup PR. |
Introduces cents<->usd<->credit converters plus basic formatters and adds test. Lays groundwork to start converting UI components into displaying comfy credits. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7061-add-shared-comfy-credit-conversion-helpers-2bb6d73d3650810bb34fdf9bb3fc115b) by [Unito](https://www.unito.io) --------- Co-authored-by: Claude <[email protected]>
|
@christian-byrne Successfully backported to #7293 |
Backport of #7061 to `cloud/1.34` Automatically created by backport workflow. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7293-backport-cloud-1-34-add-shared-comfy-credit-conversion-helpers-2c46d73d365081a9b1bcfb82462c3d7f) by [Unito](https://www.unito.io) Co-authored-by: Christian Byrne <[email protected]> Co-authored-by: Claude <[email protected]>
Introduces cents<->usd<->credit converters plus basic formatters and adds test. Lays groundwork to start converting UI components into displaying comfy credits. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7061-add-shared-comfy-credit-conversion-helpers-2bb6d73d3650810bb34fdf9bb3fc115b) by [Unito](https://www.unito.io) --------- Co-authored-by: Claude <[email protected]>
Introduces cents<->usd<->credit converters plus basic formatters and adds test. Lays groundwork to start converting UI components into displaying comfy credits.
┆Issue is synchronized with this Notion page by Unito