Skip to content

refactor: extract LocateNodeButton for errors panel - #13401

Merged
mattmillerai merged 7 commits into
mainfrom
matt/be-2256-locate-node-button
Jul 28, 2026
Merged

refactor: extract LocateNodeButton for errors panel#13401
mattmillerai merged 7 commits into
mainfrom
matt/be-2256-locate-node-button

Conversation

@mattmillerai

Copy link
Copy Markdown
Contributor

ELI-5

The errors panel had the same little "locate this node" button copy-pasted in four places, with tiny inconsistencies between the copies. This pulls it into one small reusable component so every locate button is defined once and behaves identically.

Summary

Extract the duplicated locate icon-button (variant="textonly" size="icon-sm" with a lucide--locate icon) from the errors panel into a single LocateNodeButton.vue.

Changes

  • What: New src/components/rightSidePanel/errors/LocateNodeButton.vue (prop label for the accessible name, emits locate). Replaces the four byte-identical <Button> locate sites — ErrorNodeCard.vue, TabErrors.vue, and two in MissingPackGroupRow.vue. Standardizes two prior inconsistencies across those sites: the decorative icon now always carries aria-hidden="true" (previously omitted in ErrorNodeCard/TabErrors) and the click handler always uses the .stop modifier (previously plain @click in MissingPackGroupRow, which sits under no ancestor click handler so behavior is unchanged).
  • Breaking: None. The rendered markup, classes, accessible name, and each parent's existing locateNode emit are unchanged.

Review Focus

  • Prop is named label, not ariaLabel as the grooming note suggested: a prop named ariaLabel collides with the native aria-label global attribute, so vue-tsc captures the kebab binding as a fallthrough attr and the required prop goes unresolved (real type error). label is unambiguous and maps cleanly onto the button's aria-label.
  • Text-button unification is intentionally out of scope. The grooming note's second sub-claim (promote packTextButtonClass to a shared const and replace the two inline text-button strings) is gated on a design decision: those strings diverge in font size — ErrorNodeCard uses text-sm/relaxed while TabErrors/packTextButtonClass use text-xs/relaxed — so unifying them changes ErrorNodeCard's rendered text size. That needs a design call on the intended size and is left for a follow-up rather than guessed at here.

Tests

New LocateNodeButton.test.ts covers accessible name, locate emission, and click-propagation stopping. Existing ErrorNodeCard/TabErrors/MissingPackGroupRow suites pass unchanged (61 tests). pnpm typecheck, eslint, and oxfmt clean.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 43 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e844bb3d-af29-4dbd-9ce1-faa6a93d18d1

📥 Commits

Reviewing files that changed from the base of the PR and between 24f7bbd and 7f4389b.

📒 Files selected for processing (3)
  • src/components/rightSidePanel/errors/ErrorNodeCard.test.ts
  • src/components/rightSidePanel/errors/ErrorNodeCard.vue
  • src/components/rightSidePanel/errors/MissingPackGroupRow.test.ts
📝 Walkthrough

Walkthrough

Changes

Errors panel locate controls

Layer / File(s) Summary
Shared locate button contract
src/components/rightSidePanel/errors/LocateNodeButton.vue, src/components/rightSidePanel/errors/LocateNodeButton.test.ts
Adds a reusable icon-only button with localized aria-label, locate emission, keyboard support, and stopped propagation.
Error list integration
src/components/rightSidePanel/errors/ErrorGroupList.vue, src/components/rightSidePanel/errors/ErrorNodeCard.vue
Replaces inline locate buttons with LocateNodeButton while preserving existing node-location handlers.
Missing-pack row integration
src/components/rightSidePanel/errors/MissingPackGroupRow.vue, src/components/rightSidePanel/errors/MissingPackGroupRow.test.ts
Uses item-specific locate labels for primary and child actions and updates tests for locatable and non-locatable node types.
Missing-node selector hardening
browser_tests/tests/propertiesPanel/errorsTabMissingNodes.spec.ts
Adds exact accessible-name matching for missing-node and grouped-pack row selectors.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers: christian-byrne

🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: extracting LocateNodeButton for the errors panel.
Description check ✅ Passed The description covers the required Summary, Changes, and Review Focus sections and is mostly complete, with screenshots omitted.
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.
End-To-End Regression Coverage For Fixes ✅ Passed PASS: the PR includes a browser_tests Playwright update, so the E2E-regression coverage requirement is satisfied.
Adr Compliance For Entity/Litegraph Changes ✅ Passed No changed files are under src/lib/litegraph/, src/ecs/, or graph-entity code; the PR is limited to errors-panel Vue/components and tests.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch matt/be-2256-locate-node-button

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

@mattmillerai mattmillerai added agent-coded Opened by the agent-work code loop cursor-review Trigger multi-model Cursor agent review on this PR labels Jul 2, 2026
@mattmillerai
mattmillerai marked this pull request as ready for review July 2, 2026 20:10
@mattmillerai
mattmillerai requested a review from a team July 2, 2026 20:10
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jul 2, 2026
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

🎭 Playwright: ✅ 1716 passed, 0 failed · 1 flaky

📊 Browser Reports
  • chromium: View Report (✅ 1695 / ❌ 0 / ⚠️ 1 / ⏭️ 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)

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 07/18/2026, 01:31:09 PM UTC

Links

📦 Bundle: 7.91 MB gzip 🔴 +151 B

Details

Summary

  • Raw size: 33.4 MB baseline 33.4 MB — 🟢 -164 B
  • Gzip: 7.91 MB baseline 7.91 MB — 🔴 +151 B
  • Brotli: 5.45 MB baseline 5.45 MB — 🔴 +105 B
  • Bundles: 302 current • 302 baseline • 2 added / 2 removed

Category Glance
Graph Workspace 🟢 -164 B (1.25 MB) · Vendor & Third-Party ⚪ 0 B (15.7 MB) · Other ⚪ 0 B (11.9 MB) · Utilities & Hooks ⚪ 0 B (3.4 MB) · Panels & Settings ⚪ 0 B (550 kB) · Data & Services ⚪ 0 B (273 kB) · + 5 more

App Entry Points — 47.3 kB (baseline 47.3 kB) • ⚪ 0 B

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-BKyryTZC.js (new) 47.3 kB 🔴 +47.3 kB 🔴 +14.1 kB 🔴 +12.2 kB
assets/index-C4giOV8y.js (removed) 47.3 kB 🟢 -47.3 kB 🟢 -14.1 kB 🟢 -12.1 kB

Status: 1 added / 1 removed

Graph Workspace — 1.25 MB (baseline 1.25 MB) • 🟢 -164 B

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-CZ1UQe89.js (removed) 1.25 MB 🟢 -1.25 MB 🟢 -266 kB 🟢 -200 kB
assets/GraphView-CVMC25Jw.js (new) 1.25 MB 🔴 +1.25 MB 🔴 +266 kB 🔴 +200 kB

Status: 1 added / 1 removed

Views & Navigation — 109 kB (baseline 109 kB) • ⚪ 0 B

Top-level views, pages, and routed surfaces

Status: 14 unchanged

Panels & Settings — 550 kB (baseline 550 kB) • ⚪ 0 B

Configuration panels, inspectors, and settings screens

Status: 26 unchanged

User & Accounts — 29.1 kB (baseline 29.1 kB) • ⚪ 0 B

Authentication, profile, and account management bundles

Status: 10 unchanged

Editors & Dialogs — 121 kB (baseline 121 kB) • ⚪ 0 B

Modals, dialogs, drawers, and in-app editors

Status: 6 unchanged

UI Components — 56.8 kB (baseline 56.8 kB) • ⚪ 0 B

Reusable component library chunks

Status: 13 unchanged

Data & Services — 273 kB (baseline 273 kB) • ⚪ 0 B

Stores, services, APIs, and repositories

Status: 16 unchanged

Utilities & Hooks — 3.4 MB (baseline 3.4 MB) • ⚪ 0 B

Helpers, composables, and utility bundles

Status: 36 unchanged

Vendor & Third-Party — 15.7 MB (baseline 15.7 MB) • ⚪ 0 B

External libraries and shared vendor chunks

Status: 16 unchanged

Other — 11.9 MB (baseline 11.9 MB) • ⚪ 0 B

Bundles that do not match a named category

Status: 163 unchanged

⚡ Performance Report

canvas-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 57.9 MB heap
canvas-mouse-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 51.2 MB heap
canvas-zoom-sweep: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 72.5 MB heap
dom-widget-clipping: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 54.5 MB heap
large-graph-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 62.4 MB heap
large-graph-pan: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 56.0 MB heap
large-graph-zoom: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 53.6 MB heap
minimap-idle: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 63.0 MB heap
subgraph-dom-widget-clipping: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 54.9 MB heap
subgraph-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 46.8 MB heap
subgraph-mouse-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 54.2 MB heap
subgraph-transition-enter: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 127ms TBT · 79.4 MB heap
viewport-pan-sweep: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 74.4 MB heap
vue-large-graph-idle: · 57.2 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 156.6 MB heap
vue-large-graph-pan: · 58.1 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 87ms TBT · 165.1 MB heap
workflow-execution: · 60.0 avg FPS · 59.7 P5 FPS ✅ (target: ≥52) · 0ms TBT · 49.4 MB heap

⚠️ 1 regression detected

