Skip to content

test(assets): e2e coverage for the assets-mode model library sidebar#13574

Open
synap5e wants to merge 10 commits into
synap5e/assets-mode-sidebarfrom
synap5e/test/assets-sidebar-e2e
Open

test(assets): e2e coverage for the assets-mode model library sidebar#13574
synap5e wants to merge 10 commits into
synap5e/assets-mode-sidebarfrom
synap5e/test/assets-sidebar-e2e

Conversation

@synap5e

@synap5e synap5e commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary

E2E coverage for the assets-backed model library sidebar (#13464), testing the integration seams the unit suites mock away.

Stacked on #13464 (synap5e/assets-mode-sidebar). All assets endpoints are mocked, so the suite passes regardless of whether the CI container backend has the assets API yet.

Changes

  • What:
    • sidebar/modelLibraryRouting.spec.ts: Comfy.ModelLibrary.UseAssetBrowser + Comfy.Assets.UseAssetAPI tab routing (both on → asset browser modal; either off → sidebar tree; @cloud defaults → modal).
    • sidebar/modelLibraryAssetMode.spec.ts: asset-mode tree from a mocked /api/assets walk + /api/experiment/models registration (folder registration order, eager load with no load-all button, extension allowlists verbatim vs match-all default filtering), refresh → POST /api/assets/seed, live tree/search updates on the assets.seed.fast_complete event, ghost placement filling the loader widget with loader_path, bare-tag backend fallback.
    • Fixtures: model_type:/loader_path asset fixtures, AssetHelper seed-endpoint handling, FeatureFlagHelper.setServerFlags (forces api.serverFeatureFlags; the ff: localStorage override is dev-only and tree-shaken from production builds), dispatchApiCustomEvent util for wire-level events outside the typed ApiEventTypes map, getFolderRowByLabel page-object locator (ancestor tree rows contain descendant text, so the existing label locator misclicks nested folders).
    • AssetHelper route pattern narrowed **/assets****/api/assets**: the old pattern intercepted the built frontend's /assets/*.js chunks on any navigation after mock(). No existing consumer is affected (all target /api/assets).
    • graph.spec.ts: mirrors main's branded-LinkId fix (9e5fb67) verbatim; now superseded by main having been merged through the stack (identical content, resolved cleanly).
  • Breaking: none

Review Focus

  • The assets.seed.fast_complete injection dispatches directly on the api singleton (EventTarget.prototype.dispatchEvent), replicating the socket handler's default case; the real WS frame path above that dispatch is not exercised.
  • The bare-tag test forces supports_model_type_tags: false explicitly so the real test backend's feature_flags handshake can't decide which mode is under test.

Test plan

  • pnpm typecheck:browser, eslint, oxlint, knip clean
  • 11/11 chromium tests green against a CI-shaped stack (built OSS dist served by ComfyUI --cpu --multi-user)
  • @cloud routing test green against the built cloud dist
  • Existing sidebar/modelLibrary.spec.ts + assetHelper.spec.ts (34 tests) still green with the shared-fixture changes

synap5e added 3 commits July 10, 2026 18:29
Mirrors 9e5fb67 verbatim so the stack rebase merges cleanly.
Covers the integration seams the unit suites mock away: settings-driven
tab routing (asset browser modal vs sidebar tree, including the cloud
defaults), the eager-loaded asset-mode tree rendered from a mocked walk
with registration-order folders and extension display filtering, refresh
seeding a backend rescan with live tree/search updates on the
assets.seed.fast_complete websocket event, and ghost placement filling
the loader widget with the category-relative loader_path.

All assets endpoints are mocked so the suite does not depend on the CI
container backend having the assets API. AssetHelper's route pattern is
narrowed to **/api/assets** so navigating after mock() no longer
intercepts the built frontend's /assets/*.js chunks.
The active-search scan test now proves the eager load and debounced
search pipeline settled (via a hit on existing data) before the mock
changes, so it can no longer false-pass off a still-pending load. The
bare-tag test forces supports_model_type_tags off instead of inheriting
whatever the test backend advertises, which would have broken once CI's
backend gained the capability. The seed mock response is typed as
SeedAssetsResponse per the typed-mock rule.
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7ae67e72-5e7c-4729-9962-d1c109209e6f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds browser-test infrastructure and coverage for model library asset mode, seed rescans, feature flags, routing, model placement, and bare-tag backends. It also updates a graph regression assertion to use branded link IDs.

Changes

Model library asset and routing coverage

Layer / File(s) Summary
Asset fixtures and test controls
browser_tests/fixtures/data/assetFixtures.ts, browser_tests/fixtures/helpers/*, browser_tests/fixtures/utils/dispatchApiEvent.ts
Adds loader-path-aware model fixtures, scoped asset API mocks, seed-scan responses, server-flag overrides, and API custom-event dispatching.
Asset-mode sidebar behavior
browser_tests/fixtures/components/SidebarTab.ts, browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts
Covers folder ordering, eager loading, filtering, rescans, scan-event updates, model placement, and bare-tag behavior.
Model library routing
browser_tests/tests/sidebar/modelLibraryRouting.spec.ts
Verifies whether the model library opens the asset browser modal or sidebar tree under different settings and cloud defaults.

Graph link assertion alignment

Layer / File(s) Summary
Branded link lookup assertion
browser_tests/tests/graph.spec.ts
Passes toLinkId(1) into the evaluated graph-link lookup for the target-slot regression check.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Sidebar
  participant AssetHelper
  participant AppAPI
  Sidebar->>AssetHelper: POST /assets/seed
  AssetHelper-->>Sidebar: status started
  AppAPI-->>Sidebar: assets.seed.fast_complete
  Sidebar-->>Sidebar: refresh tree and active search results
Loading

Possibly related PRs

Suggested reviewers: christian-byrne, AustinMroz, DrJKL, benceruleanlu


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
End-To-End Regression Coverage For Fixes ❓ Inconclusive PR title/commit subjects aren’t provided here, so I can’t verify the required bug-fix signal from PR metadata alone. Please provide the PR title and commit subjects (or full PR metadata) so I can determine whether this regression-test requirement applies.
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Adr Compliance For Entity/Litegraph Changes ✅ Passed PASS: changed files are browser_tests fixtures/tests only; no src/lib/litegraph, src/ecs, or graph entity files, so ADR 0003/0008 is not applicable.
Title check ✅ Passed The title concisely and accurately summarizes the main change: e2e coverage for the assets-mode model library sidebar.
Description check ✅ Passed The description follows the template sections and provides summary, changes, review focus, and test plan details.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch synap5e/test/assets-sidebar-e2e

Comment @coderabbitai help to get the list of available commands.

@synap5e synap5e added the cursor-review Trigger multi-model Cursor agent review on this PR label Jul 10, 2026
@synap5e synap5e self-assigned this Jul 10, 2026
@synap5e
synap5e marked this pull request as ready for review July 10, 2026 11:24
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

🎭 Playwright: ✅ 1708 passed, 0 failed

📊 Browser Reports
  • chromium: View Report (✅ 1687 / ❌ 0 / ⚠️ 0 / ⏭️ 5)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 18 / ❌ 0 / ⚠️ 0 / ⏭️ 0)

📦 Bundle Size

⏳ Size data collection in progress…

⚡ Performance Report

canvas-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 74.5 MB heap
canvas-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 46.2 MB heap
canvas-zoom-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 60.9 MB heap
dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 56.0 MB heap
large-graph-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 55.9 MB heap
large-graph-pan: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 80.1 MB heap
large-graph-zoom: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 65.8 MB heap
minimap-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 63.7 MB heap
subgraph-dom-widget-clipping: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 67.0 MB heap
subgraph-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 60.5 MB heap
subgraph-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 56.9 MB heap
subgraph-transition-enter: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 168ms TBT · 91.0 MB heap
viewport-pan-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 65.5 MB heap
vue-large-graph-idle: · 58.1 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 170.3 MB heap
vue-large-graph-pan: · 58.1 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 6ms TBT · 153.4 MB heap
workflow-execution: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 59.5 MB heap

ℹ️ No baseline found — significance unavailable.

Absolute values
Metric Value
canvas-idle: avg frame time 17ms
canvas-idle: p95 frame time 17ms
canvas-idle: layout duration 0ms
canvas-idle: style recalc duration 8ms
canvas-idle: layout count 0
canvas-idle: style recalc count 9
canvas-idle: task duration 440ms
canvas-idle: script duration 17ms
canvas-idle: TBT 0ms
canvas-idle: heap used 74.5 MB
canvas-idle: DOM nodes -131
canvas-idle: event listeners -97
canvas-mouse-sweep: avg frame time 17ms
canvas-mouse-sweep: p95 frame time 17ms
canvas-mouse-sweep: layout duration 4ms
canvas-mouse-sweep: style recalc duration 36ms
canvas-mouse-sweep: layout count 12
canvas-mouse-sweep: style recalc count 73
canvas-mouse-sweep: task duration 793ms
canvas-mouse-sweep: script duration 121ms
canvas-mouse-sweep: TBT 0ms
canvas-mouse-sweep: heap used 46.2 MB
canvas-mouse-sweep: DOM nodes -271
canvas-mouse-sweep: event listeners -199
canvas-zoom-sweep: avg frame time 17ms
canvas-zoom-sweep: p95 frame time 17ms
canvas-zoom-sweep: layout duration 1ms
canvas-zoom-sweep: style recalc duration 17ms
canvas-zoom-sweep: layout count 6
canvas-zoom-sweep: style recalc count 31
canvas-zoom-sweep: task duration 330ms
canvas-zoom-sweep: script duration 18ms
canvas-zoom-sweep: TBT 0ms
canvas-zoom-sweep: heap used 60.9 MB
canvas-zoom-sweep: DOM nodes -74
canvas-zoom-sweep: event listeners -83
dom-widget-clipping: avg frame time 17ms
dom-widget-clipping: p95 frame time 17ms
dom-widget-clipping: layout duration 0ms
dom-widget-clipping: style recalc duration 8ms
dom-widget-clipping: layout count 0
dom-widget-clipping: style recalc count 11
dom-widget-clipping: task duration 357ms
dom-widget-clipping: script duration 56ms
dom-widget-clipping: TBT 0ms
dom-widget-clipping: heap used 56.0 MB
dom-widget-clipping: DOM nodes -131
dom-widget-clipping: event listeners -102
large-graph-idle: avg frame time 17ms
large-graph-idle: p95 frame time 17ms
large-graph-idle: layout duration 0ms
large-graph-idle: style recalc duration 9ms
large-graph-idle: layout count 0
large-graph-idle: style recalc count 10
large-graph-idle: task duration 549ms
large-graph-idle: script duration 99ms
large-graph-idle: TBT 0ms
large-graph-idle: heap used 55.9 MB
large-graph-idle: DOM nodes -270
large-graph-idle: event listeners -198
large-graph-pan: avg frame time 17ms
large-graph-pan: p95 frame time 17ms
large-graph-pan: layout duration 0ms
large-graph-pan: style recalc duration 19ms
large-graph-pan: layout count 0
large-graph-pan: style recalc count 69
large-graph-pan: task duration 1081ms
large-graph-pan: script duration 401ms
large-graph-pan: TBT 0ms
large-graph-pan: heap used 80.1 MB
large-graph-pan: DOM nodes 16
large-graph-pan: event listeners 6
large-graph-zoom: avg frame time 17ms
large-graph-zoom: p95 frame time 17ms
large-graph-zoom: layout duration 7ms
large-graph-zoom: style recalc duration 16ms
large-graph-zoom: layout count 60
large-graph-zoom: style recalc count 63
large-graph-zoom: task duration 1281ms
large-graph-zoom: script duration 503ms
large-graph-zoom: TBT 0ms
large-graph-zoom: heap used 65.8 MB
large-graph-zoom: DOM nodes 7
large-graph-zoom: event listeners 8
minimap-idle: avg frame time 17ms
minimap-idle: p95 frame time 17ms
minimap-idle: layout duration 0ms
minimap-idle: style recalc duration 9ms
minimap-idle: layout count 0
minimap-idle: style recalc count 9
minimap-idle: task duration 487ms
minimap-idle: script duration 89ms
minimap-idle: TBT 0ms
minimap-idle: heap used 63.7 MB
minimap-idle: DOM nodes 18
minimap-idle: event listeners 5
subgraph-dom-widget-clipping: avg frame time 17ms
subgraph-dom-widget-clipping: p95 frame time 17ms
subgraph-dom-widget-clipping: layout duration 0ms
subgraph-dom-widget-clipping: style recalc duration 11ms
subgraph-dom-widget-clipping: layout count 0
subgraph-dom-widget-clipping: style recalc count 47
subgraph-dom-widget-clipping: task duration 364ms
subgraph-dom-widget-clipping: script duration 130ms
subgraph-dom-widget-clipping: TBT 0ms
subgraph-dom-widget-clipping: heap used 67.0 MB
subgraph-dom-widget-clipping: DOM nodes 20
subgraph-dom-widget-clipping: event listeners 6
subgraph-idle: avg frame time 17ms
subgraph-idle: p95 frame time 17ms
subgraph-idle: layout duration 0ms
subgraph-idle: style recalc duration 9ms
subgraph-idle: layout count 0
subgraph-idle: style recalc count 10
subgraph-idle: task duration 400ms
subgraph-idle: script duration 13ms
subgraph-idle: TBT 0ms
subgraph-idle: heap used 60.5 MB
subgraph-idle: DOM nodes -275
subgraph-idle: event listeners -199
subgraph-mouse-sweep: avg frame time 17ms
subgraph-mouse-sweep: p95 frame time 17ms
subgraph-mouse-sweep: layout duration 4ms
subgraph-mouse-sweep: style recalc duration 36ms
subgraph-mouse-sweep: layout count 16
subgraph-mouse-sweep: style recalc count 76
subgraph-mouse-sweep: task duration 676ms
subgraph-mouse-sweep: script duration 87ms
subgraph-mouse-sweep: TBT 0ms
subgraph-mouse-sweep: heap used 56.9 MB
subgraph-mouse-sweep: DOM nodes -103
subgraph-mouse-sweep: event listeners -98
subgraph-transition-enter: avg frame time 17ms
subgraph-transition-enter: p95 frame time 17ms
subgraph-transition-enter: layout duration 15ms
subgraph-transition-enter: style recalc duration 32ms
subgraph-transition-enter: layout count 15
subgraph-transition-enter: style recalc count 19
subgraph-transition-enter: task duration 763ms
subgraph-transition-enter: script duration 28ms
subgraph-transition-enter: TBT 168ms
subgraph-transition-enter: heap used 91.0 MB
subgraph-transition-enter: DOM nodes 13682
subgraph-transition-enter: event listeners 2531
viewport-pan-sweep: avg frame time 17ms
viewport-pan-sweep: p95 frame time 17ms
viewport-pan-sweep: layout duration 0ms
viewport-pan-sweep: style recalc duration 52ms
viewport-pan-sweep: layout count 0
viewport-pan-sweep: style recalc count 251
viewport-pan-sweep: task duration 3676ms
viewport-pan-sweep: script duration 1278ms
viewport-pan-sweep: TBT 0ms
viewport-pan-sweep: heap used 65.5 MB
viewport-pan-sweep: DOM nodes -271
viewport-pan-sweep: event listeners -183
vue-large-graph-idle: avg frame time 17ms
vue-large-graph-idle: p95 frame time 17ms
vue-large-graph-idle: layout duration 0ms
vue-large-graph-idle: style recalc duration 0ms
vue-large-graph-idle: layout count 0
vue-large-graph-idle: style recalc count 0
vue-large-graph-idle: task duration 11952ms
vue-large-graph-idle: script duration 552ms
vue-large-graph-idle: TBT 0ms
vue-large-graph-idle: heap used 170.3 MB
vue-large-graph-idle: DOM nodes -5807
vue-large-graph-idle: event listeners -16375
vue-large-graph-pan: avg frame time 17ms
vue-large-graph-pan: p95 frame time 17ms
vue-large-graph-pan: layout duration 0ms
vue-large-graph-pan: style recalc duration 17ms
vue-large-graph-pan: layout count 0
vue-large-graph-pan: style recalc count 72
vue-large-graph-pan: task duration 15050ms
vue-large-graph-pan: script duration 836ms
vue-large-graph-pan: TBT 6ms
vue-large-graph-pan: heap used 153.4 MB
vue-large-graph-pan: DOM nodes -3300
vue-large-graph-pan: event listeners -16368
workflow-execution: avg frame time 17ms
workflow-execution: p95 frame time 17ms
workflow-execution: layout duration 1ms
workflow-execution: style recalc duration 18ms
workflow-execution: layout count 4
workflow-execution: style recalc count 13
workflow-execution: task duration 90ms
workflow-execution: script duration 7ms
workflow-execution: TBT 0ms
workflow-execution: heap used 59.5 MB
workflow-execution: DOM nodes 132
workflow-execution: event listeners 50
Raw data
{
  "timestamp": "2026-07-17T21:38:34.135Z",
  "gitSha": "06efd29a335cec3e9d8c757d1fd82ee3b101eb41",
  "branch": "synap5e/test/assets-sidebar-e2e",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2075.7520000000227,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 7.5470000000000015,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 473.048,
      "heapDeltaBytes": 34913064,
      "heapUsedBytes": 93811312,
      "domNodes": 16,
      "jsHeapTotalBytes": 46137344,
      "scriptDurationMs": 18.645999999999997,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-idle",
      "durationMs": 2071.2630000000445,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 8.425000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 407.909,
      "heapDeltaBytes": -7389664,
      "heapUsedBytes": 62428064,
      "domNodes": -277,
      "jsHeapTotalBytes": 18759680,
      "scriptDurationMs": 14.992999999999997,
      "eventListeners": -199,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1858.3540000000198,
      "styleRecalcs": 72,
      "styleRecalcDurationMs": 38.023,
      "layouts": 12,
      "layoutDurationMs": 3.653,
      "taskDurationMs": 821.352,
      "heapDeltaBytes": -5153580,
      "heapUsedBytes": 46871364,
      "domNodes": -277,
      "jsHeapTotalBytes": 16904192,
      "scriptDurationMs": 121.023,
      "eventListeners": -199,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1791.3689999999747,
      "styleRecalcs": 73,
      "styleRecalcDurationMs": 34.556000000000004,
      "layouts": 12,
      "layoutDurationMs": 3.5509999999999997,
      "taskDurationMs": 764.815,
      "heapDeltaBytes": -2059304,
      "heapUsedBytes": 50048872,
      "domNodes": -265,
      "jsHeapTotalBytes": 16117760,
      "scriptDurationMs": 120.834,
      "eventListeners": -199,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1707.809999999995,
      "styleRecalcs": 31,
      "styleRecalcDurationMs": 16.912999999999997,
      "layouts": 6,
      "layoutDurationMs": 0.5109999999999999,
      "taskDurationMs": 360.94100000000003,
      "heapDeltaBytes": -3663580,
      "heapUsedBytes": 66163952,
      "domNodes": -225,
      "jsHeapTotalBytes": 13254656,
      "scriptDurationMs": 18.058999999999997,
      "eventListeners": -184,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1706.3080000000355,
      "styleRecalcs": 31,
      "styleRecalcDurationMs": 16.13,
      "layouts": 6,
      "layoutDurationMs": 0.5569999999999999,
      "taskDurationMs": 299.853,
      "heapDeltaBytes": 2617652,
      "heapUsedBytes": 61530048,
      "domNodes": 77,
      "jsHeapTotalBytes": 25427968,
      "scriptDurationMs": 17.704000000000004,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 595.9080000000085,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 8.220000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 333.145,
      "heapDeltaBytes": 12636936,
      "heapUsedBytes": 70094812,
      "domNodes": 18,
      "jsHeapTotalBytes": 18350080,
      "scriptDurationMs": 56.93,
      "eventListeners": 0,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66666666666665,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 595.8249999999907,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 8.697999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 381.415,
      "heapDeltaBytes": -22485076,
      "heapUsedBytes": 47334916,
      "domNodes": -279,
      "jsHeapTotalBytes": 5652480,
      "scriptDurationMs": 55.85999999999999,
      "eventListeners": -203,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66666666666665,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2037.3430000000212,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 9.627,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 560.307,
      "heapDeltaBytes": -8892896,
      "heapUsedBytes": 58640072,
      "domNodes": -266,
      "jsHeapTotalBytes": -1847296,
      "scriptDurationMs": 101.80699999999999,
      "eventListeners": -199,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2040.4049999999643,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.549000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 537.096,
      "heapDeltaBytes": -1310220,
      "heapUsedBytes": 58690640,
      "domNodes": -273,
      "jsHeapTotalBytes": -569344,
      "scriptDurationMs": 96.40799999999999,
      "eventListeners": -197,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2121.188000000018,
      "styleRecalcs": 68,
      "styleRecalcDurationMs": 17.923000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1128.6260000000002,
      "heapDeltaBytes": 11467708,
      "heapUsedBytes": 84538236,
      "domNodes": 14,
      "jsHeapTotalBytes": 11329536,
      "scriptDurationMs": 406.76,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2120.0900000000047,
      "styleRecalcs": 70,
      "styleRecalcDurationMs": 19.779999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1033.239,
      "heapDeltaBytes": 10159620,
      "heapUsedBytes": 83511756,
      "domNodes": 18,
      "jsHeapTotalBytes": 11067392,
      "scriptDurationMs": 395.59299999999996,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3112.482,
      "styleRecalcs": 62,
      "styleRecalcDurationMs": 15.399,
      "layouts": 60,
      "layoutDurationMs": 7.2090000000000005,
      "taskDurationMs": 1284.32,
      "heapDeltaBytes": 13448436,
      "heapUsedBytes": 69735396,
      "domNodes": 6,
      "jsHeapTotalBytes": 0,
      "scriptDurationMs": 490.89099999999996,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3084.446000000071,
      "styleRecalcs": 63,
      "styleRecalcDurationMs": 15.840999999999998,
      "layouts": 60,
      "layoutDurationMs": 6.978,
      "taskDurationMs": 1277.0159999999998,
      "heapDeltaBytes": 14335012,
      "heapUsedBytes": 68300692,
      "domNodes": 8,
      "jsHeapTotalBytes": 262144,
      "scriptDurationMs": 514.6999999999999,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 1999.2599999999925,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 9.449999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 499.551,
      "heapDeltaBytes": -10528332,
      "heapUsedBytes": 66360980,
      "domNodes": 18,
      "jsHeapTotalBytes": 7745536,
      "scriptDurationMs": 92.51499999999999,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 2001.0919999999714,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 8.968999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 475.2420000000001,
      "heapDeltaBytes": 10549076,
      "heapUsedBytes": 67302056,
      "domNodes": 18,
      "jsHeapTotalBytes": 6291456,
      "scriptDurationMs": 86.32300000000001,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 555.9499999999957,
      "styleRecalcs": 47,
      "styleRecalcDurationMs": 11.554000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 354.209,
      "heapDeltaBytes": 8459708,
      "heapUsedBytes": 67415768,
      "domNodes": 20,
      "jsHeapTotalBytes": 18350080,
      "scriptDurationMs": 119.16399999999999,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 576.043000000027,
      "styleRecalcs": 47,
      "styleRecalcDurationMs": 10.819999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 372.933,
      "heapDeltaBytes": 11905024,
      "heapUsedBytes": 73195488,
      "domNodes": 20,
      "jsHeapTotalBytes": 22020096,
      "scriptDurationMs": 141.289,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2040.7579999999825,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 10.490999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 410.07099999999997,
      "heapDeltaBytes": -7484344,
      "heapUsedBytes": 62470096,
      "domNodes": -276,
      "jsHeapTotalBytes": 19283968,
      "scriptDurationMs": 13.436000000000002,
      "eventListeners": -199,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2032.8719999999976,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 7.470999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 389.61400000000003,
      "heapDeltaBytes": 12516632,
      "heapUsedBytes": 64484020,
      "domNodes": -273,
      "jsHeapTotalBytes": 15855616,
      "scriptDurationMs": 12.943999999999999,
      "eventListeners": -199,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1683.5810000000038,
      "styleRecalcs": 76,
      "styleRecalcDurationMs": 36.097,
      "layouts": 16,
      "layoutDurationMs": 3.659,
      "taskDurationMs": 653.7330000000001,
      "heapDeltaBytes": -9327052,
      "heapUsedBytes": 49608440,
      "domNodes": 64,
      "jsHeapTotalBytes": 25690112,
      "scriptDurationMs": 88.497,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1725.5089999999882,
      "styleRecalcs": 76,
      "styleRecalcDurationMs": 35.954,
      "layouts": 16,
      "layoutDurationMs": 4.5840000000000005,
      "taskDurationMs": 699.161,
      "heapDeltaBytes": 16895100,
      "heapUsedBytes": 69783084,
      "domNodes": -269,
      "jsHeapTotalBytes": 14544896,
      "scriptDurationMs": 86.384,
      "eventListeners": -199,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-transition-enter",
      "durationMs": 982.3539999999866,
      "styleRecalcs": 19,
      "styleRecalcDurationMs": 32.45400000000001,
      "layouts": 15,
      "layoutDurationMs": 15.152000000000003,
      "taskDurationMs": 762.6799999999998,
      "heapDeltaBytes": 27374424,
      "heapUsedBytes": 95374120,
      "domNodes": 13682,
      "jsHeapTotalBytes": 6291456,
      "scriptDurationMs": 28.05400000000001,
      "eventListeners": 2531,
      "totalBlockingTimeMs": 168,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8169.93100000002,
      "styleRecalcs": 252,
      "styleRecalcDurationMs": 54.274,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3744.2850000000003,
      "heapDeltaBytes": -15645432,
      "heapUsedBytes": 68991896,
      "domNodes": -268,
      "jsHeapTotalBytes": 7618560,
      "scriptDurationMs": 1290.324,
      "eventListeners": -183,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8155.648999999926,
      "styleRecalcs": 250,
      "styleRecalcDurationMs": 50.105999999999995,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3607.675,
      "heapDeltaBytes": 1038472,
      "heapUsedBytes": 68470872,
      "domNodes": -273,
      "jsHeapTotalBytes": 716800,
      "scriptDurationMs": 1265.1589999999999,
      "eventListeners": -183,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 12206.613000000005,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 12189.28,
      "heapDeltaBytes": -31090184,
      "heapUsedBytes": 174574524,
      "domNodes": -8314,
      "jsHeapTotalBytes": 22609920,
      "scriptDurationMs": 594.1919999999999,
      "eventListeners": -16372,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.223333333333237,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 11731.387999999924,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 11713.855000000001,
      "heapDeltaBytes": -30298856,
      "heapUsedBytes": 182635652,
      "domNodes": -3300,
      "jsHeapTotalBytes": 5476352,
      "scriptDurationMs": 510.15,
      "eventListeners": -16378,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.219999999999953,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 15272.03400000002,
      "styleRecalcs": 76,
      "styleRecalcDurationMs": 18.467000000000013,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 15250.284000000001,
      "heapDeltaBytes": -58754284,
      "heapUsedBytes": 166570692,
      "domNodes": -3300,
      "jsHeapTotalBytes": 5738496,
      "scriptDurationMs": 854.821,
      "eventListeners": -16372,
      "totalBlockingTimeMs": 12,
      "frameDurationMs": 17.223333333333358,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 14885.332000000062,
      "styleRecalcs": 67,
      "styleRecalcDurationMs": 16.297000000000004,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 14850.654999999999,
      "heapDeltaBytes": -60932856,
      "heapUsedBytes": 155058864,
      "domNodes": -3300,
      "jsHeapTotalBytes": 16777216,
      "scriptDurationMs": 818.143,
      "eventListeners": -16364,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.223333333333358,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "workflow-execution",
      "durationMs": 130.52399999997988,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 17.097,
      "layouts": 3,
      "layoutDurationMs": 0.6859999999999998,
      "taskDurationMs": 86.47300000000001,
      "heapDeltaBytes": 3212668,
      "heapUsedBytes": 67871616,
      "domNodes": 122,
      "jsHeapTotalBytes": 2883584,
      "scriptDurationMs": 6.325000000000001,
      "eventListeners": 33,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.669999999999998,
      "p95FrameDurationMs": 16.799999999999727
    },
    {
      "name": "workflow-execution",
      "durationMs": 447.5049999999783,
      "styleRecalcs": 16,
      "styleRecalcDurationMs": 18.376,
      "layouts": 4,
      "layoutDurationMs": 1.579,
      "taskDurationMs": 93.64800000000001,
      "heapDeltaBytes": 4771528,
      "heapUsedBytes": 56853128,
      "domNodes": 141,
      "jsHeapTotalBytes": 262144,
      "scriptDurationMs": 8.45,
      "eventListeners": 67,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    }
  ]
}

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jul 10, 2026
@synap5e
synap5e marked this pull request as draft July 10, 2026 11:25
@synap5e

synap5e commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@synap5e
synap5e marked this pull request as ready for review July 10, 2026 11:28

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Cursor Review — Consolidated panel

Triggered by @synap5e.

Found 1 finding(s).

Severity Count
🟢 Low 1

Panel: 6/8 reviewers contributed findings.

Reviewers that did not contribute: kimi-k2.5:adversarial (empty), kimi-k2.5:edge-case (empty)

Comment thread browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts`:
- Around line 103-118: Update the “Refresh seeds a backend rescan” test to
validate the POST mutation’s request body in addition to its method and
endpoint. Use AssetHelper’s recorded mutation.body to assert the seed request
contains the exact payload { roots: ['models'] }, ensuring the correct root and
payload shape are sent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7241ae27-81c7-4ce4-abfa-964ae8b03671

📥 Commits

Reviewing files that changed from the base of the PR and between e6916bb and 1b44590.

📒 Files selected for processing (8)
  • browser_tests/fixtures/components/SidebarTab.ts
  • browser_tests/fixtures/data/assetFixtures.ts
  • browser_tests/fixtures/helpers/AssetHelper.ts
  • browser_tests/fixtures/helpers/FeatureFlagHelper.ts
  • browser_tests/fixtures/utils/dispatchApiEvent.ts
  • browser_tests/tests/graph.spec.ts
  • browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts
  • browser_tests/tests/sidebar/modelLibraryRouting.spec.ts

Comment thread browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts Outdated
@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

@@                       Coverage Diff                       @@
##           synap5e/assets-mode-sidebar   #13574      +/-   ##
===============================================================
- Coverage                        77.52%   77.38%   -0.14%     
===============================================================
  Files                             1656     1656              
  Lines                            95008    95195     +187     
  Branches                         31560    32266     +706     
===============================================================
+ Hits                             73656    73671      +15     
- Misses                           20642    20813     +171     
- Partials                           710      711       +1     
Flag Coverage Δ
unit 66.06% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.
see 7 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

The seed test now asserts the request body ({ roots: ['models'] }), not
just the endpoint. The placement test anchors its zero-node check on the
visible ghost preview, so it verifies arming completed without placing
rather than racing a first-poll pass.
@synap5e synap5e removed their assignment Jul 10, 2026

@christian-byrne christian-byrne left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@christian-byrne christian-byrne left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated multi-agent review of this PR's delta against its parent branch (concurrent reviewers; B-group tooling and dependency scans skipped since the review checkout has no installed deps). No blocking issues. Findings below, most inline. The route-pattern narrowing (/assets to /api/assets) was verified to regress no existing spec and to fix a latent JS-chunk-intercept bug.

Comment thread browser_tests/fixtures/helpers/FeatureFlagHelper.ts
Comment thread browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts Outdated
Comment thread browser_tests/tests/sidebar/modelLibraryRouting.spec.ts
Comment thread browser_tests/tests/sidebar/modelLibraryRouting.spec.ts Outdated
Comment thread browser_tests/fixtures/data/assetFixtures.ts Outdated
Comment thread browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts
Comment thread browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts
christian-byrne and others added 2 commits July 17, 2026 21:14
- Fix false docstring guarantee on setServerFlags: replace the "cannot
  clobber" promise with an accurate note that reconnects will drop
  injected flags; point readers to mockServerFeatures() for durable
  overrides.
- Use MODEL_TYPE_CHECKPOINT_NESTED.loader_path instead of hardcoded
  'SDXL/sd_xl_base_1.0.safetensors' so the assertion tracks the fixture.
- Add setting-value assertions to the cloud routing test so it pins the
  defaults, not just the downstream routing result.
- Swap vacuous toBeHidden() calls on v-if elements to toHaveCount(0).
- Drop dead export from CoreModelAsset (no spec imports it).
- Add inline comments explaining the intentional .gguf extension and the
  distinct coverage path of the near-duplicate fast_complete search test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@christian-byrne

Copy link
Copy Markdown
Contributor

Round 2 review — e2e test completeness

Three findings covering test robustness angles not addressed in round 1:

1. Remaining toBeHidden() calls on v-if elements (nitpick, non-blocking)

browser_tests/tests/sidebar/modelLibraryAssetMode.spec.ts:132 — the prior-round fix swapped toBeHidden()toHaveCount(0) in the routing spec, but this file still has three toBeHidden() calls (lines 76, 102, 132). For README and loadAllFoldersButton the vacuous pass is harmless since paired positive assertions guard the test. Line 132 is different: it's the "before" guard in the live-update test — if freshly_scanned were already present in the tree before the event fires, toBeHidden() would still pass (the locator returns no match), and the subsequent toBeVisible() would also pass, leaving the live-update path untested. toHaveCount(0) would catch that case.


2. No unhappy-path test for API error (suggestion, non-blocking)

browser_tests/tests/sidebar/modelLibraryAssetMode.spec.tsAssetHelper.mockError() exists but none of the new specs call it. The sidebar's behavior when /api/assets returns a 500 (error banner, empty tree, retry availability) is completely untested. Even a single test calling assetApi.mockError(500) before comfyPage.setup() and asserting the tree doesn't crash or hang would close the gap.


3. Tree node selectors rely on PrimeVue internal class names (nitpick, non-blocking)

browser_tests/fixtures/components/SidebarTab.tsgetFolderRowByLabel (new in this PR) and the existing getLeafByLabel both match via PrimeVue CSS class names (.p-tree-node-leaf, .p-tree-node:not(.p-tree-node-leaf)). PrimeVue renamed these in v4 → v5; a future upgrade would silently break every locator that uses them. Backing them with data-testid on the tree node elements (analogous to how NodeLibrarySidebarTab uses [data-testid="node-tree-leaf"]) would make them upgrade-proof.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cursor-review Trigger multi-model Cursor agent review on this PR size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants