mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-23 06:10:32 +00:00
68fdfd5e357af2e66512eb8a535fa73d4f697130
21 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
06e09df673 |
test: replace jobs mock fixture with typed route mocks (#12267)
## Summary Replace the merged stateful jobs API browser mock fixture with a small declarative typed route-mock foundation. ## Changes - **What**: Removes `JobsApiMock`, `jobsApiMockFixture`, and the old shared `jobFixtures` helper. - **What**: Adds a generic `RouteMocker` primitive for explicit typed JSON route responses. - **What**: Adds `jobsRouteFixture`, which registers explicit `/api/jobs` list/detail responses without filtering, mutation handling, or hidden in-memory backend behavior. - **What**: Migrates the current queue overlay and missing-media runtime specs onto the new jobs route fixture. - **What**: Keeps `./browser_tests/tsconfig.json` in the ESLint TypeScript resolver config. - **Dependencies**: None. ## Review Focus This is intended to be the foundation PR for the test-strategy reset: old stateful helper out, typed declarative route mocks in. It intentionally does not add the full asset sidebar, job history sidebar, or floating QPO coverage suite; those should stack on top after this fixture shape is accepted. The boundary this PR is trying to preserve: route mocks may describe frontend-visible API responses, but should not implement Core queue/history mutation semantics. Context: https://www.notion.so/comfy-org/E2E-Test-Strategy-for-Assets-Job-History-and-Queue-Progress-Overlay-35f6d73d365081209bc5f10e6c7eb8de ## Screenshots (if applicable) Not applicable. |
||
|
|
ad63f7cb9b |
test: cover missing media runtime sources (#12126)
## Summary Adds browser coverage for the missing-media runtime paths introduced by #12069 and #12111: - OSS: annotated `[output]` media is resolved from job history. - Cloud: compact `[output]` media is resolved from output assets. - OSS and Cloud: dropped video uploads do not surface a missing-media error while the upload is still in progress. This PR is now rebased directly onto `main`; the parent fix PRs have been squash-merged, so this branch only contains the E2E coverage commit. ## Test Fixtures - Adds workflow fixtures for OSS spaced output annotations and Cloud compact output annotations. - Adds a small plain MP4 fixture for video drag/drop upload coverage. ## Validation - `pnpm exec oxfmt --check browser_tests/tests/propertiesPanel/errorsTabMissingMediaRuntime.spec.ts browser_tests/assets/missing/missing_media_cloud_output_annotation.json browser_tests/assets/missing/missing_media_output_annotations.json` - `pnpm typecheck:browser` - `pnpm exec oxlint browser_tests/tests/propertiesPanel/errorsTabMissingMediaRuntime.spec.ts --type-aware` - `git diff --check origin/main..HEAD` Note: before the rebase, the Cloud project target for this spec passed locally. Local OSS project execution against the currently running Cloud dist did not reach the test body because `ComfyPage.waitForAppReady` timed out in `beforeEach`. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-12126-test-cover-missing-media-runtime-sources-35d6d73d365081f0a981c02f33c0ff84) by [Unito](https://www.unito.io) |
||
|
|
21406dceb1 |
fix: skip nested subgraph containers in replay scan (#11908)
## Summary Fixes the Cloud-only nested subgraph missing-model false positive covered by the stacked regression test in #11907. When returning from an outer subgraph to the root graph, the Vue graph node manager replays `onNodeAdded` for existing graph nodes. The realtime error-clearing hook handled a subgraph container by recursively scanning all interior nodes. For nested subgraphs, that also scanned the nested subgraph container itself. Nested subgraph container widgets are promoted synthetic views of interior widgets. Scanning them as real model-loader nodes is wrong: the container node type is the subgraph UUID, not `UNETLoader`, so Cloud asset resolution can classify an installed promoted model as missing. ## Changes - Skip nested subgraph container nodes during parent subgraph replay scans. - Keep scanning real active interior leaf nodes. - Add unit coverage proving the replay scan visits the `UNETLoader` leaf but not the nested subgraph container. - Remove the `test.fail()` annotation from the Cloud E2E regression test added in #11907. ## Stacked PR This PR is stacked on #11907. After #11907 lands, this branch should be rebased or retargeted onto `main`. ## Verification - `pnpm exec vitest run src/composables/graph/useErrorClearingHooks.test.ts -t "skips nested subgraph containers during parent subgraph replay scan"` - `pnpm exec oxfmt --check src/composables/graph/useErrorClearingHooks.ts src/composables/graph/useErrorClearingHooks.test.ts browser_tests/tests/propertiesPanel/errorsTabCloudMissingModels.spec.ts` - `pnpm exec eslint src/composables/graph/useErrorClearingHooks.ts src/composables/graph/useErrorClearingHooks.test.ts browser_tests/tests/propertiesPanel/errorsTabCloudMissingModels.spec.ts` - `pnpm exec oxlint src/composables/graph/useErrorClearingHooks.ts src/composables/graph/useErrorClearingHooks.test.ts browser_tests/tests/propertiesPanel/errorsTabCloudMissingModels.spec.ts --type-aware` - `pnpm typecheck` - `pnpm typecheck:browser` - `pnpm build:cloud` - `PLAYWRIGHT_LOCAL=1 PLAYWRIGHT_TEST_URL=http://localhost:8188 pnpm exec playwright test browser_tests/tests/propertiesPanel/errorsTabCloudMissingModels.spec.ts --project=cloud` - commit hook: `pnpm typecheck`, `pnpm typecheck:browser` - push hook: `pnpm knip` ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11908-fix-skip-nested-subgraph-containers-in-replay-scan-3566d73d3650819c8687d6ab74add1b9) by [Unito](https://www.unito.io) |
||
|
|
14320a131f |
test: add Playwright regression test for nested subgraph Cloud missing model (#11907)
## Summary Adds a Cloud Playwright regression test for the nested subgraph case where an installed Lotus diffusion model is incorrectly surfaced as missing after returning to the root graph. The fixture keeps the reproduction small: root graph -> subgraph node -> nested subgraph node -> `UNETLoader` using `lotus-depth-d-v1-1.safetensors`. The test stubs `/api/assets` through the shared asset API fixture so that model is explicitly present as a `diffusion_models` asset. This test is intentionally written as an XFAIL regression guard. Its setup and precondition checks are outside the XFAIL section: initial workflow load must not show the error overlay, the Errors tab must initially stay hidden, subgraph entry must succeed, root return must succeed, and the replay scan must run. Only the final `Errors` tab visibility assertion is expected to fail on current Cloud behavior. ## What a green run means A green CI run for this PR means the Cloud-only bug was reproduced at the intended point. The test reaches the root-return replay scan, verifies that the replay scan ran, and then current Cloud behavior makes the Errors tab visible even though the Lotus model exists in `/api/assets`. If any earlier setup or navigation step fails, or if the root-return replay scan does not run, the test fails normally because those checks happen before `test.fail()` is applied. Locally, removing `test.fail()` produces the expected red result after the replay-scan precondition passes, with `panel-tab-errors` visible. The intended post-fix contract is that the replay scan still runs, but the Errors tab remains hidden. ## Why this is XFAIL This PR intentionally ships only the regression test, not the production fix. The final behavioral assertion is annotated with `test.fail()` because the current Cloud replay path still treats the nested subgraph promoted model widget as missing. When the follow-up fix lands, Playwright will report this test as an unexpected pass until the `test.fail()` annotation is removed. That is the handoff point for converting this regression guard into a normal passing E2E test. ## Follow-up The stacked fix PR is #11908. It updates the replay scan so nested subgraph container nodes are skipped, then removes the `test.fail()` annotation from this test. ## Verification - `pnpm exec oxfmt --check browser_tests/fixtures/assetApiFixture.ts browser_tests/tests/cloud-asset-default.spec.ts browser_tests/tests/propertiesPanel/errorsTabCloudMissingModels.spec.ts` - `pnpm exec oxlint browser_tests/fixtures/assetApiFixture.ts browser_tests/tests/cloud-asset-default.spec.ts browser_tests/tests/propertiesPanel/errorsTabCloudMissingModels.spec.ts --type-aware` - `pnpm exec eslint browser_tests/fixtures/assetApiFixture.ts browser_tests/tests/cloud-asset-default.spec.ts browser_tests/tests/propertiesPanel/errorsTabCloudMissingModels.spec.ts` - `pnpm typecheck:browser` - `pnpm typecheck` - `pnpm lint` - `PLAYWRIGHT_LOCAL=1 PLAYWRIGHT_TEST_URL=http://localhost:8188 pnpm exec playwright test browser_tests/tests/propertiesPanel/errorsTabCloudMissingModels.spec.ts browser_tests/tests/cloud-asset-default.spec.ts --project=cloud` - Temporarily removed `test.fail()` locally and verified the test fails only after the replay-scan precondition passes, with `panel-tab-errors` visible ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11907-test-add-Playwright-regression-test-for-nested-subgraph-Cloud-missing-model-3566d73d3650810b86d4de916c2852f9) by [Unito](https://www.unito.io) |
||
|
|
3c5695fd42 |
test: add Vue node error/validation ring e2e coverage (#11727)
## Summary Add additional test coverage for vue node errors ## Changes - **What**: - add tests for showing error on missing node, execution error, validation failure & resolved on fix - move ErrorsTabHelper to fixtures dir & update refs - add SLOW_MO env var for headed local tests ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11727-test-add-Vue-node-error-validation-ring-e2e-coverage-3506d73d365081069ff8f70f7970dd55) by [Unito](https://www.unito.io) |
||
|
|
967f1eb562 |
test: extract title editor test component (#11605)
## Summary Extract shared TitleEditor component and update tests to use it ## Changes - **What**: - add title editor helper - update locations that used `TestIds.node.titleInput` ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11605-test-extract-title-editor-test-component-34c6d73d3650811da6b0ec493b190c3f) by [Unito](https://www.unito.io) |
||
|
|
963a7bf178 |
refactor: consolidate browser_tests/helpers/ into fixtures/ (#11411)
*PR Created by the Glary-Bot Agent* --- ## Summary - Eliminates the confusing dual-helpers structure where `browser_tests/helpers/` and `browser_tests/fixtures/helpers/` coexisted one tier apart with overlapping purposes - Routes each file to its natural home based on what it actually *is*: page objects → `components/`, standalone utils → `utils/`, domain helper classes stay in `helpers/` - Adds an ESLint guard (`no-restricted-imports`) to prevent re-creating `browser_tests/helpers/` ## File Moves | File | From | To | Reason | |---|---|---|---| | `actionbar.ts` | `helpers/` | `fixtures/components/Actionbar.ts` | Page object class imported by ComfyPage | | `templates.ts` | `helpers/` | `fixtures/components/Templates.ts` | Page object class imported by ComfyPage | | `boundsUtils.ts` | `fixtures/helpers/` | `fixtures/utils/` | Pure function, not a helper class | | `mimeTypeUtil.ts` | `fixtures/helpers/` | `fixtures/utils/` | Pure function, not a helper class | | `builderTestUtils.ts` | `helpers/` | `fixtures/utils/` | Shared test setup functions | | `clipboardSpy.ts` | `helpers/` | `fixtures/utils/` | Page injection utility | | `fitToView.ts` | `helpers/` | `fixtures/utils/` | Canvas utility function | | `manageGroupNode.ts` | `helpers/` | `fixtures/utils/` | Litegraph interaction helper | | `painter.ts` | `helpers/` | `fixtures/utils/` | Test helper functions | | `perfReporter.ts` | `helpers/` | `fixtures/utils/` | Test infrastructure | | `promotedWidgets.ts` | `helpers/` | `fixtures/utils/` | Query helpers for specs | ## What Changed Beyond File Moves - **28 import statements** updated across test specs, fixtures, and infra files - **AGENTS.md** — directory tree diagram and architectural separation descriptions updated - **README.md** — "Leverage Existing Fixtures and Helpers" section updated - **`.claude/skills/perf-fix-with-proof/SKILL.md`** — perfReporter path reference updated - **`eslint.config.ts`** — added `@e2e/helpers/*` restricted import pattern to both spec and non-spec browser_tests rules ## Verification - `pnpm typecheck` — clean - `pnpm typecheck:browser` — clean - `pnpm lint` — 0 errors, 0 warnings - `pnpm format:check` — all files formatted - `pnpm knip` — clean - Pre-commit hooks passed full pipeline (oxfmt, oxlint, eslint, typecheck, typecheck:browser) ## Config Audit No changes needed to: `tsconfig.json` (`@e2e/*` alias covers all subdirs), `playwright.config.ts`, `vite.config.mts`, `knip.config.ts`, `.oxlintrc.json`, `nx.json` ## Manual Verification Note This is a pure structural refactoring (file moves + import updates) with zero behavioral or visual changes. The typecheck and lint passes confirm all imports resolve correctly. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11411-refactor-consolidate-browser_tests-helpers-into-fixtures-3476d73d3650816cb671ef7fa8433f66) by [Unito](https://www.unito.io) --------- Co-authored-by: glary-bot <glary-bot@comfy.org> Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> Co-authored-by: DrJKL <DrJKL0424@gmail.com> Co-authored-by: Amp <amp@ampcode.com> |
||
|
|
b4d209b5f6 |
feat: refresh missing models through pipeline (#11661)
## Summary Follow-up to the closed earlier attempt in #11646. This PR keeps the same user-facing goal, but changes the implementation to reuse the existing missing model pipeline for refresh instead of maintaining a separate candidate-only recheck path. Adds a missing model refresh action in the Errors tab by reusing the existing missing model pipeline, so users can re-check models after downloading or manually placing files without reloading the workflow. ## Changes - **What**: - Adds `app.refreshMissingModels()` as a reusable refresh entry point for the current root graph. - Splits node definition reloading into `app.reloadNodeDefs()` so missing-model refresh can pull fresh `object_info` without showing the generic combo refresh success flow. - Reuses the existing missing model pipeline instead of adding a separate candidate-only checker. The refresh path serializes the current graph, reuses active workflow model metadata when available, falls back to current missing-model metadata, and then reruns the same candidate discovery/enrichment/surfacing flow used during workflow load. - Adds missing model refresh state and error handling to `missingModelStore`. - Adds a Refresh button next to Download all in the missing model card action bar. - Moves Download all from the Errors tab header into the missing model card, so the Download all and Refresh actions render or hide together. - Changes Download all visibility from “more than one downloadable model” to “at least one downloadable model.” - Keeps the action bar hidden when there are no downloadable missing models; Cloud still does not render this action area. - Normalizes active workflow `pendingWarnings` updates so resolved missing model warnings do not get revived by stale empty warning objects. - Adds test IDs and coverage for the new action bar, refresh state, refresh delegation, pending warning sync, and E2E refresh behavior. - **Breaking**: None. - **Dependencies**: None. ## Review Focus The main design choice is intentionally reusing the missing model pipeline for refresh instead of implementing a smaller candidate-only recheck. The earlier candidate-only approach was cheaper, but it created a separate source of truth for missing-model resolution and made edge cases harder to reason about. In particular, it could diverge from the behavior used when a workflow is loaded, and it did not naturally handle the case where a model becomes missing after the workflow is already open. This version pays the cost of refreshing node definitions and rerunning the missing-model scan for the current graph, but keeps the refresh behavior aligned with workflow load semantics. Expected behavior by environment: - OSS browser: - The action bar appears when at least one missing model has a downloadable URL and directory. - Download all uses the existing browser download path. - Refresh reloads `object_info`, refreshes node definitions/combo values, reruns missing-model detection for the current graph, and clears the error if the selected model is now available. - OSS desktop: - The same action bar appears under the same downloadable-model condition. - Download all uses the existing Electron DownloadManager path. - Refresh uses the same missing-model pipeline as browser, so manually placed files or desktop-downloaded files can be rechecked without reloading the workflow. - Cloud: - The action bar remains hidden because model download/import is not supported in this section for Cloud. A few boundaries are intentional: - This PR does not add automatic filesystem watching. Browser OSS cannot reliably observe local model folder changes, so the user-triggered Refresh button remains the cross-environment mechanism. - This PR does not redesign the public `refreshComboInNodes` API beyond extracting `reloadNodeDefs()` for reuse. Further cleanup of toast behavior or a more explicit object-info reload API can be follow-up work. - This PR keeps refresh scoped to missing-model validation; missing media and missing nodes continue to use their existing flows. Linear: FE-417 ## Screenshots (if applicable) https://github.com/user-attachments/assets/2e02799f-1374-4377-b7b3-172241517772 ## Validation - `pnpm format` - `pnpm lint` (passes; existing unrelated warning remains in `src/platform/workspace/composables/useWorkspaceBilling.test.ts`) - `pnpm typecheck` - `pnpm test:unit` - `pnpm test:browser:local -- --project=chromium browser_tests/tests/propertiesPanel/errorsTabMissingModels.spec.ts` - `pnpm build` - `NX_SKIP_NX_CACHE=true DISTRIBUTION=desktop USE_PROD_CONFIG=true NODE_OPTIONS='--max-old-space-size=8192' pnpm exec nx build` - Manual desktop verification through `~/Projects/desktop` after copying the desktop build into `assets/ComfyUI/web_custom_versions/desktop_app`: - confirmed the FE bundle is built with `DISTRIBUTION = "desktop"` - confirmed missing model Download uses the desktop download path instead of browser download - confirmed Refresh can clear the missing model error after the model is available - Push hook: `pnpm knip --cache` ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11661-feat-refresh-missing-models-through-pipeline-34f6d73d3650811488defee54a7a6667) by [Unito](https://www.unito.io) |
||
|
|
693b8383d6 |
fix: missing-asset correctness follow-ups from #10856 (#11233)
Follow-up to #10856. Four correctness issues and their regression tests. ## Bugs fixed ### 1. ErrorOverlay model count reflected node selection `useErrorGroups` exposed `filteredMissingModelGroups` under the public name `missingModelGroups`. `ErrorOverlay.vue` read that alias to compute its model count label, so selecting a node shrank the overlay total. The overlay must always show the whole workflow's errors. Exposed both shapes explicitly: `missingModelGroups` / `missingMediaGroups` (unfiltered totals) and `filteredMissingModelGroups` / `filteredMissingMediaGroups` (selection-scoped). `TabErrors.vue` destructures the filtered variant with an alias. Before https://github.com/user-attachments/assets/eb848c5f-d092-4a4f-b86f-d22bb4408003 After https://github.com/user-attachments/assets/75e67819-c9f2-45ec-9241-74023eca6120 ### 2. Bypass → un-bypass dropped url/hash metadata Realtime `scanNodeModelCandidates` only reads widget values, so un-bypass produced a fresh candidate without the url that `enrichWithEmbeddedMetadata` had previously attached from `graphData.models`. `MissingModelRow`'s download/copy-url buttons disappeared after a bypass/un-bypass cycle. Added `enrichCandidateFromNodeProperties` that copies `url`/`hash`/`directory` from the node's own `properties.models` — which persists across mode toggles — into each scanned candidate. Applied to every call site of the per-node scan. A later fix in the same branch also enforces directory agreement to prevent a same-name / different-directory collision from stamping the wrong metadata. Before https://github.com/user-attachments/assets/39039d83-4d55-41a9-9d01-dec40843741b After https://github.com/user-attachments/assets/047a603b-fb52-4320-886d-dfeed457d833 ### 3. Initial full scan surfaced interior errors of a muted/bypassed subgraph container `scanAllModelCandidates`, `scanAllMediaCandidates`, and the JSON-based missing-node scan only check each node's own mode. Interior nodes whose parent container was bypassed passed the filter. Added `isAncestorPathActive(rootGraph, executionId)` to `graphTraversalUtil` and post-filter the three pipelines in `app.ts` after the live rootGraph is configured. The filter uses the execution-ID path (`"65:63"` → check node 65's mode) so it handles both live-scan-produced and JSON-enrichment-produced candidates. Before https://github.com/user-attachments/assets/3032d46b-81cd-420e-ab8e-f58392267602 After https://github.com/user-attachments/assets/02a01931-951d-4a48-986c-06424044fbf8 ### 4. Bypassed subgraph entry re-surfaced interior errors `useGraphNodeManager` replays `graph.onNodeAdded` for each existing interior node when the Vue node manager initializes on subgraph entry. That chain reached `scanSingleNodeErrors` via `installErrorClearingHooks`' `onNodeAdded` override. Each interior node's own mode was active, so the caller guards passed and the scan re-introduced the error that the initial pipeline had correctly suppressed. Added an ancestor-activity gate at the top of `scanSingleNodeErrors`, the single entry point shared by paste, un-bypass, subgraph entry, and subgraph container activation. A later commit also hardens this guard against detached nodes (null execution ID → skip) and applies the same ancestor check to `isCandidateStillActive` in the realtime verification callback. Before https://github.com/user-attachments/assets/fe44862d-f1d6-41ed-982d-614a7e83d441 After https://github.com/user-attachments/assets/497a76ce-3caa-479f-9024-4cd0f7bd20a4 ## Tests - 6 unit tests for `isAncestorPathActive` (root, active, immediate-bypass, deep-nested mute, unresolvable ancestor, null rootGraph) - 4 unit tests for `enrichCandidateFromNodeProperties` (enrichment, no-overwrite, name mismatch, directory mismatch) - 1 unit test for `scanSingleNodeErrors` ancestor guard (subgraph entry replaying onNodeAdded) - 2 unit tests for `useErrorGroups` dual export + ErrorOverlay contract - 4 E2E tests: - ErrorOverlay model count stays constant when a node is selected (new fixture `missing_models_distinct.json`) - Bypass/un-bypass cycle preserves Copy URL button (uses `missing_models_from_node_properties`) - Loading a workflow with bypassed subgraph suppresses interior missing model error (new fixture `missing_models_in_bypassed_subgraph.json`) - Entering a bypassed subgraph does not resurface interior missing model error (shares the above fixture) `pnpm typecheck`, `pnpm lint`, 206 related unit tests passing. ## Follow-up Several items raised by code review are deferred as pre-existing tech debt or scope-avoided refactors. Tracked via comments on #11215 and #11216. --- Follows up on #10856. |
||
|
|
5899a9392e |
test: Simplify vue node/menu test setup (#11184)
## Summary Simplifies test setup for common settings ## Changes - **What**: - add vue-nodes tag to auto enable nodes 2.0 - remove UseNewMenu Top as this is default ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11184-test-Simplify-vue-node-menu-test-setup-3416d73d3650815487e0c357d28761fe) by [Unito](https://www.unito.io) |
||
|
|
521019d173 |
fix: exclude muted/bypassed nodes from missing asset detection (#10856)
## Summary Muted and bypassed nodes are excluded from execution but were still triggering missing model/media/node warnings. This PR makes the error system mode-aware: muted/bypassed nodes no longer produce missing asset errors, and all error lifecycle events (mode toggle, deletion, paste, undo, tab switch) are handled consistently. - Fixes Comfy-Org/ComfyUI#13256 ## Behavioral notes - **Tab switch overlay suppression (intentional)**: Switching back to a workflow with missing assets no longer re-shows the error overlay. This reverses the behavior introduced in #10190. The error state is still restored silently in the errors tab — users can access it via the properties panel without being interrupted by the overlay on every tab switch. ## Changes ### 1. Scan filtering - `scanAllModelCandidates`, `scanAllMediaCandidates`, `scanMissingNodes`: skip nodes with `mode === NEVER || BYPASS` - `collectMissingNodes` (serialized data): skip error reporting for muted/bypassed nodes while still calling `sanitizeNodeName` for safe `configure()` - `collectEmbeddedModelsWithSource`: skip muted/bypassed nodes; workflow-level `graphData.models` only create candidates when active nodes exist - `enrichWithEmbeddedMetadata`: filter unmatched workflow-level models when all referencing nodes are inactive ### 2. Realtime mode change handling - `useErrorClearingHooks.ts` chains `graph.onTrigger` to detect `node:property:changed` (mode) - Deactivation (active → muted/bypassed): remove missing model/media/node errors for the node - Activation (muted/bypassed → active): scan the node and add confirmed errors, show overlay - Subgraph container deactivation: remove all interior node errors (execution ID prefix match) - Subgraph container activation: scan all active interior nodes recursively - Subgraph interior mode change: resolve node via `localGraph.getNodeById()` then compute execution ID from root graph ### 3. Node deletion - `graph.onNodeRemoved`: remove missing model/media/node errors for the deleted node - Handle `node.graph === null` at callback time by using `String(node.id)` for root-level nodes ### 4. Node paste/duplicate - `graph.onNodeAdded`: scan via `queueMicrotask` (deferred until after `node.configure()` restores widget values) - Guard: skip during `ChangeTracker.isLoadingGraph` (undo/redo/tab switch handled by pipeline) - Guard: skip muted/bypassed nodes ### 5. Workflow tab switch optimization - `skipAssetScans` option in `loadGraphData`: skip full pipeline on tab switch - Cache missing model/media/node state per workflow via `PendingWarnings` - `beforeLoadNewGraph`: save current store state to outgoing workflow's `pendingWarnings` - `showPendingWarnings`: restore cached errors silently (no overlay), always sync missing nodes store (even when null) - Preserve UI state (`fileSizes`, `urlInputs`) on tab switch by using `setMissingModels([])` instead of `clearMissingModels()` - `MissingModelRow.vue`: fetch file size on mount via `fetchModelMetadata` memory cache ### 6. Undo/redo overlay suppression - `silentAssetErrors` option propagated through pipeline → `surfaceMissingModels`/`surfaceMissingMedia` `{ silent }` option - `showPendingWarnings` `{ silent }` option for missing nodes overlay - `changeTracker.ts`: pass `silentAssetErrors: true` on undo/redo ### 7. Error tab node filtering - Selected node filters missing model/media card contents (not just group visibility) - `isAssetErrorInSelection`: resolve execution ID → graph node for selection matching - Missing nodes intentionally unfiltered (pack-level scope) - `hasMissingMediaSelected` added to `RightSidePanel.vue` error tab visibility - Download All button: show only when 2+ downloadable models exist ### 8. New store functions - `missingModelStore`: `addMissingModels`, `removeMissingModelsByNodeId` - `missingMediaStore`: `addMissingMedia`, `removeMissingMediaByNodeId` - `missingNodesErrorStore`: `removeMissingNodesByNodeId` - `missingModelScan`: `scanNodeModelCandidates` (extracted single-node scan) - `missingMediaScan`: `scanNodeMediaCandidates` (extracted single-node scan) ### 9. Test infrastructure improvements - `data-testid` on `RightSidePanel.vue` tabs (`panel-tab-{value}`) - Error-related TestIds moved from `dialogs` to `errorsTab` namespace in `selectors.ts` - Removed unused `TestIdValue` type - Extracted `cleanupFakeModel` to shared `ErrorsTabHelper.ts` - Renamed `openErrorsTabViaSeeErrors` → `loadWorkflowAndOpenErrorsTab` - Added `aria-label` to pencil edit button and subgraph toggle button ## Test plan ### Unit tests (41 new) - Store functions: `addMissing*`, `removeMissing*ByNodeId` - `executionErrorStore`: `surfaceMissing*` silent option - Scan functions: muted/bypassed filtering, `scanNodeModelCandidates`, `scanNodeMediaCandidates` - `workflowService`: `showPendingWarnings` silent, `beforeLoadNewGraph` caching ### E2E tests (17 new in `errorsTabModeAware.spec.ts`) **Missing nodes** - [x] Deleting a missing node removes its error from the errors tab - [x] Undo after bypass restores error without showing overlay **Missing models** - [x] Loading a workflow with all nodes bypassed shows no errors - [x] Bypassing a node hides its error, un-bypassing restores it - [x] Deleting a node with missing model removes its error - [x] Undo after bypass restores error without showing overlay - [x] Pasting a node with missing model increases referencing node count - [x] Pasting a bypassed node does not add a new error - [x] Selecting a node filters errors tab to only that node **Missing media** - [x] Loading a workflow with all nodes bypassed shows no errors - [x] Bypassing a node hides its error, un-bypassing restores it - [x] Pasting a bypassed node does not add a new error - [x] Selecting a node filters errors tab to only that node **Subgraph** - [x] Bypassing a subgraph hides interior errors, un-bypassing restores them - [x] Bypassing a node inside a subgraph hides its error, un-bypassing restores it **Workflow switching** - [x] Does not resurface error overlay when switching back to workflow with missing nodes - [x] Restores missing nodes in errors tab when switching back to workflow # Screenshots https://github.com/user-attachments/assets/e0a5bcb8-69ba-4120-ab7f-5c83e4cfc3c5 ## Follow-up work - Extract error-detection computed properties from `RightSidePanel.vue` into a composable (e.g. `useErrorsTabVisibility`) --------- Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: GitHub Action <action@github.com> |
||
|
|
8c9328c1b2 |
feat: add eslint-plugin-playwright via oxlint JS plugins (#11136)
## Summary Add eslint-plugin-playwright as an oxlint JS plugin scoped to browser_tests/, enforcing Playwright best practices at lint time. ## Changes - **What**: Configure eslint-plugin-playwright@2.10.1 via oxlint's alpha `jsPlugins` field (`.oxlintrc.json` override scoped to `browser_tests/**/*.ts`). 18 recommended rules + `prefer-native-locators` + `require-to-pass-timeout` at error severity. All 173 initial violations resolved (config, auto-fix, manual fixes). `no-force-option` set to off — 28 violations need triage (canvas overlay workarounds vs unnecessary force) in a dedicated PR. - **Dependencies**: `eslint-plugin-playwright@^2.10.1` (devDependency, required by oxlint jsPlugins at runtime) ## Review Focus - `.oxlintrc.json` override structure — this is the first use of oxlint's JS plugins alpha feature in this repo - Manual fixes in spec files: `waitForSelector` → `locator.waitFor`, deprecated page methods → locator equivalents, `toPass()` timeout additions - Compound CSS selectors replaced with `.and()` (Playwright native locator composition) to avoid `prefer-native-locators` suppressions - Lint script changes in `package.json` to include `browser_tests/` in oxlint targets --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: GitHub Action <action@github.com> |
||
|
|
0132c77c7d |
test: harden 82 Playwright specs for deterministic CI runs (#10967)
## Summary
Harden 98 E2E spec files and 8 fixtures/helpers for deterministic CI
runs by replacing race-prone patterns with retry-safe alternatives.
No source code changes -- only `browser_tests/` is touched.
## Changes
- **E2E spec hardening** (98 spec files, 6 fixtures, 2 helpers):
| Fix class | Sites | Examples |
|-----------|-------|---------:|
| `expect(await ...)` -> `expect.poll()` | ~153 | interaction,
defaultKeybindings, workflows, featureFlags |
| `const x = await loc.count(); expect(x)` -> `toHaveCount()` | ~19 |
menu, linkInteraction, assets, bottomPanelShortcuts |
| `nextFrame()` -> `waitForHidden()` after menu clicks | ~22 |
contextMenu, rightClickMenu, subgraphHelper |
| Redundant `nextFrame()` removed | many | defaultKeybindings, minimap,
builderSaveFlow |
| `expect(async () => { ... }).toPass()` retry blocks | 5 | interaction
(graphdialog dismiss guard) |
| `force:true` removed from `BaseDialog.close()` | 1 | BaseDialog
fixture |
| ContextMenu `waitForHidden` simplified (check-then-act race removed) |
1 | ContextMenu fixture |
| Non-deterministic node order -> proximity-based selection | 1 |
interaction (toggle dom widget) |
| Tight poll timeout (250ms) -> >=2000ms | 2 | templates |
- **Helper improvements**: Exposed locator getters on
`ComfyPage.domWidgets`, `ToastHelper.toastErrors`, and
`WorkflowsSidebarTab.activeWorkflowLabel` so callers can use retrying
assertions (`toHaveCount()`, `toHaveText()`) directly.
- **Flake pattern catalog**: Added section 7 table to
`browser_tests/FLAKE_PREVENTION_RULES.md` documenting 8 pattern classes
for reviewers and future authors.
- **Docs**: Fixed bad examples in `browser_tests/README.md` to use
`expect.poll()`.
- **Breaking**: None
- **Dependencies**: None
## Review Focus
- All fixes follow the rules in
`browser_tests/FLAKE_PREVENTION_RULES.md`
- No behavioral changes to tests -- only timing/retry strategy is
updated
- The `ContextMenu.waitForHidden` simplification removes a
swallowed-error anti-pattern; both locators now use direct `waitFor({
state: 'hidden' })`
---------
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: github-actions <github-actions@github.com>
|
||
|
|
3b78dfbe1c |
test: migrate browser_tests/ to @e2e/ path alias and add lint rule (#10958)
## Summary Complete the @e2e/ path alias migration started in #10735 by converting all 354 remaining relative imports and adding a lint rule to prevent backsliding. ## Changes - **What**: Migrate all relative imports in browser_tests/ to use `@e2e/` (intra-directory) and `@/` (src/ imports) path aliases. Add `no-restricted-imports` ESLint rule banning `./` and `../` imports in `browser_tests/**/*.ts`. Suppress pre-existing oxlint `no-eval` and `no-console` warnings exposed by touching those files. ## Review Focus - ESLint flat-config merging: the `@playwright/test` ban and relative-import ban are in two separate blocks to avoid last-match-wins collision with the `useI18n`/`useVirtualList` blocks higher in the config. - The `['./**', '../**']` glob patterns (not `['./*', '../*']`) are needed to catch multi-level relative paths like `../../../src/foo`. Follows up on #10735 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-10958-test-migrate-browser_tests-to-e2e-path-alias-and-add-lint-rule-33c6d73d365081649d1be771eac986fd) by [Unito](https://www.unito.io) Co-authored-by: Amp <amp@ampcode.com> |
||
|
|
3f375bea9c |
test: comprehensive E2E tests for error dialog, overlay, and errors tab (#10848)
## Summary Comprehensive Playwright E2E tests for the error systems: ErrorDialog, ErrorOverlay, and the errors tab (missing nodes, models, media, execution errors). ## Changes - **What**: - **ErrorDialog** (`errorDialog.spec.ts`, 7 tests): configure/prompt error triggers, Show Report, Copy to Clipboard, Find Issues on GitHub, Contact Support - **ErrorOverlay** (`errorOverlay.spec.ts`, 12 tests): error count labels, per-type button labels (missing nodes/models/media/multiple), See Errors flow (open panel, dismiss, close), undo/redo persistence - **Errors tab — common** (`errorsTab.spec.ts`, 3 tests): tab visibility, search/filter execution errors - **Errors tab — Missing nodes** (`errorsTabMissingNodes.spec.ts`, 5 tests): MissingNodeCard, packs group, expand/collapse, locate button - **Errors tab — Missing models** (`errorsTabMissingModels.spec.ts`, 6 tests): group display, model name, expand/referencing nodes, clipboard copy, OSS Copy URL/Download buttons - **Errors tab — Missing media** (`errorsTabMissingMedia.spec.ts`, 7 tests): migrated from `missingMedia.spec.ts` with detection, upload/library/cancel flows, locate - **Errors tab — Execution** (`errorsTabExecution.spec.ts`, 2 tests): Find on GitHub/Copy buttons, runtime error panel - **Shared helpers**: `ErrorsTabHelper.ts` (openErrorsTabViaSeeErrors), `clipboardSpy.ts` (interceptClipboardWrite/getClipboardText) - **Component changes**: added `data-testid` to `ErrorDialogContent.vue`, `FindIssueButton.vue`, `MissingModelRow.vue`, `MissingModelCard.vue` - **Selectors**: registered all new test IDs in `selectors.ts` - **Test assets**: `missing_nodes_and_media.json` (compound errors), `missing_models_with_nodes.json` (expand/locate) - **Migrations**: error tests from `dialog.spec.ts` → dedicated files, `errorOverlaySeeErrors.spec.ts` → `errorOverlay.spec.ts`, `missingMedia.spec.ts` → `errorsTabMissingMedia.spec.ts` ## Review Focus - OSS tests (`@oss` tag) verify Download/Copy URL buttons appear for models with embedded URLs. - The `missing_models.json` fixture must remain without nodes — adding `CheckpointLoaderSimple` nodes causes directory mismatch in `enrichWithEmbeddedMetadata` that prevents URL enrichment. A separate `missing_models_with_nodes.json` fixture is used for expand/locate tests. ## Cloud tests deferred Missing model cloud environment tests (`@cloud` tag — hidden buttons, import-unsupported notice) are deferred to a follow-up PR. The `comfyPage` fixture cannot bypass the Firebase auth guard in cloud builds, causing `window.app` initialization timeout. A separate infra PR is needed to add cloud auth bypass to the fixture. ## Bug Discovery During testing, a bug was found where the **Locate button for missing nodes in subgraphs fails on initial workflow load**. `collectMissingNodes` in `loadGraphData` captures execution IDs using pre-`configure()` JSON node IDs, but `configure()` triggers subgraph node ID deduplication (PR #8762, always-on since PR #9510) which remaps colliding IDs. This will be addressed in a follow-up PR. - Fixes #10847 (tracked, fix pending in separate PR) ## Testing - 42 new/migrated E2E tests across 8 spec files - All OSS tests pass locally and in CI ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-10848-test-comprehensive-E2E-tests-for-error-dialog-overlay-and-errors-tab-3386d73d36508137a5e4cec8b12fa2fa) by [Unito](https://www.unito.io) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
dee236cd60 |
test: comprehensive properties panel E2E tests (PNL-01) (#10548)
## Summary Comprehensive Playwright E2E tests for the properties panel (right sidebar). Part of the **Test Coverage Q2 Overhaul** initiative (Phase 2: PNL-01). ## What's included - **PropertiesPanelHelper** page object in `browser_tests/helpers/` — locators + action methods for all panel elements - **35 test cases** covering: - Open/close via actionbar toggle - Workflow Overview (no selection): tabs, title, nodes list, global settings - Single node selection: title, parameters, info tab, widgets display - Multi-node selection: item count, node listing, hidden Info tab - Title editing: pencil icon, edit mode, rename, visibility rules - Search filtering: query, clear, empty state - Settings tab: Normal/Bypass/Mute state, color swatches, pinned toggle - Selection transitions: no-selection ↔ single ↔ multi - Nodes tab: list all, search filter - Tab label changes based on selection count - **Errors tab scaffold** (for @jaeone94 ADD-03) ## Testing - All tests use Vue nodes with new menu enabled - Zero flaky tests (proper waits, no sleeps) - Screenshots scoped to panel elements ## Unblocks - **ADD-03** (error systems by @jaeone94) — errors tab scaffold ready to extend ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-10548-test-comprehensive-properties-panel-E2E-tests-PNL-01-32f6d73d36508199a216fd8d953d8e18) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com> |
||
|
|
6ee3803770 |
feat: implement NodeLibrarySidebarTabV2 with Reka UI components (#8548)
## Summary Implement a redesigned Node Library sidebar using Reka UI components with virtualized tree rendering and improved UX. ## Changes - **What**: - Add three-tab structure (Essential, All, Custom) using Reka UI Tabs - Implement TreeExplorerV2 with virtualized tree using TreeRoot/TreeVirtualizer for performance - Add node hover preview with teleport to show NodePreview component - Implement context menu for toggling favorites on nodes - Add search functionality that auto-expands matching folders - Create panel components: EssentialNodesPanel, AllNodesPanel, CustomNodesPanel - Add 'Open Manager' button in CustomNodesPanel - Use custom icons: comfy--node for nodes, ph--folder-fill for folders - New node preview component: `NodePreviewCard` - Api node folder icon - Node drag preview - **Feature Flag**: Enabled via URL parameter `?nodeRedesign=true` ## Review Focus - TreeExplorerV2.vue uses `[...expandedKeys]` to prevent internal mutation by Reka UI TreeRoot - Context menu injection key is exported from TreeExplorerV2Node.vue and imported by TreeExplorerV2.vue - Hover preview uses teleport to `#node-library-node-preview-container-v2` ## Screenshots (if applicable) | Feature | Screenshot | |---|---| | All nodes tab |<img width="323" height="761" alt="image" src="https://github.com/user-attachments/assets/1976222b-83dc-4a1b-838a-2d49aedea3b8" />| | Custom nodes tab | <img width="308" height="748" alt="image" src="https://github.com/user-attachments/assets/2c23bffb-bdaa-4c6c-8cac-7610fb7f3fb7" />| |Api nodes icon | <img width="299" height="523" alt="image" src="https://github.com/user-attachments/assets/e9ca05b0-1143-44cf-b227-6462173c7cd0" />| | node preview|<img width="499" height="544" alt="image" src="https://github.com/user-attachments/assets/8961a7b4-77ae-4e57-99cf-62d9e4e17088" />| | node drag preview | <img width="434" height="289" alt="image" src="https://github.com/user-attachments/assets/b5838c90-65d4-4bee-b2b3-c41b57870da8" />| Test by adding `?nodeRedesign=true` to the URL ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8548-WIP-feat-implement-NodeLibrarySidebarTabV2-with-Reka-UI-components-2fb6d73d36508134b7e0f75a2c9b976a) by [Unito](https://www.unito.io) --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: GitHub Action <action@github.com> Co-authored-by: bymyself <cbyrne@comfy.org> |
||
|
|
f2d5bfab73 |
test(browser): refactor browser tests for reliability and maintainability (#8510)
## Summary Major refactoring of browser tests to improve reliability, maintainability, and type safety. ## Changes ### Test Infrastructure Decomposition - Decomposed `ComfyPage.ts` (~1000 lines) into focused helpers: - `CanvasHelper`, `DebugHelper`, `SubgraphHelper`, `NodeOperationsHelper` - `SettingsHelper`, `WorkflowHelper`, `ClipboardHelper`, `KeyboardHelper` - Created `ContextMenu` page object, `BaseDialog` base class, and `BottomPanel` page object - Extracted `DefaultGraphPositions` constants ### Locator Stability - Added `data-testid` attributes to Vue components (sidebar, dialogs, node library) - Created centralized `selectors.ts` with test ID constants - Replaced fragile CSS selectors (`.nth()`, `:nth-child()`) with `getByTestId`/`getByRole` ### Performance & Reliability - Removed `setTimeout` anti-patterns (replaced with `waitForFunction`) - Replaced `waitForTimeout` with retrying assertions - Replaced hardcoded coordinates with computed `NodeReference` positions - Enforced LF line endings for all text files ### Type Safety - Enabled `no-explicit-any` lint rule for browser_tests via oxlint - Purged `as any` casts from browser_tests - Added Window type augmentation for standardized window access - Added proper type annotations throughout ### Bug Fixes - Restored `ExtensionManager` API contract - Removed test-only settings from production schema - Fixed flaky selectors and missing test setup ## Testing - All browser tests pass - Typecheck passes <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Overhauled browser E2E test infrastructure with many new helpers/fixtures, updated test APIs, and CI test container image bumped for consistency. * **Chores** * Standardized line endings and applied stricter lint rules for browser tests; workspace dependency version updated. * **Documentation** * Updated Playwright and TypeScript testing guidance and test-run commands. * **UI** * Added stable data-testids to multiple components to improve testability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: GitHub Action <action@github.com> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> |
||
|
|
b1b2fd8a4f |
feat: right side panel favorites, no selection state, and more... (#7812)
Most of the features in this pull request are completed and can be
reviewed and merged.
## TODO
- [x] no selection panel
- [x] group selected panel
- [x] tabs
- [x] favorites tab
- [x] global settings tab
- [x] nodes tab
- [x] widget actions menu
- [x] [Bug]: style bugs
- [x] button zoom to the node on canvas.
- [x] rename widgets on widget actions
- [ ] [Bug]: the canvas has not been updated after renaming.
- [x] global settings
- [ ] setting item: "show advanced parameters"
- blocked by other things. skip for now.
- [x] setting item: show toolbox on selection
- [x] setting item: nodes 2.0
- [ ] setting item: "background color"
- blocked by other things. skip for now.
- [x] setting item: grid spacing
- [x] setting item: snap nodes to grid
- [x] setting item: link shape
- [x] setting item: show connected links
- [x] form style reuses the form style of node widgets
- [x] group node cases
- [x] group node settings
- [x] show all nodes in group
- [x] show frame name on nodes when multiple selections are made
- [x] group multiple selections
- [x] [Bug]: nodes without widgets cannot display the location and their
group
- [x] [Bug]: labels layout
- [x] favorites
- [x] the indicator on widgets
- [x] favorite and unfavorite buttons on widgets
- [x] [Bug]: show node name in favorite widgets + improve labels layout
- [ ] [Bug]: After canceling the like, the like list will not be updated
immediately.
- [x] [Bug]: The favorite function does not work for the project on
Subgraph.
- [x] subgraph
- [x] add the node name from where this parameter comes from when node
is subgraph
- [x] show and hide directly on Inputs
- [x] some bugs need to be fixed.
- [x] advanced widgets
- [x] button: show advanced inputs
- Clicking button expands the "Advanced Inputs" section on the right
side panel, regardless of whether the panel is open or not
- [x] [Bug]: style bugs
- [x] advanced inputs section when node is subgraph
- [x] inputs tab rearranging
- [x] favorited inputs rearranging
- [x] subgraph inputs rearranging
- [ ] review and reconstruction to improve complexity and architecture
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7812-feat-right-side-panel-favorites-no-selection-state-and-more-2da6d73d36508134b503d676f9b3d248)
by [Unito](https://www.unito.io)
---------
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: bymyself <cbyrne@comfy.org>
|
||
|
|
a87bd0eb37 |
feat: position properties panel opposite to sidebar (#7647)
## Problem When sidebar is positioned on the right, the properties panel also appears on the right, causing both panels to compete for space and creating a poor layout. ## Solution Properties panel now dynamically positions itself opposite to the sidebar: - Sidebar left → Properties panel right (default) - Sidebar right → Properties panel left ## Changes - Modified `LiteGraphCanvasSplitterOverlay.vue` to conditionally render properties panel based on sidebar location - Updated splitter refresh key to recalculate layout when sidebar position changes - Added dynamic close button icon in `RightSidePanel.vue` that points in the correct direction ## Testing - Created E2E tests to verify positioning behavior - Manually verified visual behavior in browser ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7647-feat-position-properties-panel-opposite-to-sidebar-2ce6d73d365081049683e74c8d03dbdd) by [Unito](https://www.unito.io) |
||
|
|
f74c176423 |
Cleanup: Properties Panel (#7137)
## Summary - Code cleanup - Copy, padding, color, alignment of components - Subgraph Edit mode changes - Partial fix for the Node Info location (need to do context menu still) - Editing node title ### Still to-do - Bi-directionality in values ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7137-WIP-Cleanup-Properties-Panel-2be6d73d3650813e9430f6bcb09dfb4d) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com> |