Show regressions
Metric Baseline PR (median) Δ Sig
canvas-mouse-sweep: layout duration 4ms 4ms +10% ⚠️ z=2.7
All metrics
Metric Baseline PR (median) Δ Sig
canvas-idle: avg frame time 17ms 17ms +0% z=-0.1
canvas-idle: p95 frame time 17ms 17ms +1%
canvas-idle: layout duration 0ms 0ms +0%
canvas-idle: style recalc duration 10ms 9ms -12% z=-1.9
canvas-idle: layout count 0 0 +0%
canvas-idle: style recalc count 10 10 +0% z=-2.1
canvas-idle: task duration 473ms 421ms -11% z=0.9
canvas-idle: script duration 24ms 18ms -26% z=-3.3
canvas-idle: TBT 0ms 0ms +0%
canvas-idle: heap used 69.3 MB 57.9 MB -16%
canvas-idle: DOM nodes 14 -122 -971% z=-113.4
canvas-idle: event listeners 4 -65 -1713% z=-16.1
canvas-mouse-sweep: avg frame time 17ms 17ms -0% z=-0.9
canvas-mouse-sweep: p95 frame time 17ms 17ms +0%
canvas-mouse-sweep: layout duration 4ms 4ms +10% ⚠️ z=2.7
canvas-mouse-sweep: style recalc duration 41ms 41ms -2% z=-0.7
canvas-mouse-sweep: layout count 12 12 +0%
canvas-mouse-sweep: style recalc count 75 77 +2% z=-0.9
canvas-mouse-sweep: task duration 841ms 885ms +5% z=0.3
canvas-mouse-sweep: script duration 130ms 124ms -4% z=-1.8
canvas-mouse-sweep: TBT 0ms 0ms +0%
canvas-mouse-sweep: heap used 51.8 MB 51.2 MB -1%
canvas-mouse-sweep: DOM nodes -265 -265 +0% z=-126.5
canvas-mouse-sweep: event listeners -133 -132 -1% z=-33.7
canvas-zoom-sweep: avg frame time 17ms 17ms -0% z=-0.3
canvas-zoom-sweep: p95 frame time 17ms 17ms +1%
canvas-zoom-sweep: layout duration 1ms 1ms -12% z=-0.5
canvas-zoom-sweep: style recalc duration 19ms 17ms -14% z=-1.7
canvas-zoom-sweep: layout count 6 6 +0%
canvas-zoom-sweep: style recalc count 32 31 -5% z=-1.7
canvas-zoom-sweep: task duration 353ms 310ms -12% z=-0.7
canvas-zoom-sweep: script duration 24ms 18ms -25% z=-3.0
canvas-zoom-sweep: TBT 0ms 0ms +0%
canvas-zoom-sweep: heap used 72.9 MB 72.5 MB -1%
canvas-zoom-sweep: DOM nodes 76 78 +3% z=-1.6
canvas-zoom-sweep: event listeners 19 19 +0% z=-0.9
dom-widget-clipping: avg frame time 17ms 17ms +0% z=0.1
dom-widget-clipping: p95 frame time 17ms 17ms -0%
dom-widget-clipping: layout duration 0ms 0ms +0%
dom-widget-clipping: style recalc duration 10ms 9ms -14% z=-1.1
dom-widget-clipping: layout count 0 0 +0%
dom-widget-clipping: style recalc count 12 13 +4% z=-1.2
dom-widget-clipping: task duration 357ms 342ms -4% z=-1.3
dom-widget-clipping: script duration 62ms 54ms -12% z=-4.1
dom-widget-clipping: TBT 0ms 0ms +0%
dom-widget-clipping: heap used 54.6 MB 54.5 MB -0%
dom-widget-clipping: DOM nodes 20 21 +5% z=-0.8
dom-widget-clipping: event listeners 2 0 -100% variance too high
large-graph-idle: avg frame time 17ms 17ms -0% z=-0.6
large-graph-idle: p95 frame time 17ms 17ms -0%
large-graph-idle: layout duration 0ms 0ms +0%
large-graph-idle: style recalc duration 10ms 8ms -20% z=-4.0
large-graph-idle: layout count 0 0 +0%
large-graph-idle: style recalc count 9 10 +6% z=-6.7
large-graph-idle: task duration 641ms 532ms -17% z=-0.2
large-graph-idle: script duration 110ms 80ms -27% z=-2.1
large-graph-idle: TBT 0ms 0ms +0%
large-graph-idle: heap used 61.4 MB 62.4 MB +2%
large-graph-idle: DOM nodes -267 -267 +0% z=-322.7
large-graph-idle: event listeners -129 -129 +0% z=-25.4
large-graph-pan: avg frame time 17ms 17ms +0% z=0.3
large-graph-pan: p95 frame time 17ms 17ms -0%
large-graph-pan: layout duration 0ms 0ms +0%
large-graph-pan: style recalc duration 15ms 17ms +11% z=-0.7
large-graph-pan: layout count 0 0 +0%
large-graph-pan: style recalc count 68 69 +1% z=-1.7
large-graph-pan: task duration 1144ms 1069ms -7% z=-0.3
large-graph-pan: script duration 399ms 368ms -8% z=-2.0
large-graph-pan: TBT 0ms 0ms +0%
large-graph-pan: heap used 53.1 MB 56.0 MB +5%
large-graph-pan: DOM nodes -268 -270 +1% z=-175.2
large-graph-pan: event listeners -129 -128 -1% z=-160.5
large-graph-zoom: avg frame time 17ms 17ms -0%
large-graph-zoom: p95 frame time 17ms 17ms -0%
large-graph-zoom: layout duration 8ms 8ms +5%
large-graph-zoom: style recalc duration 17ms 15ms -9%
large-graph-zoom: layout count 60 60 +0%
large-graph-zoom: style recalc count 66 65 -2%
large-graph-zoom: task duration 1405ms 1315ms -6%
large-graph-zoom: script duration 511ms 472ms -8%
large-graph-zoom: TBT 0ms 0ms +0%
large-graph-zoom: heap used 59.3 MB 53.6 MB -9%
large-graph-zoom: DOM nodes -269 -273 +1%
large-graph-zoom: event listeners -133 -133 +0%
minimap-idle: avg frame time 17ms 17ms +0% z=0.1
minimap-idle: p95 frame time 17ms 17ms -0%
minimap-idle: layout duration 0ms 0ms +0%
minimap-idle: style recalc duration 8ms 7ms -14% z=-3.2
minimap-idle: layout count 0 0 +0%
minimap-idle: style recalc count 8 9 +6% z=-1.6
minimap-idle: task duration 648ms 529ms -18% z=0.0
minimap-idle: script duration 112ms 80ms -28% z=-1.8
minimap-idle: TBT 0ms 0ms +0%
minimap-idle: heap used 63.5 MB 63.0 MB -1%
minimap-idle: DOM nodes -267 -269 +1% z=-210.3
minimap-idle: event listeners -129 -128 -1% z=-200.8
subgraph-dom-widget-clipping: avg frame time 17ms 17ms +0% z=0.1
subgraph-dom-widget-clipping: p95 frame time 17ms 17ms -1%
subgraph-dom-widget-clipping: layout duration 0ms 0ms +0%
subgraph-dom-widget-clipping: style recalc duration 12ms 11ms -8% z=-1.6
subgraph-dom-widget-clipping: layout count 0 0 +0%
subgraph-dom-widget-clipping: style recalc count 47 48 +1% z=-0.8
subgraph-dom-widget-clipping: task duration 387ms 373ms -3% z=-0.3
subgraph-dom-widget-clipping: script duration 126ms 124ms -1% z=-0.6
subgraph-dom-widget-clipping: TBT 0ms 0ms +0%
subgraph-dom-widget-clipping: heap used 54.9 MB 54.9 MB -0%
subgraph-dom-widget-clipping: DOM nodes 20 21 +5% z=-1.1
subgraph-dom-widget-clipping: event listeners 8 6 -25% z=-1.7
subgraph-idle: avg frame time 17ms 17ms +0% z=0.4
subgraph-idle: p95 frame time 17ms 17ms -1%
subgraph-idle: layout duration 0ms 0ms +0%
subgraph-idle: style recalc duration 10ms 8ms -19% z=-3.2
subgraph-idle: layout count 0 0 +0%
subgraph-idle: style recalc count 11 10 -14% z=-2.1
subgraph-idle: task duration 449ms 402ms -10% z=1.0
subgraph-idle: script duration 17ms 14ms -20% z=-2.4
subgraph-idle: TBT 0ms 0ms +0%
subgraph-idle: heap used 45.4 MB 46.8 MB +3%
subgraph-idle: DOM nodes -263 -267 +1% z=-192.8
subgraph-idle: event listeners -133 -133 +0% variance too high
subgraph-mouse-sweep: avg frame time 17ms 17ms -0% z=-0.1
subgraph-mouse-sweep: p95 frame time 17ms 17ms +0%
subgraph-mouse-sweep: layout duration 5ms 4ms -7% z=-1.2
subgraph-mouse-sweep: style recalc duration 39ms 38ms -4% z=-1.4
subgraph-mouse-sweep: layout count 16 16 +0%
subgraph-mouse-sweep: style recalc count 75 77 +2% z=-1.9
subgraph-mouse-sweep: task duration 752ms 681ms -9% z=-1.2
subgraph-mouse-sweep: script duration 99ms 89ms -10% z=-1.8
subgraph-mouse-sweep: TBT 0ms 0ms +0%
subgraph-mouse-sweep: heap used 46.5 MB 54.2 MB +17%
subgraph-mouse-sweep: DOM nodes -263 -101 -62% z=-74.9
subgraph-mouse-sweep: event listeners -133 -65 -52% variance too high
subgraph-transition-enter: avg frame time 17ms 17ms +0%
subgraph-transition-enter: p95 frame time 17ms 17ms +0%
subgraph-transition-enter: layout duration 16ms 13ms -15%
subgraph-transition-enter: style recalc duration 33ms 30ms -10%
subgraph-transition-enter: layout count 16 15 -6%
subgraph-transition-enter: style recalc count 20 19 -5%
subgraph-transition-enter: task duration 804ms 729ms -9%
subgraph-transition-enter: script duration 29ms 27ms -8%
subgraph-transition-enter: TBT 144ms 127ms -12%
subgraph-transition-enter: heap used 78.9 MB 79.4 MB +1%
subgraph-transition-enter: DOM nodes 13673 13673 +0%
subgraph-transition-enter: event listeners 2369 2369 +0%
viewport-pan-sweep: avg frame time 17ms 17ms +0%
viewport-pan-sweep: p95 frame time 17ms 17ms -0%
viewport-pan-sweep: layout duration 0ms 0ms +0%
viewport-pan-sweep: style recalc duration 39ms 43ms +9%
viewport-pan-sweep: layout count 0 0 +0%
viewport-pan-sweep: style recalc count 250 251 +0%
viewport-pan-sweep: task duration 3941ms 3638ms -8%
viewport-pan-sweep: script duration 1272ms 1191ms -6%
viewport-pan-sweep: TBT 0ms 0ms +0%
viewport-pan-sweep: heap used 71.7 MB 74.4 MB +4%
viewport-pan-sweep: DOM nodes -268 -265 -1%
viewport-pan-sweep: event listeners -113 -113 +0%
vue-large-graph-idle: avg frame time 18ms 17ms -2%
vue-large-graph-idle: p95 frame time 17ms 17ms -1%
vue-large-graph-idle: layout duration 0ms 0ms +0%
vue-large-graph-idle: style recalc duration 0ms 0ms +0%
vue-large-graph-idle: layout count 0 0 +0%
vue-large-graph-idle: style recalc count 0 0 +0%
vue-large-graph-idle: task duration 12936ms 13629ms +5%
vue-large-graph-idle: script duration 571ms 527ms -8%
vue-large-graph-idle: TBT 0ms 0ms +0%
vue-large-graph-idle: heap used 162.1 MB 156.6 MB -3%
vue-large-graph-idle: DOM nodes -8311 -8311 +0%
vue-large-graph-idle: event listeners -16386 -16384 -0%
vue-large-graph-pan: avg frame time 17ms 17ms -0%
vue-large-graph-pan: p95 frame time 17ms 17ms +0%
vue-large-graph-pan: layout duration 0ms 0ms +0%
vue-large-graph-pan: style recalc duration 14ms 16ms +18%
vue-large-graph-pan: layout count 0 0 +0%
vue-large-graph-pan: style recalc count 83 107 +28%
vue-large-graph-pan: task duration 15925ms 16884ms +6%
vue-large-graph-pan: script duration 870ms 887ms +2%
vue-large-graph-pan: TBT 17ms 87ms +409%
vue-large-graph-pan: heap used 171.2 MB 165.1 MB -4%
vue-large-graph-pan: DOM nodes -8311 -8311 +0%
vue-large-graph-pan: event listeners -16380 -16381 +0%
workflow-execution: avg frame time 17ms 17ms -0% z=0.1
workflow-execution: p95 frame time 17ms 17ms +0%
workflow-execution: layout duration 1ms 1ms -56% z=-6.6
workflow-execution: style recalc duration 23ms 20ms -13% z=-1.9
workflow-execution: layout count 3 3 -17% z=-4.5
workflow-execution: style recalc count 18 13 -28% z=-2.3
workflow-execution: task duration 126ms 125ms -1% z=0.2
workflow-execution: script duration 10ms 12ms +14% z=-5.8
workflow-execution: TBT 0ms 0ms +0%
workflow-execution: heap used 49.7 MB 49.4 MB -1%
workflow-execution: DOM nodes 141 125 -12% z=-5.1
workflow-execution: event listeners 65 58 -11% z=1.4
Historical variance (last 15 runs)
Metric μ σ CV
canvas-idle: avg frame time 17ms 0ms 0.0%
canvas-idle: layout duration 0ms 0ms 0.0%
canvas-idle: style recalc duration 11ms 1ms 8.2%
canvas-idle: layout count 0 0 0.0%
canvas-idle: style recalc count 11 1 5.0%
canvas-idle: task duration 395ms 31ms 7.9%
canvas-idle: script duration 25ms 2ms 8.8%
canvas-idle: TBT 0ms 0ms 0.0%
canvas-idle: DOM nodes 23 1 5.6%
canvas-idle: event listeners 12 5 40.9%
canvas-mouse-sweep: avg frame time 17ms 0ms 0.0%
canvas-mouse-sweep: layout duration 4ms 0ms 5.4%
canvas-mouse-sweep: style recalc duration 43ms 3ms 7.4%
canvas-mouse-sweep: layout count 12 0 0.0%
canvas-mouse-sweep: style recalc count 79 2 3.0%
canvas-mouse-sweep: task duration 865ms 58ms 6.7%
canvas-mouse-sweep: script duration 136ms 6ms 4.8%
canvas-mouse-sweep: TBT 0ms 0ms 0.0%
canvas-mouse-sweep: DOM nodes 62 3 4.2%
canvas-mouse-sweep: event listeners 8 4 49.4%
canvas-zoom-sweep: avg frame time 17ms 0ms 0.0%
canvas-zoom-sweep: layout duration 1ms 0ms 7.0%
canvas-zoom-sweep: style recalc duration 19ms 2ms 8.0%
canvas-zoom-sweep: layout count 6 0 0.0%
canvas-zoom-sweep: style recalc count 31 0 1.5%
canvas-zoom-sweep: task duration 327ms 23ms 7.1%
canvas-zoom-sweep: script duration 27ms 3ms 11.1%
canvas-zoom-sweep: TBT 0ms 0ms 0.0%
canvas-zoom-sweep: DOM nodes 79 1 1.0%
canvas-zoom-sweep: event listeners 24 5 21.8%
dom-widget-clipping: avg frame time 17ms 0ms 0.0%
dom-widget-clipping: layout duration 0ms 0ms 0.0%
dom-widget-clipping: style recalc duration 10ms 1ms 8.0%
dom-widget-clipping: layout count 0 0 0.0%
dom-widget-clipping: style recalc count 13 0 3.8%
dom-widget-clipping: task duration 365ms 16ms 4.5%
dom-widget-clipping: script duration 68ms 3ms 4.8%
dom-widget-clipping: TBT 0ms 0ms 0.0%
dom-widget-clipping: DOM nodes 22 1 6.4%
dom-widget-clipping: event listeners 8 6 81.2%
large-graph-idle: avg frame time 17ms 0ms 0.0%
large-graph-idle: layout duration 0ms 0ms 0.0%
large-graph-idle: style recalc duration 12ms 1ms 8.6%
large-graph-idle: layout count 0 0 0.0%
large-graph-idle: style recalc count 12 0 2.7%
large-graph-idle: task duration 542ms 54ms 10.0%
large-graph-idle: script duration 102ms 11ms 10.3%
large-graph-idle: TBT 0ms 0ms 0.0%
large-graph-idle: DOM nodes 25 1 3.7%
large-graph-idle: event listeners 26 6 23.2%
large-graph-pan: avg frame time 17ms 0ms 0.0%
large-graph-pan: layout duration 0ms 0ms 0.0%
large-graph-pan: style recalc duration 17ms 1ms 4.6%
large-graph-pan: layout count 0 0 0.0%
large-graph-pan: style recalc count 70 1 0.9%
large-graph-pan: task duration 1082ms 43ms 4.0%
large-graph-pan: script duration 408ms 20ms 4.8%
large-graph-pan: TBT 0ms 0ms 0.0%
large-graph-pan: DOM nodes 19 2 8.7%
large-graph-pan: event listeners 5 1 16.8%
minimap-idle: avg frame time 17ms 0ms 0.0%
minimap-idle: layout duration 0ms 0ms 0.0%
minimap-idle: style recalc duration 10ms 1ms 8.6%
minimap-idle: layout count 0 0 0.0%
minimap-idle: style recalc count 10 1 7.1%
minimap-idle: task duration 527ms 47ms 9.0%
minimap-idle: script duration 98ms 10ms 10.1%
minimap-idle: TBT 0ms 0ms 0.0%
minimap-idle: DOM nodes 19 1 7.1%
minimap-idle: event listeners 5 1 14.4%
subgraph-dom-widget-clipping: avg frame time 17ms 0ms 0.0%
subgraph-dom-widget-clipping: layout duration 0ms 0ms 0.0%
subgraph-dom-widget-clipping: style recalc duration 13ms 1ms 7.4%
subgraph-dom-widget-clipping: layout count 0 0 0.0%
subgraph-dom-widget-clipping: style recalc count 48 1 1.2%
subgraph-dom-widget-clipping: task duration 378ms 18ms 4.9%
subgraph-dom-widget-clipping: script duration 128ms 6ms 4.9%
subgraph-dom-widget-clipping: TBT 0ms 0ms 0.0%
subgraph-dom-widget-clipping: DOM nodes 22 1 5.0%
subgraph-dom-widget-clipping: event listeners 16 6 36.0%
subgraph-idle: avg frame time 17ms 0ms 0.0%
subgraph-idle: layout duration 0ms 0ms 0.0%
subgraph-idle: style recalc duration 10ms 1ms 7.5%
subgraph-idle: layout count 0 0 0.0%
subgraph-idle: style recalc count 11 1 6.0%
subgraph-idle: task duration 370ms 31ms 8.5%
subgraph-idle: script duration 20ms 3ms 13.2%
subgraph-idle: TBT 0ms 0ms 0.0%
subgraph-idle: DOM nodes 22 1 6.9%
subgraph-idle: event listeners 10 7 64.5%
subgraph-mouse-sweep: avg frame time 17ms 0ms 0.0%
subgraph-mouse-sweep: layout duration 5ms 0ms 6.8%
subgraph-mouse-sweep: style recalc duration 42ms 3ms 7.8%
subgraph-mouse-sweep: layout count 16 0 0.0%
subgraph-mouse-sweep: style recalc count 80 2 2.4%
subgraph-mouse-sweep: task duration 766ms 69ms 9.0%
subgraph-mouse-sweep: script duration 101ms 7ms 6.5%
subgraph-mouse-sweep: TBT 0ms 0ms 0.0%
subgraph-mouse-sweep: DOM nodes 67 2 3.3%
subgraph-mouse-sweep: event listeners 8 4 52.6%
workflow-execution: avg frame time 17ms 0ms 0.0%
workflow-execution: layout duration 2ms 0ms 9.4%
workflow-execution: style recalc duration 24ms 2ms 9.1%
workflow-execution: layout count 5 1 11.0%
workflow-execution: style recalc count 18 2 11.5%
workflow-execution: task duration 123ms 11ms 8.8%
workflow-execution: script duration 29ms 3ms 10.2%
workflow-execution: TBT 0ms 0ms 0.0%
workflow-execution: DOM nodes 161 7 4.4%
workflow-execution: event listeners 52 4 8.4%
Trend (last 15 commits on main)
Metric Trend Dir Latest
canvas-idle: avg frame time ▆▃▆▁▆▃▆█▆▆▄▃▃▄▃ ➡️ 17ms
canvas-idle: p95 frame time ➡️ NaNms
canvas-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-idle: style recalc duration ▇▇▆▆▃█▄▃▄▃▇▄▁▆▇ ➡️ 11ms
canvas-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
canvas-idle: style recalc count █▃▅▂▅▆▃▁▂▁▂▅▆▅▆ ➡️ 12
canvas-idle: task duration ▃▃▃▆▂▃▃▅▆▂█▃▁▃▃ ➡️ 391ms
canvas-idle: script duration ▄▃▅▇▂▅▃▆▇▅█▄▁▅▆ ➡️ 27ms
canvas-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-idle: heap used ➡️ NaN MB
canvas-idle: DOM nodes █▇▆▅▃▇▃▁▂▂▅▆▆▆▇ ➡️ 24
canvas-idle: event listeners ▅█▅▄▁▅▁▁▁▄▅▅▁▅▄ 📉 11
canvas-mouse-sweep: avg frame time ▆█▆▃▁▃▁▆▆▁▃▆▆▃▃ ➡️ 17ms
canvas-mouse-sweep: p95 frame time ➡️ NaNms
canvas-mouse-sweep: layout duration ▁▃▂▄▁▂▁▃▆▂█▇▆▄▃ ➡️ 4ms
canvas-mouse-sweep: style recalc duration ▄▄▂▄▁▂▃▃▅▄█▆▂▄▄ ➡️ 43ms
canvas-mouse-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 12
canvas-mouse-sweep: style recalc count █▅▄▃▂▂▁▄▄▅▆▅▂▇▄ ➡️ 79
canvas-mouse-sweep: task duration █▆▄▂▂▃▂▄▄▅█▆▁▆▄ ➡️ 868ms
canvas-mouse-sweep: script duration ▄▅▄▆▄▆▆▆▅▅█▆▁▅▆ ➡️ 139ms
canvas-mouse-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-mouse-sweep: heap used ➡️ NaN MB
canvas-mouse-sweep: DOM nodes █▅▃▃▁▂▂▃▂▄▆▅▃▅▅ ➡️ 64
canvas-mouse-sweep: event listeners █▁▁▁▁▁▇▁▁▁██▇▁█ 📈 13
canvas-zoom-sweep: avg frame time ▅▅█▄▅▁▁▁▅▁▁▅▄▅▁ ➡️ 17ms
canvas-zoom-sweep: p95 frame time ➡️ NaNms
canvas-zoom-sweep: layout duration ▆▅▅▄▁▁█▅▃▅▇▆▁▂▆ ➡️ 1ms
canvas-zoom-sweep: style recalc duration ▆▅▄▆▅▃█▆▇▅▇▄▁▃▅ ➡️ 20ms
canvas-zoom-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 6
canvas-zoom-sweep: style recalc count ▁▁▃▄▆▃▆█▄▄▆▁▆▁▆ ➡️ 32
canvas-zoom-sweep: task duration ▄▂▁▇▂▂▄▅▆▃█▄▁▁▅ ➡️ 338ms
canvas-zoom-sweep: script duration ▃▃▂▇▂▂▅▇▆▅█▄▁▂▆ ➡️ 30ms
canvas-zoom-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
canvas-zoom-sweep: heap used ➡️ NaN MB
canvas-zoom-sweep: DOM nodes ▄▃▁▅█▁▃▆▄▅▅▃▃▄▃ ➡️ 79
canvas-zoom-sweep: event listeners ▁▁▂▅█▂▁▅▁▅▅▄▁▅▁ ➡️ 19
dom-widget-clipping: avg frame time ▂▄▅▅▂▄█▇▅▇▇▅▅▁▇ ➡️ 17ms
dom-widget-clipping: p95 frame time ➡️ NaNms
dom-widget-clipping: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
dom-widget-clipping: style recalc duration ▆▆▂▆▄▃██▄▁▆▇▆▃▅ ➡️ 10ms
dom-widget-clipping: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
dom-widget-clipping: style recalc count ▇█▅█▅▄█▇▇▁▇▄▇▂▅ ➡️ 13
dom-widget-clipping: task duration ▃▃▁▅▄▃▅▆▅▂▇█▁▅▅ ➡️ 371ms
dom-widget-clipping: script duration ▅▄▄▆▆▅▇▇▆▃█▇▁▇▇ ➡️ 71ms
dom-widget-clipping: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
dom-widget-clipping: heap used ➡️ NaN MB
dom-widget-clipping: DOM nodes ▇▇▄▇▅▄█▇▅▁▅▄▇▃▄ ➡️ 21
dom-widget-clipping: event listeners ▅▅▅▅▁▅██▁▁▁▁█▁▁ 📉 2
large-graph-idle: avg frame time ▅▅▅▅▅▂▁▂▄▅▄▂▂▅█ ➡️ 17ms
large-graph-idle: p95 frame time ➡️ NaNms
large-graph-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-idle: style recalc duration ▅▅▅▆▄▅▃▄▅▅▆█▁▄▆ ➡️ 13ms
large-graph-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
large-graph-idle: style recalc count █▆█▃▃▁▃▆▃▆▆▃▆██ ➡️ 12
large-graph-idle: task duration ▂▃▂▆▂▃▃▇▅▃██▁▂▅ ➡️ 569ms
large-graph-idle: script duration ▄▅▄▆▄▅▅▇▆▅█▆▁▃▆ ➡️ 110ms
large-graph-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-idle: heap used ➡️ NaN MB
large-graph-idle: DOM nodes ▆█▅▂▅▃▁▂▃▅▅▆▂▆▅ ➡️ 25
large-graph-idle: event listeners ███▇██▄▁▄▇▇█▂█▇ ➡️ 29
large-graph-pan: avg frame time ▆▃▃▆█▃▁█▆▆▆▆█▁▆ ➡️ 17ms
large-graph-pan: p95 frame time ➡️ NaNms
large-graph-pan: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-pan: style recalc duration ▃▂▄▄▁▅▂▂▁▄▄█▃▁▂ ➡️ 17ms
large-graph-pan: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
large-graph-pan: style recalc count ▆▃█▂▃▂▂▂▁▇▅▃█▆▃ ➡️ 69
large-graph-pan: task duration ▄▃▄▆▄▄▄▆▄▄█▆▁▂▅ ➡️ 1100ms
large-graph-pan: script duration ▅▄▅▆▆▅▄▆▄▅█▄▁▄▅ ➡️ 413ms
large-graph-pan: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
large-graph-pan: heap used ➡️ NaN MB
large-graph-pan: DOM nodes ▅▃▆▂▄▁▃▁▁▅▁▂█▅▂ ➡️ 18
large-graph-pan: event listeners █▆█▁▁▆▁▁▃▆▁▃██▃ ➡️ 5
minimap-idle: avg frame time ▃▆▆▃█▁█▆▆▃▃▆█▆█ ➡️ 17ms
minimap-idle: p95 frame time ➡️ NaNms
minimap-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
minimap-idle: style recalc duration ▄█▁█▅▅█▅▅▃▅▁▁▄▆ ➡️ 10ms
minimap-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
minimap-idle: style recalc count ▃▅▂▄█▃▆▁▂▅▂▁▅▆▃ ➡️ 9
minimap-idle: task duration ▃▄▁▅▁▃▄▅▇▃█▅▁▁▅ ➡️ 547ms
minimap-idle: script duration ▄▆▃▇▃▅▆▆▇▅█▅▁▃▆ ➡️ 106ms
minimap-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
minimap-idle: heap used ➡️ NaN MB
minimap-idle: DOM nodes ▃▅▂▄█▃▆▁▂▅▂▁▅▆▃ ➡️ 19
minimap-idle: event listeners ▃▃▆▁▁▁▃▁▁▆▁▃█▆▁ ➡️ 4
subgraph-dom-widget-clipping: avg frame time ▅▄▄▄▄▄█▄▄▄▃▁▆▃▃ ➡️ 17ms
subgraph-dom-widget-clipping: p95 frame time ➡️ NaNms
subgraph-dom-widget-clipping: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-dom-widget-clipping: style recalc duration ▂▄▃▅▅▃▂▅▇▃▄█▁▄▆ ➡️ 14ms
subgraph-dom-widget-clipping: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
subgraph-dom-widget-clipping: style recalc count ▇█▆▃▆▃▁▆█▇▃▆▇█▅ ➡️ 48
subgraph-dom-widget-clipping: task duration ▂▃▃▆▅▅▂▅█▂▆█▁▂▇ ➡️ 398ms
subgraph-dom-widget-clipping: script duration ▃▃▃▄▅▅▂▄█▂▅▇▁▂▅ ➡️ 131ms
subgraph-dom-widget-clipping: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-dom-widget-clipping: heap used ➡️ NaN MB
subgraph-dom-widget-clipping: DOM nodes ▅▇▅▂▅▂▁▅▅▅▁▇▅█▄ ➡️ 22
subgraph-dom-widget-clipping: event listeners ▅▅▅▂▅▁▅██▁▁█▅█▅ 📈 16
subgraph-idle: avg frame time ▆▆█▁▆▃▆▆▆▃▆▁▃▆█ ➡️ 17ms
subgraph-idle: p95 frame time ➡️ NaNms
subgraph-idle: layout duration ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-idle: style recalc duration ▁▇▃▆▂▄▂▃▃▆▆▄▃▇█ ➡️ 12ms
subgraph-idle: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0
subgraph-idle: style recalc count ▃▆▃▃▂▅▁▂▁▆▃▃██▇ ➡️ 12
subgraph-idle: task duration ▁▃▁▇▁▁▃▆▅▂█▅▁▁▄ ➡️ 378ms
subgraph-idle: script duration ▁▃▂▇▁▂▃▇▆▂█▅▂▁▅ ➡️ 22ms
subgraph-idle: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-idle: heap used ➡️ NaN MB
subgraph-idle: DOM nodes ▃▅▃▂▁▄▁▂▁▅▃▂▇█▇ ➡️ 24
subgraph-idle: event listeners ▁▅▁▁▁▁▁▁▁▅▄▁███ 📈 21
subgraph-mouse-sweep: avg frame time ▅▄▁▃▃▄▆▄▆▃▃█▁▃▃ ➡️ 17ms
subgraph-mouse-sweep: p95 frame time ➡️ NaNms
subgraph-mouse-sweep: layout duration ▁▄▄▄▃▃▅▅▅▂█▇▂▃▆ ➡️ 5ms
subgraph-mouse-sweep: style recalc duration ▃▂▄▅▂▃▄▅█▃█▆▁▂▅ ➡️ 43ms
subgraph-mouse-sweep: layout count ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 16
subgraph-mouse-sweep: style recalc count ▅▂▅▅▁▄▃▅█▅▆▄▂▄▅ ➡️ 81
subgraph-mouse-sweep: task duration ▃▂▄▅▂▄▄▅▇▄█▆▁▃▅ ➡️ 785ms
subgraph-mouse-sweep: script duration ▄▅▄▇▅▅▆▇▆▅██▁▄▆ ➡️ 105ms
subgraph-mouse-sweep: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
subgraph-mouse-sweep: heap used ➡️ NaN MB
subgraph-mouse-sweep: DOM nodes ▅▁▄▅▁▄▃▃█▅▅▄▂▅▃ ➡️ 66
subgraph-mouse-sweep: event listeners ▇▁▂▇▁▂▂▂█▇▂▂▇▇▂ 📈 5
workflow-execution: avg frame time ▆▆▆▄▆▆▃▄▁▄█▆▅▄▆ ➡️ 17ms
workflow-execution: p95 frame time ➡️ NaNms
workflow-execution: layout duration ▁▆▁▃▂▄▃▂▃▃▅█▄▂▅ ➡️ 2ms
workflow-execution: style recalc duration ▃▇▅▇▁▅▆▇█▁██▂▄▆ ➡️ 25ms
workflow-execution: layout count ▁█▂▃▂▃▃▁▃▃▄▃▂▃▂ ➡️ 5
workflow-execution: style recalc count ▃█▅▇▁▄▅▆▅▅▅▅▄▄▂ ➡️ 15
workflow-execution: task duration ▂▅▄▅▁▄▆▆▆▁▇█▁▃▃ ➡️ 120ms
workflow-execution: script duration ▄▃▄▄▃▅▄▅▆▂▇█▁▃▄ ➡️ 29ms
workflow-execution: TBT ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ➡️ 0ms
workflow-execution: heap used ➡️ NaN MB
workflow-execution: DOM nodes ▂█▃▆▁▄▃▅▃█▃▃▄▃▁ ➡️ 152
workflow-execution: event listeners ▅███▁▅███▁██▅█▅ ➡️ 49
Raw data
{
  "timestamp": "2026-07-18T13:40:55.857Z",
  "gitSha": "d634452fdeea05ee4f1f3d3a0cfb04ccde222f5d",
  "branch": "matt/be-2256-locate-node-button",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2095.47299999997,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 10.735000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 421.929,
      "heapDeltaBytes": 3865444,
      "heapUsedBytes": 72673172,
      "domNodes": 20,
      "jsHeapTotalBytes": 19939328,
      "scriptDurationMs": 18.289,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "canvas-idle",
      "durationMs": 2044.5130000000518,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 7.5729999999999995,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 420.813,
      "heapDeltaBytes": -20161300,
      "heapUsedBytes": 48703632,
      "domNodes": -264,
      "jsHeapTotalBytes": 19542016,
      "scriptDurationMs": 17.376999999999995,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1990.6330000000025,
      "styleRecalcs": 79,
      "styleRecalcDurationMs": 45.161,
      "layouts": 12,
      "layoutDurationMs": 4.899000000000001,
      "taskDurationMs": 961.0730000000001,
      "heapDeltaBytes": -14987060,
      "heapUsedBytes": 53735644,
      "domNodes": -266,
      "jsHeapTotalBytes": 20066304,
      "scriptDurationMs": 134.77100000000002,
      "eventListeners": -131,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1758.232000000021,
      "styleRecalcs": 74,
      "styleRecalcDurationMs": 35.917,
      "layouts": 12,
      "layoutDurationMs": 3.377,
      "taskDurationMs": 809.302,
      "heapDeltaBytes": -15239556,
      "heapUsedBytes": 53728400,
      "domNodes": -264,
      "jsHeapTotalBytes": 19279872,
      "scriptDurationMs": 113.432,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1756.0849999999846,
      "styleRecalcs": 31,
      "styleRecalcDurationMs": 18.128,
      "layouts": 6,
      "layoutDurationMs": 0.665,
      "taskDurationMs": 318.988,
      "heapDeltaBytes": 7113164,
      "heapUsedBytes": 75873020,
      "domNodes": 79,
      "jsHeapTotalBytes": 20201472,
      "scriptDurationMs": 18.664,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1724.2149999999583,
      "styleRecalcs": 30,
      "styleRecalcDurationMs": 14.903999999999998,
      "layouts": 6,
      "layoutDurationMs": 0.5760000000000001,
      "taskDurationMs": 300.614,
      "heapDeltaBytes": 7241880,
      "heapUsedBytes": 76255572,
      "domNodes": 77,
      "jsHeapTotalBytes": 19939328,
      "scriptDurationMs": 17.858,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 528.6459999999806,
      "styleRecalcs": 13,
      "styleRecalcDurationMs": 8.953000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 333.69599999999997,
      "heapDeltaBytes": -11700752,
      "heapUsedBytes": 57210420,
      "domNodes": 22,
      "jsHeapTotalBytes": 19677184,
      "scriptDurationMs": 53.349999999999994,
      "eventListeners": 0,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 596.4099999999917,
      "styleRecalcs": 12,
      "styleRecalcDurationMs": 9.001999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 351.264,
      "heapDeltaBytes": -11728088,
      "heapUsedBytes": 57123032,
      "domNodes": 20,
      "jsHeapTotalBytes": 20201472,
      "scriptDurationMs": 55.523999999999994,
      "eventListeners": 0,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2015.8899999999562,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 7.268,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 529.477,
      "heapDeltaBytes": 4803376,
      "heapUsedBytes": 64140592,
      "domNodes": -270,
      "jsHeapTotalBytes": 5455872,
      "scriptDurationMs": 79.997,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2032.6669999999467,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 8.838000000000003,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 533.878,
      "heapDeltaBytes": 5337956,
      "heapUsedBytes": 66637916,
      "domNodes": -264,
      "jsHeapTotalBytes": 5193728,
      "scriptDurationMs": 80.119,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2153.3980000000383,
      "styleRecalcs": 68,
      "styleRecalcDurationMs": 14.755999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1083.57,
      "heapDeltaBytes": -4648316,
      "heapUsedBytes": 55587304,
      "domNodes": -271,
      "jsHeapTotalBytes": 4669440,
      "scriptDurationMs": 369.369,
      "eventListeners": -127,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2173.283999999967,
      "styleRecalcs": 69,
      "styleRecalcDurationMs": 18.795,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1054.7759999999998,
      "heapDeltaBytes": 1376900,
      "heapUsedBytes": 61760912,
      "domNodes": -269,
      "jsHeapTotalBytes": 5660672,
      "scriptDurationMs": 367.259,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3147.570999999971,
      "styleRecalcs": 65,
      "styleRecalcDurationMs": 15.347000000000003,
      "layouts": 60,
      "layoutDurationMs": 8.328999999999999,
      "taskDurationMs": 1334.488,
      "heapDeltaBytes": -5405052,
      "heapUsedBytes": 56223500,
      "domNodes": -273,
      "jsHeapTotalBytes": 7553024,
      "scriptDurationMs": 478.58500000000004,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3134.5199999999522,
      "styleRecalcs": 65,
      "styleRecalcDurationMs": 14.928999999999998,
      "layouts": 60,
      "layoutDurationMs": 7.968000000000001,
      "taskDurationMs": 1295.2359999999999,
      "heapDeltaBytes": -5254872,
      "heapUsedBytes": 56275320,
      "domNodes": -273,
      "jsHeapTotalBytes": 8339456,
      "scriptDurationMs": 464.99099999999993,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 2002.9139999999757,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 7.644000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 541.144,
      "heapDeltaBytes": 5075572,
      "heapUsedBytes": 65878164,
      "domNodes": -268,
      "jsHeapTotalBytes": 5193728,
      "scriptDurationMs": 82.94200000000001,
      "eventListeners": -129,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "minimap-idle",
      "durationMs": 2014.8299999999608,
      "styleRecalcs": 8,
      "styleRecalcDurationMs": 6.284999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 517.569,
      "heapDeltaBytes": 4913948,
      "heapUsedBytes": 66226708,
      "domNodes": -269,
      "jsHeapTotalBytes": 5193728,
      "scriptDurationMs": 77.917,
      "eventListeners": -127,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 573.0280000000221,
      "styleRecalcs": 47,
      "styleRecalcDurationMs": 10.887999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 361.59200000000004,
      "heapDeltaBytes": -11441764,
      "heapUsedBytes": 57534136,
      "domNodes": 20,
      "jsHeapTotalBytes": 21250048,
      "scriptDurationMs": 121.96499999999999,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 588.0110000000514,
      "styleRecalcs": 48,
      "styleRecalcDurationMs": 11.559,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 384.82300000000004,
      "heapDeltaBytes": -11482488,
      "heapUsedBytes": 57494956,
      "domNodes": 22,
      "jsHeapTotalBytes": 20725760,
      "scriptDurationMs": 126.75799999999998,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2004.9450000000206,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 8.41,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 400.078,
      "heapDeltaBytes": -18990376,
      "heapUsedBytes": 49936424,
      "domNodes": -267,
      "jsHeapTotalBytes": 19279872,
      "scriptDurationMs": 13.908999999999999,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2022.4719999999934,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 7.4590000000000005,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 404.28200000000004,
      "heapDeltaBytes": -20447368,
      "heapUsedBytes": 48312076,
      "domNodes": -266,
      "jsHeapTotalBytes": 20066304,
      "scriptDurationMs": 13.866,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1706.8070000000262,
      "styleRecalcs": 76,
      "styleRecalcDurationMs": 37.80799999999999,
      "layouts": 16,
      "layoutDurationMs": 4.4670000000000005,
      "taskDurationMs": 648.395,
      "heapDeltaBytes": -5201908,
      "heapUsedBytes": 63684456,
      "domNodes": 62,
      "jsHeapTotalBytes": 19677184,
      "scriptDurationMs": 87.103,
      "eventListeners": 4,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1731.1019999999644,
      "styleRecalcs": 77,
      "styleRecalcDurationMs": 37.650000000000006,
      "layouts": 16,
      "layoutDurationMs": 4.171,
      "taskDurationMs": 713.3530000000001,
      "heapDeltaBytes": -18988440,
      "heapUsedBytes": 49988304,
      "domNodes": -263,
      "jsHeapTotalBytes": 21377024,
      "scriptDurationMs": 91.274,
      "eventListeners": -133,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "subgraph-transition-enter",
      "durationMs": 932.3010000000522,
      "styleRecalcs": 19,
      "styleRecalcDurationMs": 29.788999999999994,
      "layouts": 15,
      "layoutDurationMs": 13.205000000000002,
      "taskDurationMs": 729.4019999999999,
      "heapDeltaBytes": 1302212,
      "heapUsedBytes": 83290392,
      "domNodes": 13673,
      "jsHeapTotalBytes": 12058624,
      "scriptDurationMs": 27.03900000000001,
      "eventListeners": 2369,
      "totalBlockingTimeMs": 127,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8169.573999999955,
      "styleRecalcs": 250,
      "styleRecalcDurationMs": 42.077000000000005,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3669.6850000000004,
      "heapDeltaBytes": 16802304,
      "heapUsedBytes": 78138704,
      "domNodes": -265,
      "jsHeapTotalBytes": 8282112,
      "scriptDurationMs": 1225.357,
      "eventListeners": -113,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8207.194000000072,
      "styleRecalcs": 251,
      "styleRecalcDurationMs": 43.623,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3606.973,
      "heapDeltaBytes": 17090212,
      "heapUsedBytes": 77956092,
      "domNodes": -265,
      "jsHeapTotalBytes": 6447104,
      "scriptDurationMs": 1155.961,
      "eventListeners": -113,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 13860.964000000024,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 13843.328000000001,
      "heapDeltaBytes": -41939608,
      "heapUsedBytes": 158775364,
      "domNodes": -8311,
      "jsHeapTotalBytes": -7802880,
      "scriptDurationMs": 529.938,
      "eventListeners": -16384,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.77333333333336,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 13427.010999999993,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 13413.680000000002,
      "heapDeltaBytes": -56388700,
      "heapUsedBytes": 169677900,
      "domNodes": -8311,
      "jsHeapTotalBytes": -9637888,
      "scriptDurationMs": 523.531,
      "eventListeners": -16384,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.220000000000073,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 17179.892999999993,
      "styleRecalcs": 110,
      "styleRecalcDurationMs": 17.054999999999986,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 17155.534,
      "heapDeltaBytes": -47577552,
      "heapUsedBytes": 180805544,
      "domNodes": -8311,
      "jsHeapTotalBytes": -10248192,
      "scriptDurationMs": 867.3839999999999,
      "eventListeners": -16380,
      "totalBlockingTimeMs": 164,
      "frameDurationMs": 17.219999999999953,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 16636.761999999977,
      "styleRecalcs": 103,
      "styleRecalcDurationMs": 15.490999999999977,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 16612.234,
      "heapDeltaBytes": -43664612,
      "heapUsedBytes": 165444192,
      "domNodes": -8311,
      "jsHeapTotalBytes": -14356480,
      "scriptDurationMs": 907.463,
      "eventListeners": -16382,
      "totalBlockingTimeMs": 9,
      "frameDurationMs": 17.223333333333358,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "workflow-execution",
      "durationMs": 449.75299999998697,
      "styleRecalcs": 13,
      "styleRecalcDurationMs": 19.453000000000007,
      "layouts": 2,
      "layoutDurationMs": 0.456,
      "taskDurationMs": 123.64100000000002,
      "heapDeltaBytes": -15720648,
      "heapUsedBytes": 52452828,
      "domNodes": 130,
      "jsHeapTotalBytes": 6045696,
      "scriptDurationMs": 13.353,
      "eventListeners": 67,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "workflow-execution",
      "durationMs": 492.6259999999729,
      "styleRecalcs": 13,
      "styleRecalcDurationMs": 20.607,
      "layouts": 3,
      "layoutDurationMs": 0.7279999999999999,
      "taskDurationMs": 125.47500000000001,
      "heapDeltaBytes": -16601908,
      "heapUsedBytes": 51238960,
      "domNodes": 119,
      "jsHeapTotalBytes": 7356416,
      "scriptDurationMs": 10.469000000000001,
      "eventListeners": 49,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    }
  ]
}

