mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-24 14:45:36 +00:00
cea5f0b721a1b73993259ee67390f87379052d0d
11 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
73d4e24ffa |
revert: roll back #10849 + #11697 (per-instance promoted widget values) (#11790)
## Summary Reverts #10849 (per-instance promoted widget value storage) and its companion test-pinning PR #11697. The fix in #10849 caused regressions in promoted-widget serialization (notably the Z-Image-Turbo template, see #10146 follow-up). A replacement fix is being developed on `fix/subgraph-promoted-widget-inline-state` and will land separately. ## Changes - **Revert #11697** — drops the `it.fails`-marked tests that pin the #10849 corruption symptom. With #10849 reverted, those markers would falsely flip to passing. - **Revert #10849** — removes per-instance `_instanceWidgetValues` map, `_pendingWidgetsValues` configure-time hydration, the `widgets_values` write path in `SubgraphNode.serialize()`, the `sourceSerialize` field on `PromotedWidgetView`, the multi-instance Vitest suite, and the multi-instance E2E test + asset. - **Conflict resolution** in `browser_tests/tests/subgraph/subgraphSerialization.spec.ts`: kept the restored test coverage from #11579 (which is post-#10849 on main) and removed only the now-unreachable multi-instance test, its helper, and its workflow constant. Auto-merge with #11698 (`incrementVersion`) and #11699 (ID type aliases) was clean. ## Review Focus - Confirm no other on-main code path has come to depend on `PromotedWidgetView.sourceSerialize` or `SubgraphNode._instanceWidgetValues` since #10849 (grep is clean locally). - Confirm we want to land this revert before the replacement fix on `fix/subgraph-promoted-widget-inline-state` is ready — this leaves the original #10146 (multi-instance widget value collision) unfixed in the meantime. - The retained #11579 test coverage now exercises pre-#10849 behavior; some of those assertions were written expecting the #10849 code path. CI will surface any that need adjustment. ┆Issue is synchronized with this [Notion page](https://app.notion.com/p/PR-11790-revert-roll-back-10849-11697-per-instance-promoted-widget-values-3536d73d3650814094abd58b6b712d8d) 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> |
||
|
|
8dcadd6fe1 |
test: restore deleted subgraph serialization E2E tests (#11579)
*PR Created by the Glary-Bot Agent* --- ## Summary #10759 removed ~12 E2E tests from `subgraphSerialization.spec.ts` during a reorganization that shifted semantic coverage to Vitest. Several of the removed tests covered the exact `serialize() → JSON → configure()` round-trip that #10849's positional `_instanceWidgetValues` path later regressed on Main — promoted widget values binding to the wrong slots when loading templates whose `widgets_values` ordering doesn't match current `proxyWidgets`. This restores the pre-reorg E2E coverage so future regressions in promoted-widget serialization are caught at the browser level. ## Restored tests From `subgraphSerialization.spec.ts` (pre-#10759): - **Deterministic proxyWidgets Hydrate** (3 tests) — round-trip stability and compressed `target_slot` resolution. - **Legacy And Round-Trip Coverage** (5 tests) — includes the most directly-relevant restorations: - `Promoted widgets survive serialize -> loadGraphData round-trip` - `Multi-link input representative stays stable through save/reload` - `Cloning a subgraph node keeps promoted widget entries on original and clone` - **Duplicate ID Remapping** (5 tests) — includes `Promoted widget tuples are stable after full page reload boot path`. The 4 tests that already existed on Main (added by #10849 and the Vue-nodes legacy-prefixed block) are kept as-is. ## Adaptations to current APIs - Imports reworked for the post-`@e2e/*` alias layout. - Redundant `comfyPage.nextFrame()` calls dropped — `loadWorkflow` / `loadGraphData` / `serializeAndReload` already wait internally (#11264). - Alt-drag clone block wrapped in `try/finally` around `keyboard.up('Alt')` to match the current `subgraphCrud.spec.ts` pattern. - `PromotedWidgetEntry` is now exported from `browser_tests/helpers/promotedWidgets.ts` so the restored `expectPromotedWidgetsToResolveToInteriorNodes` helper can type its argument. ## Review follow-ups applied - Use `expect.poll()` instead of `expect(async () => …).toPass()` for the single-value snapshot comparison, per `browser_tests/AGENTS.md`. - Capture and call `dispose()` from `SubgraphHelper.collectConsoleWarnings()` inside a `try/finally` so the console listener is unregistered after the test. ## Verification - `pnpm typecheck:browser` — clean. - `pnpm exec eslint` + `pnpm exec oxlint` on changed files — 0 warnings, 0 errors. - `pnpm exec oxfmt` on changed files — applied (no diff). - Ran 2 key restored tests against local ComfyUI + dev server: - `Promoted widgets survive serialize -> loadGraphData round-trip` — PASS (3.9s) - `Multi-link input representative stays stable through save/reload` — PASS (2.9s) - Full-suite runs in this sandbox are blocked by the existing `comfyPage` fixture's `createUser` path failing on repeat runs against persistent backend state — unrelated to this PR. CI will exercise the full suite. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11579-test-restore-deleted-subgraph-serialization-E2E-tests-34b6d73d365081f29b27c1069476ad17) by [Unito](https://www.unito.io) --------- Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> |
||
|
|
ecb6fbe8fb |
test: Add waitForWorkflowIdle & remove redundant nextFrame (#11264)
## Summary More cleanup and reliability ## Changes - **What**: - Add wait for idle - Remove redundant nextFrames ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11264-test-Add-waitForWorkflowIdle-remove-redundant-nextFrame-3436d73d3650812c837ac7503ce0947b) by [Unito](https://www.unito.io) Co-authored-by: Alexander Brown <drjkl@comfy.org> |
||
|
|
52ccd9ed1a |
refactor: internalize nextFrame() into fixture/helper methods (#11166)
## Summary
Internalize `nextFrame()` calls into fixture/helper methods so spec
authors don't need to remember to call it after common operations.
`nextFrame()` waits for one `requestAnimationFrame` (~16ms) — an extra
call is always safe, making this a low-risk refactor.
## Changes
### Phase 1: `SettingsHelper.setSetting()`
`setSetting()` now calls `nextFrame()` internally. Removed 15 redundant
calls across 7 files.
### Phase 2: `CommandHelper.executeCommand()`
`executeCommand()` now calls `nextFrame()` internally. Removed 15
redundant calls across 7 files, including the now-redundant call in
`AppModeHelper.toggleAppMode()`.
### Phase 3: `WorkflowHelper.loadGraphData()`
New helper wraps `page.evaluate(loadGraphData)` + `nextFrame()`.
Migrated `SubgraphHelper.serializeAndReload()` and `groupNode.spec.ts`.
### Phase 4: `NodeReference` cleanup
Removed redundant `nextFrame()` from `copy()`, `convertToGroupNode()`,
`resizeNode()`, `dragTextEncodeNode2()`, and
`convertDefaultKSamplerToSubgraph()`. Removed 6 spec-level calls after
`node.click('title')`.
### Phase 5: `KeyboardHelper.press()` and `delete()`
New convenience methods that press a key and wait one frame. Converted
40 `canvas.press(key)` + `nextFrame()` pairs across 13 spec files.
### Phase 6: `ComfyPage.expectScreenshot()`
New helper combines `nextFrame()` + `toHaveScreenshot()`. Converted 45
pairs across 12 spec files.
## Total impact
- **~130 redundant `nextFrame()` calls eliminated** across ~35
spec/helper files
- **3 new helper methods** added (`loadGraphData`, `press`/`delete`,
`expectScreenshot`)
- **2 existing methods** enhanced (`setSetting`, `executeCommand`)
## What was NOT changed
- `performance.spec.ts` frame-counting loops (intentional)
- `ComfyMouse.ts` / `CanvasHelper.ts` (already internalized)
- `SubgraphHelper.packAllInteriorNodes()` (deliberate orchestration)
- Builder helpers (already internalized)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11166-refactor-internalize-nextFrame-into-fixture-helper-methods-33f6d73d3650817bb5f6fb46e396085e)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Amp <amp@ampcode.com>
|
||
|
|
6847c7ba2d |
fix: store promoted widget values per SubgraphNode instance (#10849)
## Summary - Multiple SubgraphNode instances of the same blueprint share inner nodes, causing promoted widget values to collide — the last configured instance overwrites all previous values - Add per-instance value storage (`_instanceWidgetValues`) on SubgraphNode so each instance preserves its own promoted widget values independently - Restore `widgets_values` from serialized data into this per-instance map after promoted views are created during configure - Fixes #10146 ## Root Cause When loading a workflow with multiple SubgraphNode instances of the same blueprint: 1. `LGraph.configure()` creates ONE shared Subgraph per blueprint (line 2625) 2. Each SubgraphNode instance calls `configure(instanceData)` sequentially 3. `PromotedWidgetView.value` setter writes to the **shared inner node's widget** (`promotedWidgetView.ts:199`) 4. The last instance's `configure()` overwrites all previous instances' values **Regression**: Introduced by PR #8594 (WidgetValueStore, v1.41.3) which centralized widget state without per-instance scoping for shared blueprints. ## Fix - **SubgraphNode**: Add `_instanceWidgetValues` Map and `_pendingWidgetsValues` for configure-time restoration - **PromotedWidgetView getter**: Check instance map first before falling back to widget store / inner node - **PromotedWidgetView setter**: Write to instance map to avoid shared inner node mutation - **_internalConfigureAfterSlots**: Apply serialized `widgets_values` to per-instance map after promoted views are created ## Red-Green Verification | Commit | CI Status | Purpose | |--------|-----------|---------| | `test: add failing tests for multi-instance subgraph widget value collision` | 🔴 Red | Proves widget values collide across instances | | `fix: store promoted widget values per SubgraphNode instance` | 🟢 Green | Per-instance storage prevents collision | ## Test Plan - [x] CI red on test-only commit - [x] CI green on fix commit - [x] Unit test: `preserves promoted widget values after configure with different widgets_values` - [x] All 253 existing subgraph tests pass - [ ] Manual: load workflow from issue image → verify 3 subgraph instances produce different results ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-10849-fix-store-promoted-widget-values-per-SubgraphNode-instance-3386d73d3650815a8544f54adcc0d504) by [Unito](https://www.unito.io) --------- Co-authored-by: dante <dante@danteui-MacStudio.local> |
||
|
|
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>
|
||
|
|
25d1ac7456 |
test: reorganize subgraph test suite into composable domain specs (#10759)
## Summary Reorganize the subgraph test suite so browser tests are thin representative user journeys while lower-level Vitest suites own combinatorics, migration edge cases, and data-shape semantics. ## Changes - **What**: Migrate 17 flat subgraph browser specs into 10 domain-organized specs under `browser_tests/tests/subgraph/`, move redundant semantic coverage down to 8 Vitest owner suites, delete all legacy flat files - **Browser specs** (54 tests): `subgraphSlots`, `subgraphPromotion`, `subgraphPromotionDom`, `subgraphSerialization`, `subgraphNavigation`, `subgraphNested`, `subgraphLifecycle`, `subgraphCrud`, `subgraphSearch`, `subgraphOperations` - **Vitest owners** (230 tests): `SubgraphNode.test.ts` (rename/label propagation), `subgraphNodePromotion.test.ts`, `promotedWidgetView.test.ts`, `SubgraphSerialization.test.ts` (duplicate-ID remap), `SubgraphWidgetPromotion.test.ts` (legacy hydration), `subgraphNavigationStore*.test.ts` (viewport cache, workflow-switch), `subgraphStore.test.ts` (search aliases, description) - **Net effect**: browser suite shrinks from ~96 scattered tests to 54 focused journeys ## Review Focus - Coverage ownership split: each browser test has a unique UI-only failure mode; semantic coverage lives in Vitest - `subgraphPromotionDom.spec.ts` forces LiteGraph mode and uses `canvas.openSubgraph()` instead of `navigateIntoSubgraph()` to avoid a wrapper-specific DOM overlay duplication issue — entry-affordance coverage lives in `subgraphNavigation.spec.ts` - No product code changes — test-only migration ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-10759-test-reorganize-subgraph-test-suite-into-composable-domain-specs-3336d73d365081b0a56bcbf809b1f584) by [Unito](https://www.unito.io) --------- Co-authored-by: Amp <amp@ampcode.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> |
||
|
|
4cb83353cb |
test: stabilize flaky Playwright tests (#10817)
Stabilize flaky Playwright tests by improving test reliability. This PR aims to identify and fix flaky e2e tests. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-10817-test-stabilize-flaky-Playwright-tests-3366d73d365081ada40de73ce11af625) by [Unito](https://www.unito.io) --------- Co-authored-by: Amp <amp@ampcode.com> |
||
|
|
0e7cab96b7 |
test: reorganize subgraph E2E tests into domain-organized directory (#10695)
## Summary From the primordial entropy of 17 scattered spec files — a formless sprawl of mixed concerns and inconsistent naming — emerges a clean, domain-organized hierarchy. Order triumphs over chaos. ## Changes - **What**: Reorganize all subgraph E2E tests from 17 flat files in `browser_tests/tests/` into 10 domain-grouped files under `browser_tests/tests/subgraph/`. | File | Tests | Domain | |------|-------|--------| | `subgraphSlots` | 16 | I/O slot CRUD, rename, alignment, promoted slot position | | `subgraphPromotion` | 22 | Auto-promote, visibility, reactivity, context menu, cleanup | | `subgraphSerialization` | 16 | Hydration, round-trip, legacy formats, ID remapping | | `subgraphNavigation` | 10 | Breadcrumb, viewport, hotkeys, progress state | | `subgraphNested` | 9 | Configure order, duplicate names, pack values, stale proxies | | `subgraphLifecycle` | 7 | Source removal cleanup, pseudo-preview lifecycle | | `subgraphPromotionDom` | 6 | DOM widget persistence, cleanup, positioning | | `subgraphCrud` | 5 | Create, delete, copy, unpack | | `subgraphSearch` | 3 | Search aliases, description, persistence | | `subgraphOperations` | 2 | Copy/paste inside, undo/redo inside | Where once the monolith `subgraph.spec.ts` (856 lines) mixed slot CRUD with hotkeys, DOM widgets with navigation, and copy/paste with undo/redo — now each behavioral domain has its sovereign territory. Where once `subgraph-rename-dialog.spec.ts`, `subgraphInputSlotRename.spec.ts`, and `subgraph-promoted-slot-position.spec.ts` scattered rename concerns across three kingdoms — now they answer to one crown: `subgraphSlots.spec.ts`. Where once `kebab-case` and `camelCase` warred for dominion — now a single convention reigns. All 96 test cases preserved. Zero test logic changes. Purely structural. ## Review Focus - Verify no tests were lost in the consolidation - Confirm import paths all resolve correctly at the new depth (`../../fixtures/`) - The `import.meta.dirname` asset path in `subgraphSlots.spec.ts` (slot alignment test) updated for new directory depth ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-10695-test-reorganize-subgraph-E2E-tests-into-domain-organized-directory-3326d73d36508197939be8825b69ea88) by [Unito](https://www.unito.io) Co-authored-by: Amp <amp@ampcode.com> |