mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-07-11 01:28:03 +00:00
bdf47aebca4fa187f5bdaf2a9c90a0b3a7e2ae1f
16 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d831b1de54 |
fix: use uuid subgraph ids in nested promoted model asset
The nested promoted-missing-model test asset used readable slug ids for its subgraph definitions. createNodeLocatorId only accepts UUID subgraph ids, so getLiveWidget could not resolve the interior nodes, and the stale promoted combobox never rendered disabled. Real subgraphs always get uuid ids; the asset now matches, which is the actual fix for the interior disabled-state assertion. Revert the useProcessedWidgets disabled-derivation change: with valid asset ids the original logic is correct, so the refactor was unnecessary. |
||
|
|
caabebe145 |
Redesign missing model detection contract for promoted subgraph widgets (#13059)
## Summary Redesign missing-model detection for ADR 0009 promoted subgraph widgets so candidates are created from the widget value the user can actually edit, while still using the concrete interior widget as the schema/options source. ## Why This PR Exists This PR comes from the follow-up missing-model detection work for the ADR 0009 / 1.46 subgraph widget changes introduced by [#12197](https://github.com/Comfy-Org/ComfyUI_frontend/pull/12197). [#12197](https://github.com/Comfy-Org/ComfyUI_frontend/pull/12197) intentionally changed promoted subgraph widgets to be represented through subgraph input links. After that change, the promoted widget on the host `SubgraphNode` is the editable value owner, and linked interior widgets are no longer guaranteed to mirror that value. The old missing-model contract still treated the concrete interior node widget as the effective source of truth in subgraph cases: - recursive scans entered the subgraph and scanned the interior widget value; - candidates were keyed by the interior node/widget identity; - the parent subgraph host mostly received propagated highlight/navigation behavior; - subgraph container widgets were not treated as first-class candidate sources. That contract breaks after ADR 0009. A user can resolve a missing model by changing the promoted host widget to an installed model, while the linked interior widget can still hold the old stale value. If detection keeps scanning the linked interior value, entering the subgraph or reloading the workflow can re-create a false missing-model error that no longer corresponds to the value the user can edit. ADR 0009 also means the same subgraph definition can be reused by multiple `SubgraphNode` hosts. Once missing-model detection moves from the interior definition widget to the promoted host widget, the selected value is no longer a property of the shared definition alone. It is a property of a specific host instance. That makes the old interior-node identity insufficient for mode changes, removal handling, and re-scan behavior: a single interior leaf definition can be reachable through multiple host execution paths, and only the affected host path should add, remove, or restore a candidate. This PR also builds on [#12990](https://github.com/Comfy-Org/ComfyUI_frontend/pull/12990), which narrowed workflow-level `models[]` and embedded model data to metadata enrichment only. Together, the intended boundary is: - live widgets create missing-model candidates; - workflow/root-level `models[]` and node metadata only enrich candidates that already came from a live widget; - promoted widget values are read from the editable host widget, not inferred from stale interior `widgets_values`. ## Changes - **What**: - Introduces promoted-widget scan targets that split: - host promoted widget value and candidate identity; - concrete leaf widget/node definition data. - Scans the outermost unlinked promoted widget on a `SubgraphNode` host as the selected value owner. - Skips linked interior widgets as candidate sources, preventing stale linked widget values from producing duplicate or false missing-model candidates. - Resolves the concrete leaf widget for combo options, asset-widget support, node type, directory lookup, and embedded metadata enrichment. - Keys promoted missing-model candidates by the host execution id and host promoted widget name. - Adds `sourceExecutionId` to promoted candidates so liveness still follows the concrete source execution path, including nested inactive subgraph containers. - Uses source-scope activity for pipeline filtering and async verification, while keeping highlight/store/clearing identity host-keyed. - Removes host-keyed promoted candidates when their source execution scope is removed or bypassed. - Re-scans ancestor subgraph hosts when an interior source path is un-bypassed, so host-keyed promoted errors can reappear correctly. - Handles shared subgraph definitions by deriving promoted source paths from the concrete host instance path, rather than treating the shared definition node id as globally unique. - Shares promoted source resolution between Vue node processing and the right-side panel to avoid drift. - Aligns missing-model clearing across Vue node widgets, legacy canvas widgets, and right-side panel Parameters/Nodes section widgets. - Adds unit coverage for scan identity, source-scope liveness, dynamic mode changes, source-scope removal, shared-definition host isolation, and right-side panel clearing. - Adds nested promoted-widget E2E coverage for OSS and Cloud flows across Vue, Parameters tab, and legacy widget surfaces. - **Breaking**: None expected. - **Dependencies**: None. ## New Detection Contract A missing-model candidate is created from an unlinked final editable value owner. That value owner can be: - a normal node model widget; or - the outermost promoted model widget displayed on a `SubgraphNode` host. For promoted widgets: - the host promoted widget supplies the selected value; - the host execution id and host widget name are the candidate identity; - the concrete leaf widget supplies definition data such as combo options and asset-browser support; - the concrete source execution path is retained as `sourceExecutionId` for liveness only; - linked interior widgets are skipped as candidate sources because their values are not authoritative when driven by a promoted input. For a nested chain: `Outer promoted widget A -> inner promoted widget B -> concrete widget C` only `A` creates the candidate. `B` and `C` are linked along the promoted-input path and are skipped as selected-value sources, while `C` still provides the concrete widget definition used to evaluate `A`. ## Shared Definition And Source-Scope Liveness ADR 0009 promoted widgets make subgraphs behave more like reusable definitions with host-owned inputs. Two host `SubgraphNode`s can point at the same interior subgraph definition while carrying different promoted widget values. In that shape, the missing-model candidate must be keyed to the editable host surface, but the activity check cannot use the host id alone. For example, if two outer hosts share the same nested subgraph definition, one host can select a valid model while the other still selects a missing model. The result should be one missing-model reference, not a single definition-level error and not two errors after one host is fixed. Likewise, bypassing or un-bypassing an interior nested container should affect only the host execution paths that actually pass through that container. This PR therefore separates two concepts: - **candidate identity**: host execution id + host promoted widget name, used for storage, highlight, navigation, and clearing; - **candidate liveness**: concrete source execution path, used for scan-time activity checks, pipeline filtering, async verification, source-scope removal, and re-exposure after mode changes. That separation is the reason this PR updates more than the scan itself. Moving the detection target to the subgraph host also requires the mode-change and removal paths to understand that a host-keyed candidate can be invalidated by a descendant source path, and can need to be restored by re-scanning an ancestor host when an interior source path becomes active again. ## Review Focus Please review the identity split carefully: - candidate/store/highlight/clearing identity should remain host-keyed for promoted widgets; - liveness should use `sourceExecutionId` when present, falling back to `nodeId` for normal candidates; - scan-time activity checks should account for the source node itself and all ancestor subgraph containers; - source-scope removal should remove host-keyed candidates whose concrete source path was removed or bypassed; - un-bypassing an interior source path should re-scan affected ancestor subgraph hosts so host-keyed candidates can reappear; - shared subgraph definitions should not merge errors across different host instances; - linked interior widgets should not produce their own missing-model candidates; - asset-browser eligibility should be resolved from the concrete leaf node type and widget name, not the synthetic subgraph host type; - right-side panel edits should clear host missing-model errors and source validation errors consistently. The E2E matrix intentionally keeps nested promoted workflows only. Nested promoted widgets cover the same editable host path as single promoted widgets while also exercising the `A -> B -> C` chain that can break source-scope liveness and re-scan behavior. The nested fixture also includes multiple host instances that share the same subgraph definition, so it verifies that fixing one host does not accidentally clear or suppress another host's missing-model candidate. Direct/single promoted behavior is still covered at the unit level. ## Non-Goals - This PR does not reintroduce workflow-level `models[]` candidate creation. - This PR does not infer selected model values from `widgets_values`. - This PR does not synchronize linked interior widget values back from promoted host widgets. - This PR does not redesign missing-media scanning; missing media still skips subgraph containers and remains keyed by concrete interior paths. The shared async post-verification active-scope filter is intentionally stricter, so a pending missing-media candidate is no longer surfaced if its own node is bypassed or removed while verification is in flight. ## Validation - `pnpm exec vitest run src/components/rightSidePanel/parameters/SectionWidgets.test.ts src/platform/missingModel/missingModelScan.test.ts src/composables/graph/useErrorClearingHooks.test.ts src/platform/missingModel/missingModelPipeline.test.ts src/platform/missingModel/missingModelStore.test.ts src/utils/graphTraversalUtil.test.ts src/composables/graph/useGraphNodeManager.test.ts src/renderer/extensions/vueNodes/composables/useProcessedWidgets.test.ts --reporter=dot` - 8 files passed, 294 tests passed. - `pnpm exec vitest run src/platform/missingModel/missingModelScan.test.ts src/core/graph/subgraph/resolveConcretePromotedWidget.test.ts src/components/rightSidePanel/parameters/SectionWidgets.test.ts` - 3 files passed, 71 tests passed. - `pnpm typecheck` - `pnpm typecheck:browser` - `pnpm format:check` - targeted ESLint for changed production/unit/E2E files - `git diff --check` - `pnpm build` - `pnpm build:cloud` - OSS affected E2E on the 8188 build: - `PLAYWRIGHT_LOCAL=1 PLAYWRIGHT_TEST_URL=http://localhost:8188 pnpm exec playwright test browser_tests/tests/propertiesPanel/errorsTabModeAware.spec.ts --project=chromium --grep "Changing an OSS .*promoted|Refreshing a resolved promoted|Reloading a resolved nested"` - 5 passed. - Cloud affected E2E on the 8188 cloud build: - `PLAYWRIGHT_LOCAL=1 PLAYWRIGHT_TEST_URL=http://localhost:8188 pnpm exec playwright test browser_tests/tests/propertiesPanel/errorsTabCloudMissingModels.spec.ts --project=cloud --grep "Changing a Cloud .*promoted"` - 2 passed; the Cloud legacy promoted asset-modal case still fails until [#13075](https://github.com/Comfy-Org/ComfyUI_frontend/pull/13075) is merged. - Full OSS `errorsTabModeAware.spec.ts` on the 8188 build: - 23 passed; 3 existing paste/clipboard cases failed before the promoted subgraph section with node count remaining at 1 after `clipboard.paste()`. - Commit hooks ran `oxfmt`, `oxlint`, `eslint`, `pnpm typecheck`, and browser typecheck where applicable. - Pre-push hook ran `pnpm knip --cache`. ## Screenshots Before https://github.com/user-attachments/assets/6380c1da-1d92-4b70-888e-3ade572c4b5b After https://github.com/user-attachments/assets/4cfc24d6-3dc3-4e36-9b31-72fea6b3d9d5 |
||
|
|
6d43320b93 |
Simplify missing model error presentation (#12793)
## Summary Simplifies the Missing Models error card as the fifth slice of the catalog-driven error-tab redesign. This PR is intentionally larger than the previous slices because Missing Models is the only remaining error type where the card UI, OSS download flow, Cloud import flow, and shared model-import dialog all have to move together to preserve the resolution path. The high-level goal is to make Missing Models behave like the other simplified error cards: show the exact missing item, show the affected nodes, keep locate actions predictable, and only expose actions that can actually resolve the problem. This follows the staged error-tab cleanup plan: 1. #12683 refined validation, runtime, and prompt error presentation. 2. #12705 simplified missing media error presentation. 3. #12735 simplified missing node pack error presentation. 4. #12768 simplified swap node error presentation. 5. This PR simplifies missing model presentation and the model-import handoff. ## Why This PR Is Larger Missing Models has more resolution paths than the previous error groups: - OSS can refresh model state, download individual models, and download all available models. - Cloud cannot download directly from the panel; it resolves supported rows through the model import dialog. - Some Cloud rows cannot be resolved through import at all because the node/widget cannot consume imported model assets. - Importing from Cloud needs to know the originating missing-model row so it can lock the expected model type and apply the imported model back to the affected widgets. - Already-imported files can still be unusable if they were imported under a different model type than the missing node expects. Because of those constraints, splitting the card layout from the dialog handoff would leave either a misleading Import button or an import dialog that does not know what it is resolving. This PR keeps that behavior in one reviewable unit. ## User-Facing Behavior ### Shared Missing Models Card - Replaces the older grouped presentation with compact model rows. - Shows each missing model as the primary row label. - Shows model metadata as a smaller sublabel instead of using large section headers. - Keeps locate-node controls visually consistent with the other simplified error cards. - Keeps rows expandable when multiple nodes reference the same missing model. - Shows the affected node rows under expanded models. - Allows single-reference rows to locate the affected node without rendering an extra duplicate child row. - Keeps unknown rows visible, including their affected nodes, instead of silently hiding them. - Removes the old library-select UI from the Missing Models card. ### OSS Behavior - Keeps the refresh action available from the Missing Models group header. - Keeps individual Download actions for downloadable models. - Moves file size out of the Download button label and into the row sublabel. - Keeps Download all when multiple downloadable models are available. - Places Download all at the bottom of the card rather than competing with the group header. - Leaves rows without a download URL as non-downloadable instead of rendering a broken action. ### Cloud Behavior - Shows Import only for missing models that can be resolved by importing a model asset of the required type. - Separates models that cannot be resolved through Cloud import into an Import Not Supported section. - Gives unsupported rows a direct explanation: nodes referencing those models do not support imported models, so users need to open the node and choose a supported built-in model or replace the node with a supported loader. - Treats unknown model type/directory as unsupported for Cloud import, because the import dialog cannot lock a valid model type and the node cannot safely consume the imported asset. - Keeps affected nodes visible in the unsupported section so users still have a path to locate and replace the node manually. ## Cloud Import Dialog Changes The shared model import dialog now accepts missing-model context when opened from the Missing Models card. When that context is present: - The dialog shows which missing model will be replaced. - The dialog lists the affected node/widget references that will be updated. - The model type selector is locked to the required model directory/type. - The Back/import-another path is disabled when it would break the targeted missing-model flow. - Import progress can be associated with the originating missing-model row. - After import completion, matching missing-model references are applied automatically where possible. - If the selected file is already imported under an incompatible model type, the dialog shows a targeted failure state explaining why this import cannot resolve the missing model. This keeps the generic import dialog reusable while adding only the context-specific behavior needed for Missing Models. ## Implementation Notes - `MissingModelCard.vue` owns the card-level grouping and OSS/Cloud section decisions. - `MissingModelRow.vue` owns per-model row rendering, expansion, locate actions, import/download actions, and row-level progress states. - `useMissingModelInteractions.ts` remains the interaction layer for locating nodes and applying resolved model selections. - `UploadModelDialog.vue`, `UploadModelConfirmation.vue`, `UploadModelFooter.vue`, `UploadModelProgress.vue`, and `useUploadModelWizard.ts` receive the missing-model context needed by the Cloud import handoff. - `MissingModelLibrarySelect.vue` is removed because the simplified card no longer exposes that inline selection path. - Locale and selector changes are limited to the new simplified row/section states and removed unused Missing Models strings. ## Tests Added / Updated - Unit coverage for Missing Models card grouping and row states. - Unit coverage for importable vs unsupported Cloud rows. - Unit coverage for model row expansion, locate actions, progress display, and action availability. - Unit coverage for upload confirmation/footer/progress behavior when a missing-model context is present. - Unit coverage for incompatible already-imported model handling. - E2E coverage for OSS Missing Models presentation. - E2E coverage for mode-aware Missing Models interactions. - Cloud E2E coverage for importable rows vs Import Not Supported rows. - Cloud E2E coverage for opening the import dialog with missing-model replacement context. ## Review Focus - Cloud import eligibility: unsupported or unknown model rows should not expose Import as if the row can be resolved automatically. - Missing-model context in the import dialog: the required model type should be locked, and the affected node/widget references should be clear. - OSS parity: OSS should keep refresh, individual Download, and Download all while visually matching the simplified Cloud card where possible. - Narrow side panel behavior: row labels may wrap, but link, primary action, and locate controls should not overlap. - Scope boundaries: this PR intentionally does not redesign Missing Node Pack / Swap Node / Missing Media again; visual parity issues shared across those cards can be handled in a follow-up unification pass if needed. ## Validation - `pnpm format` - `pnpm lint` - `pnpm typecheck` - Related unit tests: 8 files / 84 tests passed - `pnpm build` - OSS Missing Models E2E: `errorsTabMissingModels.spec.ts` passed, 8/8 - Mode-aware Missing Models E2E subset passed, 11/11, excluding unrelated local paste clipboard cases - `pnpm build:cloud` - Cloud Missing Models E2E: `errorsTabCloudMissingModels.spec.ts` passed, 3/3 - Final Claude review: no Blocker or Major findings ## Breaking / Dependencies - Breaking: none. - Dependencies: none. ## Screenshots OSS <img width="575" height="393" alt="스크린샷 2026-06-12 오전 12 25 27" src="https://github.com/user-attachments/assets/f5c44f95-711a-4d3d-99bd-f39ac2bb2012" /> <img width="659" height="351" alt="스크린샷 2026-06-12 오전 12 24 37" src="https://github.com/user-attachments/assets/4bb65a47-c1aa-408b-836b-a1998412f815" /> Cloud <img width="688" height="357" alt="스크린샷 2026-06-12 오전 12 23 59" src="https://github.com/user-attachments/assets/9330a7e7-9f22-420f-82b3-dde0fb2b3dd1" /> <img width="531" height="437" alt="스크린샷 2026-06-12 오전 12 21 13" src="https://github.com/user-attachments/assets/734bd911-f6f7-4872-8868-bb927ddeedd8" /> New import model flow https://github.com/user-attachments/assets/c094c670-62b9-47ce-bfe1-2d09f4f7359d |
||
|
|
c7797b201e |
Simplify swap node error presentation (#12768)
## Summary Simplifies the Swap Nodes error card as the fourth slice of the catalog/error-tab presentation refactor, aligning it with the newer compact error-row patterns while preserving the existing replace and locate behavior. This follows the staged rollout plan from the earlier error-tab PRs: 1. #12683 refined execution-style errors: validation, runtime, and prompt errors. 2. #12705 simplified missing media errors into flat, locatable rows. 3. #12735 simplified missing node pack errors and aligned grouped-row behavior. 4. This PR applies the same simplification pass to Swap Nodes errors. 5. A later PR is expected to handle Missing Models, which is larger and intentionally kept separate. After the Missing Models slice lands, a follow-up consistency PR will normalize the shared row/disclosure pattern across Missing Node Packs, Swap Nodes, and Missing Models together. That follow-up will cover parameterized i18n labels for disclosure controls, shared text-button styling, and consistent disclosure semantics/accessibility across those grouped rows. ## Changes - **What**: Reworks the Swap Nodes card rows so each replacement group is presented as a compact row with the source node type, replacement target, replace action, and locate action. - **What**: For a single affected node, the visible row label can be clicked to locate the node, matching the interaction model used by the newer missing-media and missing-node rows. - **What**: For multiple affected nodes with the same replacement target, the group renders a count badge and a disclosure row. Expanding the group shows the affected node rows, each with its own locate action. - **What**: Removes the old node-id badge path from Swap Nodes rows. Node-id badges remain available to the other error cards that still own that behavior. - **What**: Keeps replacement behavior unchanged: per-group replacement and replace-all still call through the existing node replacement store flow. - **What**: Adds regression coverage for the new grouped-row UI, including same-type grouping in both Vue Nodes and LiteGraph render modes. - **Breaking**: None. - **Dependencies**: None. ## Review Focus Please focus on the Swap Nodes presentation and interaction symmetry with the previous error-tab PRs: - Single-node groups should remain directly locatable via the row label and the locate icon. - Multi-node groups should expose the count and expand/collapse behavior without adding duplicate focusable disclosure controls. - The visible row labels intentionally keep their own accessible names, while the separate locate icon uses the generic `Locate node on canvas` accessible name. This mirrors the established pattern from the previous slices. - The newly added Playwright fixture covers two same-type replaceable nodes so duplicate group keys and grouped disclosure behavior are exercised end-to-end. ## Validation - `pnpm format` - `pnpm test:unit src/platform/nodeReplacement/components/SwapNodeGroupRow.test.ts` - `pnpm test:browser:local browser_tests/tests/nodeReplacement.spec.ts --project=chromium` - Pre-commit hook: lint-staged, stylelint, oxfmt, oxlint, eslint, `pnpm typecheck`, `pnpm typecheck:browser` - Pre-push hook: `pnpm knip --cache` - Additional parallel code review pass completed locally; no blocker or major issues remained. ## Screenshots (if applicable) This PR <img width="561" height="362" alt="스크린샷 2026-06-11 오전 3 46 06" src="https://github.com/user-attachments/assets/65395467-6c2f-4aa1-84c5-3d9614c00c80" /> old (Main) <img width="611" height="798" alt="스크린샷 2026-06-11 오전 3 46 32" src="https://github.com/user-attachments/assets/3862d5df-f839-40c0-9488-ce64b051378e" /> |
||
|
|
1b14f4df8a |
Simplify missing node pack error presentation (#12735)
## Summary Simplify the Missing Node Packs error card so it follows the new error-tab item-row direction, with clearer pack rows, predictable locate behavior, and focused E2E coverage. This is the third PR in the staged error-tab simplification plan: 1. Merged: execution/prompt/validation error presentation and catalog grouping in #12683. 2. Merged: missing media presentation simplification in #12705. 3. This PR: missing node pack presentation simplification. 4. Planned next: swap-node presentation simplification. 5. Planned later: missing model presentation and action-flow simplification. ## Changes - **What**: Refactors Missing Node Packs rows so pack-level and node-level actions are easier to scan and more consistent with the rest of the refreshed Errors tab. - **What**: Removes the node-id badge from missing node pack rows, matching the simplified item-row direction. - **What**: Makes a single-node known pack row directly locatable from the pack label, rather than rendering an extra child row. - **What**: Keeps multi-node packs collapsed by default, with both the chevron and pack title toggling the child node list. - **What**: Keeps unknown packs expanded by default, including the single-node unknown-pack case, so users can still see the unresolved node type immediately. - **What**: Keeps per-node child rows clickable for locate-on-canvas behavior when a pack contains multiple affected nodes. - **What**: Replaces missing-node-pack action labels with shared `g.install` and `g.search` copy and removes now-unused English locale keys. - **What**: Adds targeted Playwright coverage for the simplified missing-node-pack card, including unknown-pack default rows, row-label locate behavior, and chevron/title expansion behavior. - **Breaking**: None. - **Dependencies**: None. ## Review Focus Please focus on the missing-node-pack row behavior: - Single known pack with one affected node should stay compact and locate the node from the pack label or locate icon. - Known packs with multiple affected nodes should show a count, start collapsed, and expand/collapse from either the chevron or title. - Unknown packs should expose the affected node rows immediately, including when there is only one affected node. - Locate actions should remain attached to the affected node rows, not to the parent pack when there are multiple nodes. - The E2E fixture intentionally uses two missing nodes with the same `cnr_id` and node sizes of `[400, 200]` to follow browser-test asset guidance. ## Validation - `pnpm format:check` - `pnpm lint` - `pnpm typecheck` - `pnpm knip --cache` via pre-push hook - `pnpm test:unit src/components/rightSidePanel/errors/MissingPackGroupRow.test.ts src/components/rightSidePanel/errors/MissingNodeCard.test.ts --run` - `pnpm test:browser:local browser_tests/tests/propertiesPanel/errorsTabMissingNodes.spec.ts --project=chromium` - Pre-commit hook: staged formatting, linting, `pnpm typecheck`, and `pnpm typecheck:browser` ## Screenshots This PR <img width="531" height="598" alt="스크린샷 2026-06-10 오전 1 54 31" src="https://github.com/user-attachments/assets/9c0addeb-92d2-4cef-a4f3-35a87bbad308" /> old (Main) <img width="509" height="807" alt="스크린샷 2026-06-10 오전 1 53 51" src="https://github.com/user-attachments/assets/b8488f73-d8ed-4356-bd4c-fc678ea205f7" /> |
||
|
|
dbeb9cc10d |
fix: clear missing model on promoted widget change (#12677)
## Summary Fixes FE-942 by clearing missing model indicators when promoted subgraph widgets are changed through the legacy canvas path. ## Changes - **What**: Resolves promoted widget error-clearing targets in `useErrorClearingHooks`, including legacy canvas path events from interior widgets. - **Dependencies**: None. ## Review Focus - Promoted widget validation errors clear by resolved interior widget name, while missing model/media state clears by source widget name. - Same-named promoted widgets are value-gated so changing one promoted model widget does not clear unchanged sibling indicators. - Core promoted widget event emission remains unchanged; the fix is scoped to the error-clearing hook. ## Validation - `pnpm test:unit src/composables/graph/useErrorClearingHooks.test.ts` - `pnpm test:unit src/core/graph/subgraph/promotedWidgetView.test.ts src/lib/litegraph/src/subgraph/SubgraphWidgetPromotion.test.ts` - `pnpm exec oxfmt --check src/composables/graph/useErrorClearingHooks.ts src/composables/graph/useErrorClearingHooks.test.ts src/stores/executionErrorStore.ts` - `pnpm exec oxlint src/composables/graph/useErrorClearingHooks.ts src/composables/graph/useErrorClearingHooks.test.ts src/stores/executionErrorStore.ts --type-aware` - `pnpm exec eslint src/composables/graph/useErrorClearingHooks.ts src/composables/graph/useErrorClearingHooks.test.ts src/stores/executionErrorStore.ts` - `pnpm typecheck` - `pnpm test:browser:local browser_tests/tests/propertiesPanel/errorsTabModeAware.spec.ts --project=chromium --grep Subgraph` - pre-push `knip --cache` ## Screenshots (if applicable) N/A |
||
|
|
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) |
||
|
|
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) |
||
|
|
5e3266e0c2 |
test: add e2e tests for node replacement flows (#11242)
## Summary Add Playwright e2e tests for the node replacement feature (swap nodes UI in the errors tab). ## Changes - **What**: 6 e2e test cases across two describe blocks covering single and multi-type node replacement flows. Tests verify swap nodes group visibility, in-place replacement, widget value preservation, Replace All across multiple types, output connection preservation, and success toast display. Includes typed mock data for `/api/node_replacements` and two workflow fixture files with fake missing node types mapped to real core nodes. ## Review Focus - Mock setup pattern in `setupNodeReplacement` — enables feature flag via `page.evaluate` and routes the API endpoint - Workflow fixture design — uses fake node types (E2E_OldSampler, E2E_OldUpscaler) that map to real registered types (KSampler, ImageScaleBy) - Assertion coverage for link preservation after replacement ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11242-test-add-e2e-tests-for-node-replacement-flows-3426d73d3650811e87d7f0d96fd66433) by [Unito](https://www.unito.io) --------- Co-authored-by: Connor Byrne <c.byrne@comfy.org> |
||
|
|
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> |