@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 @mattmillerai.

✅ No high-signal findings.

Panel: 8/8 reviewers contributed findings.

@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...omponents/rightSidePanel/errors/ErrorGroupList.vue 50.00% 1 Missing ⚠️
...components/rightSidePanel/errors/ErrorNodeCard.vue 83.33% 1 Missing ⚠️
@@            Coverage Diff             @@
##             main   #13401      +/-   ##
==========================================
- Coverage   78.65%   77.81%   -0.84%     
==========================================
  Files        1683     1687       +4     
  Lines       98357    95618    -2739     
  Branches    34800    33646    -1154     
==========================================
- Hits        77364    74409    -2955     
- Misses      20526    20775     +249     
+ Partials      467      434      -33     
Flag Coverage Δ
unit 67.29% <85.71%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...ponents/rightSidePanel/errors/LocateNodeButton.vue 100.00% <100.00%> (ø)
...ents/rightSidePanel/errors/MissingPackGroupRow.vue 99.13% <100.00%> (+4.03%) ⬆️
...omponents/rightSidePanel/errors/ErrorGroupList.vue 88.23% <50.00%> (+0.54%) ⬆️
...components/rightSidePanel/errors/ErrorNodeCard.vue 97.53% <83.33%> (+8.75%) ⬆️

... and 181 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.

