mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-01-26 10:59:53 +00:00
## Summary Standing on the shoulders of giants. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7295-Testing-section-update-2c46d73d3650818f935bcb2ac65d9830) by [Unito](https://www.unito.io)
9.4 KiB
9.4 KiB
Repository Guidelines
Project Structure & Module Organization
- Source:
src/- Vue 3.5+
- TypeScript
- Tailwind 4
- Key areas:
components/views/stores/(Pinia)composables/services/utils/assets/locales/
- Routing:
src/router.ts, - i18n:
src/i18n.ts, - Entry Point:
src/main.ts. - Tests:
- unit/component in
tests-ui/andsrc/**/*.test.ts - E2E (Playwright) in
browser_tests/**/*.spec.ts
- unit/component in
- Public assets:
public/ - Build output:
dist/ - Configs
vite.config.mtsvitest.config.tsplaywright.config.tseslint.config.ts.prettierrc- etc.
Monorepo Architecture
The project uses Nx for build orchestration and task management
Build, Test, and Development Commands
pnpm dev: Start Vite dev server.pnpm dev:electron: Dev server with Electron API mockspnpm build: Type-check then production build todist/pnpm preview: Preview the production build locallypnpm test:unit: Run Vitest unit testspnpm test:browser: Run Playwright E2E tests (browser_tests/)pnpm lint/pnpm lint:fix: Lint (ESLint)pnpm format/pnpm format:check: Prettierpnpm typecheck: Vue TSC type checking
Coding Style & Naming Conventions
- Language:
- TypeScript (exclusive, no new JavaScript)
- Vue 3 SFCs (
.vue)- Composition API only
- Tailwind 4 styling
- Avoid
<style>blocks
- Avoid
- Style: (see
.prettierrc)- Indent 2 spaces
- single quotes
- no trailing semicolons
- width 80
- Imports:
- sorted/grouped by plugin
- run
pnpm formatbefore committing
- ESLint:
- Vue + TS rules
- no floating promises
- unused imports disallowed
- i18n raw text restrictions in templates
- Naming:
- Vue components in PascalCase (e.g.,
MenuHamburger.vue) - composables
useXyz.ts - Pinia stores
*Store.ts
- Vue components in PascalCase (e.g.,
Commit & Pull Request Guidelines
- PRs:
- Include clear description
- Reference linked issues (e.g.
- Fixes #123) - Keep it extremely concise and information-dense
- Don't use emojis or add excessive headers/sections
- Follow the PR description template in the
.github/folder.
- Quality gates:
pnpm lintpnpm typecheckpnpm knip- Relevant tests must pass
- Never use
--no-verifyto bypass failing tests- Identify the issue and present root cause analysis and possible solutions if you are unable to solve quickly yourself
- Keep PRs focused and small
- If it looks like the current changes will have 300+ lines of non-test code, suggest ways it could be broken into multiple PRs
Security & Configuration Tips
- Secrets: Use
.env(see.env_example); do not commit secrets.
Vue 3 Composition API Best Practices
- Use
<script setup lang="ts">for component logic - Utilize
reffor reactive state - Implement computed properties with computed()
- Use watch and watchEffect for side effects
- Avoid using a
refand awatchif acomputedwould work instead
- Avoid using a
- Implement lifecycle hooks with onMounted, onUpdated, etc.
- Utilize provide/inject for dependency injection
- Do not use dependency injection if a Store or a shared composable would be simpler
- Use Vue 3.5 TypeScript style of default prop declaration
-
Example:
const { nodes, showTotal = true } = defineProps<{ nodes: ApiNodeCost[] showTotal?: boolean }>() -
Prefer reactive props destructuring to
const props = defineProps<...> -
Do not use
withDefaultsor runtime props declaration -
Do not import Vue macros unnecessarily
-
Prefer
useModelto separately defining a prop and emit -
Be judicious with addition of new refs or other state
- If it's possible to accomplish the design goals with just a prop, don't add a
ref - If it's possible to use the
refor prop directly, don't add acomputed - If it's possible to use a
computedto name and reuse a derived value, don't use awatch
- If it's possible to accomplish the design goals with just a prop, don't add a
-
Development Guidelines
- Leverage VueUse functions for performance-enhancing styles
- Use es-toolkit for utility functions
- Use TypeScript for type safety
- If a complex type definition is inlined in multiple related places, extract and name it for reuse
- In Vue Components, implement proper props and emits definitions
- Utilize Vue 3's Teleport component when needed
- Use Suspense for async components
- Implement proper error handling
- Follow Vue 3 style guide and naming conventions
- Use Vite for fast development and building
- Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json
- Avoid new usage of PrimeVue components
- Write tests for all changes, especially bug fixes to catch future regressions
- Write code that is expressive and self-documenting to the furthest degree possible. This reduces the need for code comments which can get out of sync with the code itself. Try to avoid comments unless absolutely necessary
- Do not add or retain redundant comments, clean as you go
- Whenever a new piece of code is written, the author should ask themselves 'is there a simpler way to introduce the same functionality?'. If the answer is yes, the simpler course should be chosen
- Refactoring should be used to make complex code simpler
- Try to minimize the surface area (exported values) of each module and composable
- Don't use barrel files, e.g.
/some/package/index.tsto re-export within/src - Keep functions short and functional
- Minimize nesting, e.g.
if () { ... }orfor () { ... } - 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
Testing Guidelines
- Frameworks:
- Vitest (unit/component, happy-dom)
- Playwright (E2E)
- Test files:
- Unit/Component:
**/*.test.ts - E2E:
browser_tests/**/*.spec.ts - Litegraph Specific:
src/lib/litegraph/test/
- Unit/Component:
General
- Do not write change detector tests
e.g. a test that just asserts that the defaults are certain values - Do not write tests that are dependent on non-behavioral features like utility classes or styles
- Be parsimonious in testing, do not write redundant tests
See https://tidyfirst.substack.com/p/composable-tests - Don’t Mock What You Don’t Own
Vitest / Unit Tests
- Do not write tests that just test the mocks
Ensure that the tests fail when the code itself would behave in a way that was not expected or desired - For mocking, leverage Vitest's utilities where possible
- Keep your module mocks contained
Do not use global mutable state within the test file
Usevi.hoisted()if necessary to allow for per-test Arrange phase manipulation of deeper mock state - For Component testing, use Vue Test Utils and especially follow the advice about making components easy to test
- Aim for behavioral coverage of critical and new features
Playwright / Browser / E2E Tests
- Follow the Best Practices described in the Playwright documentation
- Do not use waitForTimeout, use Locator actions and retrying assertions
- Tags like
@mobile,@2xare respected by config and should be used for relevant tests
External Resources
- Vue: https://vuejs.org/api/
- Tailwind: https://tailwindcss.com/docs/styling-with-utility-classes
- VueUse: https://vueuse.org/functions.html
- shadcn/vue: https://www.shadcn-vue.com/
- Reka UI: https://reka-ui.com/
- PrimeVue: https://primevue.org
- ComfyUI: https://docs.comfy.org
- Electron: https://www.electronjs.org/docs/latest/
- Wiki: https://deepwiki.com/Comfy-Org/ComfyUI_frontend/1-overview
- Nx: https://nx.dev/docs/reference/nx-commands
- Practical Test Pyramid
Project Philosophy
- Follow good software engineering principles
- YAGNI
- AHA
- DRY
- SOLID
- Clean, stable public APIs
- Domain-driven design
- Thousands of users and extensions
- Prioritize clean interfaces that restrict extension access
Repository Navigation
- Check README files in key folders (tests-ui, browser_tests, composables, etc.)
- Prefer running single tests for performance
- Use --help for unfamiliar CLI tools
GitHub Integration
When referencing Comfy-Org repos:
- Check for local copy
- Use GitHub API for branches/PRs/metadata
- Curl GitHub website if needed
Common Pitfalls
- NEVER use
anytype - use proper TypeScript types - NEVER use
as anytype assertions - fix the underlying type issue - NEVER use
--no-verifyflag when committing - NEVER delete or disable tests to make them pass
- NEVER circumvent quality checks
- NEVER use the
dark:tailwind variant- Instead use a semantic value from the
style.csstheme- e.g.
bg-node-component-surface
- e.g.
- Instead use a semantic value from the
- NEVER use
:class="[]"to merge class names- Always use
import { cn } from '@/utils/tailwindUtil'- e.g.
<div :class="cn('text-node-component-header-icon', hasError && 'text-danger')" />
- e.g.
- Use
cn()inline in the template when feasible instead of creating acomputedto hold the value
- Always use