mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-19 03:49:33 +00:00
e2b44f34ea2f04e212a085cc032ff6ced0cbee9e
7 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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. |
||
|
|
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> |
||
|
|
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> |
||
|
|
d9466947b2 |
feat: detect and resolve missing media inputs in error tab (#10309)
## Summary Add detection and resolution UI for missing image/video/audio inputs (LoadImage, LoadVideo, LoadAudio nodes) in the Errors tab, mirroring the existing missing model pipeline. ## Changes - **What**: New `src/platform/missingMedia/` module — scan pipeline detects missing media files on workflow load (sync for OSS, async for cloud), surfaces them in the error tab with upload dropzone, thumbnail library select, and 2-step confirm flow - **Detection**: `scanAllMediaCandidates()` checks combo widget values against options; cloud path defers to `verifyCloudMediaCandidates()` via `assetsStore.updateInputs()` - **UI**: `MissingMediaCard` groups by media type; `MissingMediaRow` shows node name (single) or filename+count (multiple), upload dropzone with drag & drop, `MissingMediaLibrarySelect` with image/video thumbnails - **Resolution**: Upload via `/upload/image` API or select from library → status card → checkmark confirm → widget value applied, item removed from error list - **Integration**: `executionErrorStore` aggregates into `hasAnyError`/`totalErrorCount`; `useNodeErrorFlagSync` flags nodes on canvas; `useErrorGroups` renders in error tab - **Shared**: Extract `ACCEPTED_IMAGE_TYPES`/`ACCEPTED_VIDEO_TYPES` to `src/utils/mediaUploadUtil.ts`; extract `resolveComboValues` to `src/utils/litegraphUtil.ts` (shared across missingMedia + missingModel scan) - **Reverse clearing**: Widget value changes on nodes auto-remove corresponding missing media errors (via `clearWidgetRelatedErrors`) ## Testing ### Unit tests (22 tests) - `missingMediaScan.test.ts` (12): groupCandidatesByName, groupCandidatesByMediaType (ordering, multi-name), verifyCloudMediaCandidates (missing/present, abort before/after updateInputs, already resolved true/false, no-pending skip, updateInputs spy) - `missingMediaStore.test.ts` (10): setMissingMedia, clearMissingMedia (full lifecycle with interaction state), missingMediaNodeIds, hasMissingMediaOnNode, removeMissingMediaByWidget (match/no-match/last-entry), createVerificationAbortController ### E2E tests (10 scenarios in `missingMedia.spec.ts`) - Detection: error overlay shown, Missing Inputs group in errors tab, correct row count, dropzone + library select visibility, no false positive for valid media - Upload flow: file picker → uploading status card → confirm → row removed - Library select: dropdown → selected status card → confirm → row removed - Cancel: pending selection → returns to upload/library UI - All resolved: Missing Inputs group disappears - Locate node: canvas pans to missing media node ## Review Focus - Cloud verification path: `verifyCloudMediaCandidates` compares widget value against `asset_hash` — implicit contract - 2-step confirm mirrors missing model pattern (`pendingSelection` → confirm/cancel) - Event propagation guard on dropzone (`@drop.prevent.stop`) to prevent canvas LoadImage node creation - `clearAllErrors()` intentionally does NOT clear missing media (same as missing models — preserves pending repairs) - `runMissingMediaPipeline` is now `async` and `await`-ed, matching model pipeline ## Test plan - [x] OSS: load workflow with LoadImage referencing non-existent file → error tab shows it - [x] Upload file via dropzone → status card shows "Uploaded" → confirm → widget updated, error removed - [x] Select from library with thumbnail preview → confirm → widget updated, error removed - [x] Cancel pending selection → returns to upload/library UI - [x] Load workflow with valid images → no false positives - [x] Click locate-node → canvas navigates to the node - [x] Multiple nodes referencing different missing files → correct row count - [x] Widget value change on node → missing media error auto-removed ## Screenshots https://github.com/user-attachments/assets/631c0cb0-9706-4db2-8615-f24a4c3fe27d |
||
|
|
efe78b799f |
[feat] Node replacement UI (#8604)
## Summary Add node replacement UI to the missing nodes dialog. Users can select and replace deprecated/missing nodes with compatible alternatives directly from the dialog. ## Changes - Classify missing nodes into **Replaceable** (quick fix) and **Install Required** sections - Add select-all checkbox + per-node checkboxes for batch replacement - `useNodeReplacement` composable handles in-place node replacement on the graph: - Simple replacement (configure+copy) for nodes without mapping - Input/output connection remapping for nodes with mapping - Widget value transfer via `old_widget_ids` - Dot-notation input handling for Autogrow/DynamicCombo - Undo/redo support via `changeTracker` (try/finally) - Title and properties preservation - Footer UX: "Skip for Now" button when all nodes are replaceable (cloud + OSS) - Auto-close dialog when all replaceable nodes are replaced and no non-replaceable remain - Settings navigation link from "Don't show again" checkbox - 505-line unit test suite for `useNodeReplacement` ## Review Focus - `useNodeReplacement.ts` — core graph manipulation logic - `MissingNodesContent.vue` — checkbox selection state management - `MissingNodesFooter.vue` — conditional button rendering (cloud vs OSS vs all-replaceable) [screen-capture.webm](https://github.com/user-attachments/assets/7dae891c-926c-4f26-987f-9637c4a2ca16) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8604-feat-Node-replacement-UI-2fd6d73d36508148a371dabb8f4115af) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com> |
||
|
|
aa5125cef6 |
Chore: Oxfmt formatting pass (#8341)
## Summary Expanding the covered files to format. One-time formatting pass. To be added to the `.git-blame-ignore-revs` ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8341-Chore-Oxfmt-formatting-pass-2f56d73d365081f2988fcb7570f9a2a1) by [Unito](https://www.unito.io) |
||
|
|
efd9b04a6e |
[refactor] Organize all browser test assets into logical folders (#5058)
* move subgraph test assets into subfolder * [refactor] Organize browser test assets into logical folders Reorganized test assets for better maintainability: - groupnodes/: GroupNode feature tests - groups/: Visual grouping tests - missing/: Missing nodes/models tests - links/: Link-related tests - inputs/: Input widget tests - widgets/: Widget-specific tests - nodes/: Node-related tests - workflowInMedia/: Workflow media files Updated all loadWorkflow references to use new folder structure. Fixed programmatic filename references to prevent test failures. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * [fix] Update mobile test to use new asset path * [fix] Update remaining loadWorkflow calls to use new folder structure * [fix] Fix remaining programmatic filename references * [fix] Run prettier formatting * [fix] Fix setupWorkflowsDirectory references to use correct folder paths * [refactor] Rename subgraph folder to subgraphs for consistency * [fix] Fix breadcrumb name in subgraph DOM widget test * Update test expectations [skip ci] --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: github-actions <github-actions@github.com> |