Deduplicate the byte-identical locate icon-button repeated across four
sites in the errors panel (ErrorNodeCard, TabErrors, MissingPackGroupRow
x2) into a single LocateNodeButton component. Standardizes the decorative
icon's aria-hidden and the click .stop modifier, which previously varied
between sites.
@mattmillerai
mattmillerai force-pushed the matt/be-2256-locate-node-button branch from 4638b2c to 5c32def Compare July 8, 2026 20:39
@mattmillerai

Copy link
Copy Markdown
Contributor Author

Rebased onto main to resolve the merge conflict in TabErrors.vue. Since main extracted the error-group markup into ErrorGroupList.vue, the fourth LocateNodeButton call site moved there — the extraction now applies to ErrorGroupList, ErrorNodeCard, and MissingPackGroupRow (x2). Typecheck, lint, format, and the errors-panel unit tests pass locally.

Comment thread src/components/rightSidePanel/errors/LocateNodeButton.test.ts
Comment thread src/components/rightSidePanel/errors/MissingPackGroupRow.vue
Comment thread src/components/rightSidePanel/errors/LocateNodeButton.vue
Comment thread src/components/rightSidePanel/errors/LocateNodeButton.test.ts Outdated
Comment thread src/components/rightSidePanel/errors/LocateNodeButton.test.ts
Comment thread src/components/rightSidePanel/errors/LocateNodeButton.test.ts Outdated
Comment thread src/components/rightSidePanel/errors/LocateNodeButton.vue
Comment thread src/components/rightSidePanel/errors/LocateNodeButton.test.ts
Comment thread src/components/rightSidePanel/errors/MissingPackGroupRow.vue
mattmillerai and others added 2 commits July 13, 2026 22:21
…cate labels

