Commit Graph

4 Commits

Author SHA1 Message Date
pythongosssss
5899a9392e test: Simplify vue node/menu test setup (#11184)
## Summary
Simplifies test setup for common settings

## Changes

- **What**: 
- add vue-nodes tag to auto enable nodes 2.0
- remove UseNewMenu Top as this is default

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11184-test-Simplify-vue-node-menu-test-setup-3416d73d3650815487e0c357d28761fe)
by [Unito](https://www.unito.io)
2026-04-13 20:43:25 +00:00
Alexander Brown
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>
2026-04-09 20:50:56 -07:00
Alexander Brown
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>
2026-04-08 11:28:59 -07:00
jaeone94
bb96e3c95c fix: resolve subgraph promoted widget panel regressions (#10648)
## Summary

Fix four bugs in the subgraph promoted widget panel where linked
promotions were not distinguished from independent ones, causing
incorrect UI state in both the SubgraphEditor (Settings) panel and the
Parameters tab WidgetActions menu.

## Changes

- **What**: Add `isLinkedPromotion` helper to correctly identify widgets
driven by subgraph input connections. Fix `disambiguatingSourceNodeId`
lookup mismatch that broke `isWidgetShownOnParents` and
`handleHideInput` for non-nested promoted widgets. Replace fragile CSS
icon selectors with `data-testid` attributes.

## Bugs fixed

Companion fix PR for #10502 (red-green test PR). All 4 E2E tests from
#10502 now pass:

| Bug | Root cause | Fix |
|-----|-----------|-----|
| Linked promoted widgets have hide toggle enabled | `SubgraphEditor`
only checked `node.id === -1` (physical) — linked promotions from
subgraph input connections were not detected | Added `isLinkedPromotion`
helper that checks `input._widget` bindings; `SubgraphNodeWidget`
`:is-physical` prop now covers both physical and linked cases |
| Linked promoted widgets show eye icon instead of link icon | Same root
cause as above — `isPhysical` prop was only true for `node.id === -1` |
Extended the `:is-physical` condition to include `isLinkedPromotion`
check |
| Widget labels show raw names instead of renamed values |
`SubgraphEditor` passed `widget.name` instead of `widget.label \|\|
widget.name` | Changed `:widget-name` binding to prefer `widget.label` |
| WidgetActions menu shows Hide/Show for linked promotions |
`v-if="hasParents"` didn't exclude linked promotions | Added
`canToggleVisibility` computed that combines `hasParents` with
`!isLinked` check via `isLinkedPromotion` |

### Additional bugs discovered and fixed

| Bug | Root cause | Fix |
|-----|-----------|-----|
| "Show input" always displayed instead of "Hide input" for promoted
widgets | `SectionWidgets.isWidgetShownOnParents` used
`getSourceNodeId(widget)` which falls back to `widget.sourceNodeId` when
`disambiguatingSourceNodeId` is undefined — this mismatches the
promotion store key (`undefined`) | Changed to
`widget.disambiguatingSourceNodeId` directly |
| "Hide input" click does nothing | `WidgetActions.handleHideInput` used
`getSourceNodeId(widget)` for the same reason — `demote()` couldn't find
the entry to remove | Same fix — use `widget.disambiguatingSourceNodeId`
directly |

## Tests added

### E2E (Playwright) —
`browser_tests/tests/subgraphPromotedWidgetPanel.spec.ts`

| Test | What it verifies |
|------|-----------------|
| linked promoted widgets have hide toggle disabled | All toggle buttons
in SubgraphEditor shown section are disabled for linked widgets (covers
1-level and 2-level nested promotions via `subgraph-nested-promotion`
fixture) |
| linked promoted widgets show link icon instead of eye icon | Link
icons appear for linked widgets, no eye icons present |
| widget labels display renamed values instead of raw names |
`widget.label` is displayed when set, not `widget.name` |
| linked promoted widget menu should not show Hide/Show input |
Three-dot menu on Parameters tab omits Hide/Show options for linked
promotions, Rename is still available |

### Unit (Vitest) — `src/core/graph/subgraph/promotionUtils.test.ts`

7 tests covering `isLinkedPromotion`: basic matching, negative cases,
nested subgraph with `disambiguatingSourceNodeId`, multiple inputs, and
mixed linked/independent state.

### Unit (Vitest) —
`src/components/rightSidePanel/parameters/WidgetActions.test.ts`

- Added `isSubgraphNode: () => false` to mock nodes to prevent crash
from new `isLinked` computed

## Review Focus

- `isLinkedPromotion` reads `input._widget` (WeakRef-backed,
non-reactive) directly in the template. This is intentional — `_widget`
bindings are set during subgraph initialization before the user opens
the panel, so stale reads don't occur in practice. A computed-based
approach was attempted but reverted because `_widget` changes cannot
trigger Vue reactivity.
- `getSourceNodeId` removal in `SectionWidgets` and `WidgetActions` is
intentional — the old fallback (`?? widget.sourceNodeId`) caused key
mismatches with the promotion store for non-nested widgets.

## Screenshots
Before
<img width="723" height="935" alt="image"
src="https://github.com/user-attachments/assets/09862578-a0d1-45b4-929c-f22f7494ebe2"
/>

After
<img width="999" height="952" alt="image"
src="https://github.com/user-attachments/assets/ed8fe604-6b44-46b9-a315-6da31d6b405a"
/>
2026-04-01 17:10:30 +09:00