- Replace closure-captured counter with vi.fn() spy in the click-propagation
  test so it actually fails when @click.stop is removed
- Add keyboard-activation coverage and pin aria-label via DOM assertion
- Give each MissingPackGroupRow locate button a distinct accessible name
  via locateNodeFor, matching ErrorGroupList (WCAG 2.4.6)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 14, 2026
The LocateNodeButton extraction switched the locate button aria-label
from the static "Locate node on canvas" to the per-item
`rightSidePanel.locateNodeFor` ("Locate {item}"), but these test queries
were not updated, so they failed to find the button.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@mattmillerai

Copy link
Copy Markdown
Contributor Author

Fixed the failing MissingPackGroupRow.test.ts unit tests. The LocateNodeButton extraction switched the locate button's aria-label from the static "Locate node on canvas" to the per-item rightSidePanel.locateNodeFor ("Locate {item}"), but the test's i18n mock and role queries still expected the old label. Updated the mock key and queries to the resolved per-item names (e.g. "Locate OnlyNode", "Locate MissingA"); all 30 tests pass locally.

…ange

The extracted LocateNodeButton now carries a per-item accessible name
("Locate {item}"), so getByRole('button', { name }) matched both the row
label button and the locate button, tripping Playwright strict mode. Use
exact matching to target the row label button.
@mattmillerai

Copy link
Copy Markdown
Contributor Author

Fixed the failing errorsTabMissingNodes e2e shard: extracting LocateNodeButton gave the locate button a per-item accessible name (Locate {item}), so getByRole('button', { name }) matched both the row-label button and the locate button and tripped Playwright strict mode. Updated those locators to use exact: true (c6fbac4).

…ode-button

# Conflicts:
#	src/components/rightSidePanel/errors/ErrorGroupList.vue
@mattmillerai

Copy link
Copy Markdown
Contributor Author

Merged latest main to resolve the conflict in ErrorGroupList.vue. The conflict was between this PR's LocateNodeButton extraction and #13684's escapeParameter: false fix on the locate aria-label; resolved by keeping the extracted component and passing escapeParameter: false into its label. For consistency I also applied escapeParameter: false to the two MissingPackGroupRow locate labels (same raw-node-name → aria-label double-escape path). All errors-panel unit tests pass locally (158), including main's new special-character assertions.

@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: 2

🤖 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 `@src/components/rightSidePanel/errors/ErrorNodeCard.vue`:
- Around line 39-42: Update the LocateNodeButton label in ErrorNodeCard to use
the node-specific rightSidePanel.locateNodeFor translation with card.nodeTitle
or card.title, plus a safe fallback when both are unavailable. Add an
integration assertion verifying each error card’s locate button exposes the
expected node-specific accessible name.

In `@src/components/rightSidePanel/errors/MissingPackGroupRow.test.ts`:
- Line 165: Strengthen the negative assertions in MissingPackGroupRow tests
around the resolving and non-locatable rows: verify that no locate action button
is rendered for the relevant row, rather than only checking that the “Locate
OnlyNode” label is absent. Apply the same absence or expected-count assertion to
the additional cases at the referenced assertions.
🪄 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: f3f924e3-f157-4d33-bf49-1a74bf664cd6

📥 Commits

Reviewing files that changed from the base of the PR and between 20258fe and 24f7bbd.

📒 Files selected for processing (7)
  • browser_tests/tests/propertiesPanel/errorsTabMissingNodes.spec.ts
  • src/components/rightSidePanel/errors/ErrorGroupList.vue
  • src/components/rightSidePanel/errors/ErrorNodeCard.vue
  • src/components/rightSidePanel/errors/LocateNodeButton.test.ts
  • src/components/rightSidePanel/errors/LocateNodeButton.vue
  • src/components/rightSidePanel/errors/MissingPackGroupRow.test.ts
  • src/components/rightSidePanel/errors/MissingPackGroupRow.vue

Comment thread src/components/rightSidePanel/errors/ErrorNodeCard.vue Outdated
Comment thread src/components/rightSidePanel/errors/MissingPackGroupRow.test.ts
Use rightSidePanel.locateNodeFor with the card node title (safe fallback to
generic label) so runtime error cards expose distinguishable locate buttons.
Strengthen MissingPackGroupRow negative assertions to check locate-button
count, not only a specific label's absence.

@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 (8 agents). The extraction is clean: .stop propagation is safe (Button declares no click emit so the modifier attaches a native DOM listener), aria-label forwarding through Reka UI's Primitive is confirmed, all four call sites wire @locate correctly, no regression on the prior double-escape fix, and locateNodeFor exists in all 10 locale files. Two test quality gaps below.

Comment thread src/components/rightSidePanel/errors/LocateNodeButton.test.ts
Comment thread src/components/rightSidePanel/errors/LocateNodeButton.test.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-coded Opened by the agent-work code loop cursor-review Trigger multi-model Cursor agent review on this PR size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants