Skip to content

test: Curve Widget E2E Test Plan#10837

Open
kaili-yang wants to merge 1 commit intomainfrom
test/curve-widget-E2E-test-plan
Open

test: Curve Widget E2E Test Plan#10837
kaili-yang wants to merge 1 commit intomainfrom
test/curve-widget-E2E-test-plan

Conversation

@kaili-yang
Copy link
Copy Markdown
Collaborator

@kaili-yang kaili-yang commented Apr 3, 2026

Summary

test: Curve Widget E2E Test Plan

  1. Rendering & Defaults
  2. Control Point Manipulation
  3. Dragging & Geometry
  4. Interactive States
  5. Final Validation(Visual Regression& Edge Cases)

┆Issue is synchronized with this Notion page by Unito

@kaili-yang kaili-yang requested a review from a team April 3, 2026 08:22
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Apr 3, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 3, 2026

📝 Walkthrough

Walkthrough

This pull request introduces comprehensive test infrastructure for a new Curve widget feature. It adds test assets, a helper class for Playwright-based widget interactions, fixture updates to support curve widget testing, and an extensive E2E test suite covering widget functionality including point manipulation, interpolation, and state management.

Changes

Cohort / File(s) Summary
Test Asset
browser_tests/assets/vueNodes/widgets/curve_widget.json
New Vue node graph JSON defining a CLIPTextEncode node titled "Curve" for testing curve widget functionality.
Widget Helper
browser_tests/fixtures/helpers/CurveWidgetHelper.ts
New Playwright helper class providing methods to interact with SVG curve widgets: clickAt, dragPoint, rightClickPoint, and getCurveData for coordinate translation, point dragging, and data extraction.
Test Fixtures
browser_tests/fixtures/ComfyPage.ts
Added curveWidget fixture to locate and initialize curve widgets; updated setupUser and createUser signatures to return Promise<string> with improved user creation logic handling duplicate username errors via randomization.
Test Suite
browser_tests/tests/vueNodes/widgets/curve/curveWidget.spec.ts
New E2E test suite validating curve widget rendering, point addition via click, drag mechanics with clamping, interpolation switching (Smooth/Linear), deletion semantics, disabled states, and persistence across workflow reloads.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A curve so smooth, with points that dance,
Dragging left and dragging right,
SVG paths in perfect prance,
Tests ensure the widget's flight!
Linear, smooth—we hop with cheer,

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description is incomplete. It lists test plan sections but lacks the structured template sections (What, Breaking changes, Dependencies, Review Focus) and detailed explanations of the changes. Expand the description to follow the repository template: add a proper 'What' section explaining the core test functionality, clarify any breaking changes or dependencies, and detail critical design decisions or edge cases for reviewers.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding comprehensive end-to-end tests for the Curve Widget with multiple test coverage areas.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
End-To-End Regression Coverage For Fixes ✅ Passed PR title and commits lack bug-fix language, and multiple files under browser_tests/ are changed.
Adr Compliance For Entity/Litegraph Changes ✅ Passed All changed files are in browser_tests/ directory; none are in src/lib/litegraph/, src/ecs/, or graph entity source paths.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/curve-widget-E2E-test-plan

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

🎨 Storybook: ✅ Built — View Storybook

Details

⏰ Completed at: 04/03/2026, 08:24:32 AM UTC

Links

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

🎭 Playwright: ❌ 948 passed, 5 failed · 3 flaky

❌ Failed Tests

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

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 3, 2026

📦 Bundle: 5.11 MB gzip 🟢 -91 B

Details

Summary

  • Raw size: 23.5 MB baseline 23.5 MB — ⚪ 0 B
  • Gzip: 5.11 MB baseline 5.11 MB — 🟢 -91 B
  • Brotli: 3.95 MB baseline 3.95 MB — 🟢 -32 B
  • Bundles: 250 current • 250 baseline • 114 added / 114 removed

Category Glance
Vendor & Third-Party ⚪ 0 B (9.8 MB) · Other ⚪ 0 B (8.44 MB) · Data & Services ⚪ 0 B (2.97 MB) · Graph Workspace ⚪ 0 B (1.2 MB) · Panels & Settings ⚪ 0 B (484 kB) · Utilities & Hooks ⚪ 0 B (338 kB) · + 5 more

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

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-25OZtidL.js (new) 22.3 kB 🔴 +22.3 kB 🔴 +7.95 kB 🔴 +6.79 kB
assets/index-BQFKGOSV.js (removed) 22.3 kB 🟢 -22.3 kB 🟢 -7.95 kB 🟢 -6.79 kB

Status: 1 added / 1 removed

Graph Workspace — 1.2 MB (baseline 1.2 MB) • ⚪ 0 B

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-ov7S7nW-.js (new) 1.2 MB 🔴 +1.2 MB 🔴 +256 kB 🔴 +193 kB
assets/GraphView-uvJNeKIB.js (removed) 1.2 MB 🟢 -1.2 MB 🟢 -256 kB 🟢 -193 kB

Status: 1 added / 1 removed

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

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-DnLogLwn.js (new) 15.7 kB 🔴 +15.7 kB 🔴 +3.4 kB 🔴 +2.9 kB
assets/CloudSurveyView-YXF21fMV.js (removed) 15.7 kB 🟢 -15.7 kB 🟢 -3.4 kB 🟢 -2.89 kB
assets/CloudLoginView-BdKY4cSx.js (new) 12 kB 🔴 +12 kB 🔴 +3.36 kB 🔴 +2.96 kB
assets/CloudLoginView-DeVpiw6j.js (removed) 12 kB 🟢 -12 kB 🟢 -3.36 kB 🟢 -2.96 kB
assets/CloudSignupView-CF2j63R0.js (removed) 9.78 kB 🟢 -9.78 kB 🟢 -2.86 kB 🟢 -2.5 kB
assets/CloudSignupView-IP-_KD6r.js (new) 9.78 kB 🔴 +9.78 kB 🔴 +2.85 kB 🔴 +2.5 kB
assets/UserCheckView-3O3igXbH.js (new) 9.04 kB 🔴 +9.04 kB 🔴 +2.33 kB 🔴 +2.03 kB
assets/UserCheckView-C42KLgWV.js (removed) 9.04 kB 🟢 -9.04 kB 🟢 -2.33 kB 🟢 -2.03 kB
assets/CloudLayoutView-DgNsFpvL.js (removed) 7.54 kB 🟢 -7.54 kB 🟢 -2.36 kB 🟢 -2.06 kB
assets/CloudLayoutView-mjv-4bmV.js (new) 7.54 kB 🔴 +7.54 kB 🔴 +2.36 kB 🔴 +2.04 kB
assets/CloudForgotPasswordView-C99LmsTz.js (new) 5.94 kB 🔴 +5.94 kB 🔴 +2.09 kB 🔴 +1.85 kB
assets/CloudForgotPasswordView-D8x84dfQ.js (removed) 5.94 kB 🟢 -5.94 kB 🟢 -2.09 kB 🟢 -1.83 kB
assets/CloudAuthTimeoutView-CKt4SJYx.js (new) 5.31 kB 🔴 +5.31 kB 🔴 +1.93 kB 🔴 +1.69 kB
assets/CloudAuthTimeoutView-DFnwyJDv.js (removed) 5.31 kB 🟢 -5.31 kB 🟢 -1.93 kB 🟢 -1.68 kB
assets/CloudSubscriptionRedirectView-ByA9Wmkg.js (new) 5.08 kB 🔴 +5.08 kB 🔴 +1.91 kB 🔴 +1.68 kB
assets/CloudSubscriptionRedirectView-DTdLEAPn.js (removed) 5.08 kB 🟢 -5.08 kB 🟢 -1.91 kB 🟢 -1.69 kB
assets/UserSelectView-AGmvPadg.js (new) 4.71 kB 🔴 +4.71 kB 🔴 +1.74 kB 🔴 +1.55 kB
assets/UserSelectView-BDBdkhno.js (removed) 4.71 kB 🟢 -4.71 kB 🟢 -1.74 kB 🟢 -1.54 kB

Status: 9 added / 9 removed / 2 unchanged

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

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/KeybindingPanel-BRJtko8a.js (new) 46.6 kB 🔴 +46.6 kB 🔴 +9.52 kB 🔴 +8.47 kB
assets/KeybindingPanel-OOJsiP2n.js (removed) 46.6 kB 🟢 -46.6 kB 🟢 -9.52 kB 🟢 -8.47 kB
assets/SecretsPanel-DsFrzhEL.js (removed) 22.4 kB 🟢 -22.4 kB 🟢 -5.42 kB 🟢 -4.78 kB
assets/SecretsPanel-h9v3V-0S.js (new) 22.4 kB 🔴 +22.4 kB 🔴 +5.42 kB 🔴 +4.78 kB
assets/LegacyCreditsPanel-CPwSuD2G.js (new) 21.5 kB 🔴 +21.5 kB 🔴 +5.81 kB 🔴 +5.13 kB
assets/LegacyCreditsPanel-RU7odCVb.js (removed) 21.5 kB 🟢 -21.5 kB 🟢 -5.81 kB 🟢 -5.13 kB
assets/SubscriptionPanel-0sF3CkQI.js (new) 19.7 kB 🔴 +19.7 kB 🔴 +5.01 kB 🔴 +4.4 kB
assets/SubscriptionPanel-Bd3-KR2E.js (removed) 19.7 kB 🟢 -19.7 kB 🟢 -5.01 kB 🟢 -4.4 kB
assets/AboutPanel-CGui_hJV.js (removed) 12 kB 🟢 -12 kB 🟢 -3.33 kB 🟢 -2.98 kB
assets/AboutPanel-ChpTCv98.js (new) 12 kB 🔴 +12 kB 🔴 +3.33 kB 🔴 +3 kB
assets/ExtensionPanel-B_VXABgT.js (new) 9.78 kB 🔴 +9.78 kB 🔴 +2.82 kB 🔴 +2.51 kB
assets/ExtensionPanel-g6TGAGkG.js (removed) 9.78 kB 🟢 -9.78 kB 🟢 -2.82 kB 🟢 -2.51 kB
assets/ServerConfigPanel-BuaM-Ql1.js (new) 6.85 kB 🔴 +6.85 kB 🔴 +2.27 kB 🔴 +2.03 kB
assets/ServerConfigPanel-DY8jgiOW.js (removed) 6.85 kB 🟢 -6.85 kB 🟢 -2.27 kB 🟢 -2.03 kB
assets/UserPanel-CPOB-LMU.js (new) 6.56 kB 🔴 +6.56 kB 🔴 +2.15 kB 🔴 +1.9 kB
assets/UserPanel-ePxJEGZf.js (removed) 6.56 kB 🟢 -6.56 kB 🟢 -2.15 kB 🟢 -1.88 kB
assets/cloudRemoteConfig-BK93MxtA.js (removed) 1.85 kB 🟢 -1.85 kB 🟢 -903 B 🟢 -791 B
assets/cloudRemoteConfig-CjfEDjT1.js (new) 1.85 kB 🔴 +1.85 kB 🔴 +902 B 🔴 +794 B
assets/refreshRemoteConfig-3sXzzq4J.js (removed) 1.45 kB 🟢 -1.45 kB 🟢 -649 B 🟢 -548 B
assets/refreshRemoteConfig-oB80zn1Q.js (new) 1.45 kB 🔴 +1.45 kB 🔴 +648 B 🔴 +552 B

Status: 10 added / 10 removed / 12 unchanged

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

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/auth-Dhg1UQRU.js (removed) 3.57 kB 🟢 -3.57 kB 🟢 -1.26 kB 🟢 -1.07 kB
assets/auth-Iix_DZ0R.js (new) 3.57 kB 🔴 +3.57 kB 🔴 +1.26 kB 🔴 +1.07 kB
assets/SignUpForm-BT9UCtdT.js (new) 3.16 kB 🔴 +3.16 kB 🔴 +1.29 kB 🔴 +1.15 kB
assets/SignUpForm-Cj2NDE6B.js (removed) 3.16 kB 🟢 -3.16 kB 🟢 -1.29 kB 🟢 -1.15 kB
assets/UpdatePasswordContent-B5x7B0mt.js (removed) 2.66 kB 🟢 -2.66 kB 🟢 -1.19 kB 🟢 -1.07 kB
assets/UpdatePasswordContent-SkfKhvCm.js (new) 2.66 kB 🔴 +2.66 kB 🔴 +1.19 kB 🔴 +1.05 kB
assets/authStore-B_NMw0CZ.js (removed) 989 B 🟢 -989 B 🟢 -484 B 🟢 -436 B
assets/authStore-KObD1trv.js (new) 989 B 🔴 +989 B 🔴 +486 B 🔴 +438 B
assets/auth-C9-hjJE1.js (new) 348 B 🔴 +348 B 🔴 +216 B 🔴 +193 B
assets/auth-oyMq3yqm.js (removed) 348 B 🟢 -348 B 🟢 -218 B 🟢 -190 B

Status: 5 added / 5 removed / 2 unchanged

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

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useShareDialog-BA_RlAHw.js (removed) 108 kB 🟢 -108 kB 🟢 -22.4 kB 🟢 -18.9 kB
assets/useShareDialog-upjDbPm5.js (new) 108 kB 🔴 +108 kB 🔴 +22.4 kB 🔴 +18.9 kB
assets/useSubscriptionDialog-CMTg1gWK.js (removed) 969 B 🟢 -969 B 🟢 -475 B 🟢 -420 B
assets/useSubscriptionDialog-DO6HEwEE.js (new) 969 B 🔴 +969 B 🔴 +476 B 🔴 +420 B

Status: 2 added / 2 removed

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

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/ComfyQueueButton-NSr7HrXz.js (new) 13.5 kB 🔴 +13.5 kB 🔴 +3.79 kB 🔴 +3.37 kB
assets/ComfyQueueButton-RB_aFpSE.js (removed) 13.5 kB 🟢 -13.5 kB 🟢 -3.79 kB 🟢 -3.37 kB
assets/useTerminalTabs-Bhh-VHJb.js (new) 10.7 kB 🔴 +10.7 kB 🔴 +3.6 kB 🔴 +3.17 kB
assets/useTerminalTabs-CKn8frPW.js (removed) 10.7 kB 🟢 -10.7 kB 🟢 -3.6 kB 🟢 -3.16 kB
assets/SubscribeButton-DFpYi4OT.js (new) 2.42 kB 🔴 +2.42 kB 🔴 +1.04 kB 🔴 +914 B
assets/SubscribeButton-jWD2eDHw.js (removed) 2.42 kB 🟢 -2.42 kB 🟢 -1.05 kB 🟢 -914 B
assets/cloudFeedbackTopbarButton-D247WnGJ.js (removed) 1.66 kB 🟢 -1.66 kB 🟢 -844 B 🟢 -750 B
assets/cloudFeedbackTopbarButton-DeSx0oQE.js (new) 1.66 kB 🔴 +1.66 kB 🔴 +845 B 🔴 +752 B
assets/ComfyQueueButton-CG4AMD2y.js (removed) 1.03 kB 🟢 -1.03 kB 🟢 -489 B 🟢 -442 B
assets/ComfyQueueButton-WJ7UxDQy.js (new) 1.03 kB 🔴 +1.03 kB 🔴 +489 B 🔴 +443 B

Status: 5 added / 5 removed / 8 unchanged

Data & Services — 2.97 MB (baseline 2.97 MB) • ⚪ 0 B

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/dialogService-ah0NwNOU.js (new) 1.94 MB 🔴 +1.94 MB 🔴 +445 kB 🔴 +338 kB
assets/dialogService-CaW4TQiA.js (removed) 1.94 MB 🟢 -1.94 MB 🟢 -445 kB 🟢 -338 kB
assets/api-BzQeKjsg.js (removed) 885 kB 🟢 -885 kB 🟢 -211 kB 🟢 -167 kB
assets/api-tUlmIJtv.js (new) 885 kB 🔴 +885 kB 🔴 +211 kB 🔴 +167 kB
assets/load3dService-C9ZR-ISJ.js (removed) 92.5 kB 🟢 -92.5 kB 🟢 -19.7 kB 🟢 -16.9 kB
assets/load3dService-tzp7KZU8.js (new) 92.5 kB 🔴 +92.5 kB 🔴 +19.7 kB 🔴 +17 kB
assets/workflowShareService-BUw65M93.js (new) 16.6 kB 🔴 +16.6 kB 🔴 +4.88 kB 🔴 +4.33 kB
assets/workflowShareService-CKcycI85.js (removed) 16.6 kB 🟢 -16.6 kB 🟢 -4.88 kB 🟢 -4.32 kB
assets/keybindingService-C__Yt75C.js (removed) 13.8 kB 🟢 -13.8 kB 🟢 -3.67 kB 🟢 -3.21 kB
assets/keybindingService-CbYd2Uq6.js (new) 13.8 kB 🔴 +13.8 kB 🔴 +3.67 kB 🔴 +3.22 kB
assets/releaseStore-B_8YuLcD.js (removed) 8.12 kB 🟢 -8.12 kB 🟢 -2.28 kB 🟢 -2 kB
assets/releaseStore-Dm0XVdAf.js (new) 8.12 kB 🔴 +8.12 kB 🔴 +2.28 kB 🔴 +2 kB
assets/userStore-BrNhxOWq.js (removed) 2.24 kB 🟢 -2.24 kB 🟢 -869 B 🟢 -766 B
assets/userStore-DZuxI0kS.js (new) 2.24 kB 🔴 +2.24 kB 🔴 +867 B 🔴 +770 B
assets/audioService-Bbk_7N1F.js (new) 1.8 kB 🔴 +1.8 kB 🔴 +878 B 🔴 +761 B
assets/audioService-CM5KuzAn.js (removed) 1.8 kB 🟢 -1.8 kB 🟢 -877 B 🟢 -758 B
assets/releaseStore-BLZ8d_Un.js (removed) 993 B 🟢 -993 B 🟢 -482 B 🟢 -430 B
assets/releaseStore-CdVEOB99.js (new) 993 B 🔴 +993 B 🔴 +480 B 🔴 +429 B
assets/workflowDraftStore-BO40oXEh.js (removed) 969 B 🟢 -969 B 🟢 -473 B 🟢 -426 B
assets/workflowDraftStore-DEfIEW1-.js (new) 969 B 🔴 +969 B 🔴 +475 B 🔴 +426 B
assets/dialogService-DvQDJTAr.js (removed) 958 B 🟢 -958 B 🟢 -467 B 🟢 -417 B
assets/dialogService-J3cw-Eyc.js (new) 958 B 🔴 +958 B 🔴 +468 B 🔴 +419 B
assets/settingStore-Bt-pmN7j.js (new) 956 B 🔴 +956 B 🔴 +471 B 🔴 +420 B
assets/settingStore-CHAty-Ih.js (removed) 956 B 🟢 -956 B 🟢 -470 B 🟢 -419 B
assets/assetsStore-Czue4Q0j.js (new) 955 B 🔴 +955 B 🔴 +471 B 🔴 +422 B
assets/assetsStore-DOBjeWas.js (removed) 955 B 🟢 -955 B 🟢 -469 B 🟢 -421 B

Status: 13 added / 13 removed / 4 unchanged

Utilities & Hooks — 338 kB (baseline 338 kB) • ⚪ 0 B

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useConflictDetection-CVtIDolT.js (removed) 232 kB 🟢 -232 kB 🟢 -51.3 kB 🟢 -41.7 kB
assets/useConflictDetection-D7GtiEj7.js (new) 232 kB 🔴 +232 kB 🔴 +51.3 kB 🔴 +41.8 kB
assets/useLoad3dViewer-CC1LaBue.js (removed) 18.7 kB 🟢 -18.7 kB 🟢 -4.44 kB 🟢 -3.88 kB
assets/useLoad3dViewer-gf-z_AdY.js (new) 18.7 kB 🔴 +18.7 kB 🔴 +4.44 kB 🔴 +3.87 kB
assets/useLoad3d-CQYf9Pxe.js (new) 15 kB 🔴 +15 kB 🔴 +3.79 kB 🔴 +3.36 kB
assets/useLoad3d-K5cZszIo.js (removed) 15 kB 🟢 -15 kB 🟢 -3.79 kB 🟢 -3.35 kB
assets/useFeatureFlags-CZzYCSBp.js (new) 5.78 kB 🔴 +5.78 kB 🔴 +1.75 kB 🔴 +1.48 kB
assets/useFeatureFlags-DjYwCzEG.js (removed) 5.78 kB 🟢 -5.78 kB 🟢 -1.75 kB 🟢 -1.48 kB
assets/useCopyToClipboard-BdFO5ast.js (removed) 5.29 kB 🟢 -5.29 kB 🟢 -1.86 kB 🟢 -1.57 kB
assets/useCopyToClipboard-D_M9ivzr.js (new) 5.29 kB 🔴 +5.29 kB 🔴 +1.86 kB 🔴 +1.57 kB
assets/useWorkspaceUI-Bgl5NYuC.js (removed) 3.34 kB 🟢 -3.34 kB 🟢 -979 B 🟢 -813 B
assets/useWorkspaceUI-DW7vLUph.js (new) 3.34 kB 🔴 +3.34 kB 🔴 +980 B 🔴 +809 B
assets/subscriptionCheckoutUtil-1BCtyJfV.js (removed) 2.97 kB 🟢 -2.97 kB 🟢 -1.31 kB 🟢 -1.14 kB
assets/subscriptionCheckoutUtil-C8IMayOg.js (new) 2.97 kB 🔴 +2.97 kB 🔴 +1.3 kB 🔴 +1.14 kB
assets/assetPreviewUtil-CCDi12Rz.js (new) 2.27 kB 🔴 +2.27 kB 🔴 +958 B 🔴 +833 B
assets/assetPreviewUtil-EaQ588si.js (removed) 2.27 kB 🟢 -2.27 kB 🟢 -958 B 🟢 -832 B
assets/useUpstreamValue-CH98pguo.js (removed) 2.08 kB 🟢 -2.08 kB 🟢 -805 B 🟢 -713 B
assets/useUpstreamValue-Cyh_BjXA.js (new) 2.08 kB 🔴 +2.08 kB 🔴 +802 B 🔴 +710 B
assets/useLoad3d-B7q1omQe.js (removed) 1.13 kB 🟢 -1.13 kB 🟢 -540 B 🟢 -484 B
assets/useLoad3d-F9Ib7u6E.js (new) 1.13 kB 🔴 +1.13 kB 🔴 +538 B 🔴 +478 B
assets/useLoad3dViewer-Bfem1ACI.js (new) 1.07 kB 🔴 +1.07 kB 🔴 +504 B 🔴 +458 B
assets/useLoad3dViewer-DT9BBmYK.js (removed) 1.07 kB 🟢 -1.07 kB 🟢 -505 B 🟢 -455 B
assets/useCurrentUser-BTt-Qly2.js (new) 955 B 🔴 +955 B 🔴 +471 B 🔴 +418 B
assets/useCurrentUser-BZmQjFiX.js (removed) 955 B 🟢 -955 B 🟢 -470 B 🟢 -421 B
assets/useWorkspaceSwitch-CrmBR2te.js (removed) 747 B 🟢 -747 B 🟢 -384 B 🟢 -330 B
assets/useWorkspaceSwitch-DBUpEpaq.js (new) 747 B 🔴 +747 B 🔴 +383 B 🔴 +331 B

Status: 13 added / 13 removed / 13 unchanged

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

External libraries and shared vendor chunks

Status: 16 unchanged

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

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/core-0W328O5V.js (new) 76.8 kB 🔴 +76.8 kB 🔴 +19.9 kB 🔴 +16.9 kB
assets/core-CmhufUOl.js (removed) 76.8 kB 🟢 -76.8 kB 🟢 -19.9 kB 🟢 -16.9 kB
assets/groupNode-CJUzZrFX.js (removed) 74 kB 🟢 -74 kB 🟢 -18.5 kB 🟢 -16.3 kB
assets/groupNode-D9ThqXWW.js (new) 74 kB 🔴 +74 kB 🔴 +18.5 kB 🔴 +16.3 kB
assets/WidgetSelect-B8IT7jpY.js (new) 64.6 kB 🔴 +64.6 kB 🔴 +14.1 kB 🔴 +12.2 kB
assets/WidgetSelect-BmX1IdnY.js (removed) 64.6 kB 🟢 -64.6 kB 🟢 -14.1 kB 🟢 -12.2 kB
assets/SubscriptionRequiredDialogContentWorkspace-BI1sMvEI.js (removed) 48.9 kB 🟢 -48.9 kB 🟢 -9.29 kB 🟢 -7.95 kB
assets/SubscriptionRequiredDialogContentWorkspace-DHGf3coV.js (new) 48.9 kB 🔴 +48.9 kB 🔴 +9.29 kB 🔴 +7.93 kB
assets/WidgetPainter-DpbzYR6N.js (removed) 33.3 kB 🟢 -33.3 kB 🟢 -8.12 kB 🟢 -7.19 kB
assets/WidgetPainter-DspP6tfE.js (new) 33.3 kB 🔴 +33.3 kB 🔴 +8.11 kB 🔴 +7.19 kB
assets/Load3DControls-BJ4G1OlM.js (removed) 32.1 kB 🟢 -32.1 kB 🟢 -5.47 kB 🟢 -4.76 kB
assets/Load3DControls-CdtMqD1t.js (new) 32.1 kB 🔴 +32.1 kB 🔴 +5.47 kB 🔴 +4.75 kB
assets/WorkspacePanelContent-25afP9cD.js (new) 29.9 kB 🔴 +29.9 kB 🔴 +6.33 kB 🔴 +5.54 kB
assets/WorkspacePanelContent-jc_Je5qX.js (removed) 29.9 kB 🟢 -29.9 kB 🟢 -6.33 kB 🟢 -5.55 kB
assets/SubscriptionRequiredDialogContent-BrVsTOqn.js (new) 28.2 kB 🔴 +28.2 kB 🔴 +7.17 kB 🔴 +6.29 kB
assets/SubscriptionRequiredDialogContent-DLaMFntU.js (removed) 28.2 kB 🟢 -28.2 kB 🟢 -7.17 kB 🟢 -6.3 kB
assets/Load3dViewerContent-Cdx1KCZl.js (new) 24.5 kB 🔴 +24.5 kB 🔴 +5.33 kB 🔴 +4.63 kB
assets/Load3dViewerContent-DlcxV4NQ.js (removed) 24.5 kB 🟢 -24.5 kB 🟢 -5.33 kB 🟢 -4.64 kB
assets/WidgetImageCrop-CyeWwhwR.js (removed) 23.3 kB 🟢 -23.3 kB 🟢 -5.83 kB 🟢 -5.13 kB
assets/WidgetImageCrop-DZMiyKJR.js (new) 23.3 kB 🔴 +23.3 kB 🔴 +5.82 kB 🔴 +5.13 kB
assets/SubscriptionPanelContentWorkspace-BO-QsEEl.js (removed) 22.2 kB 🟢 -22.2 kB 🟢 -5.18 kB 🟢 -4.55 kB
assets/SubscriptionPanelContentWorkspace-FD2e8ME3.js (new) 22.2 kB 🔴 +22.2 kB 🔴 +5.18 kB 🔴 +4.58 kB
assets/SignInContent-2crlqyio.js (removed) 20.4 kB 🟢 -20.4 kB 🟢 -5.29 kB 🟢 -4.64 kB
assets/SignInContent-BVyR5AC1.js (new) 20.4 kB 🔴 +20.4 kB 🔴 +5.29 kB 🔴 +4.62 kB
assets/CurrentUserPopoverWorkspace-6gdcvtRB.js (new) 20.4 kB 🔴 +20.4 kB 🔴 +4.83 kB 🔴 +4.32 kB
assets/CurrentUserPopoverWorkspace-CUrxlqTi.js (removed) 20.4 kB 🟢 -20.4 kB 🟢 -4.83 kB 🟢 -4.33 kB
assets/WidgetInputNumber-CThSBFOy.js (removed) 19.1 kB 🟢 -19.1 kB 🟢 -4.84 kB 🟢 -4.3 kB
assets/WidgetInputNumber-WhbEnUN1.js (new) 19.1 kB 🔴 +19.1 kB 🔴 +4.84 kB 🔴 +4.3 kB
assets/WidgetRecordAudio-BcTIpjjh.js (new) 18.1 kB 🔴 +18.1 kB 🔴 +5.18 kB 🔴 +4.64 kB
assets/WidgetRecordAudio-DbiOw4aS.js (removed) 18.1 kB 🟢 -18.1 kB 🟢 -5.18 kB 🟢 -4.64 kB
assets/Load3D-Bt4A_sek.js (new) 16.9 kB 🔴 +16.9 kB 🔴 +4.12 kB 🔴 +3.59 kB
assets/Load3D-DaoaT4Qg.js (removed) 16.9 kB 🟢 -16.9 kB 🟢 -4.12 kB 🟢 -3.59 kB
assets/load3d-C8Hr52JK.js (new) 15 kB 🔴 +15 kB 🔴 +4.31 kB 🔴 +3.74 kB
assets/load3d-DG7xgSgw.js (removed) 15 kB 🟢 -15 kB 🟢 -4.32 kB 🟢 -3.73 kB
assets/WaveAudioPlayer-CCKMo0Hj.js (removed) 13.4 kB 🟢 -13.4 kB 🟢 -3.69 kB 🟢 -3.22 kB
assets/WaveAudioPlayer-Cj1Plpth.js (new) 13.4 kB 🔴 +13.4 kB 🔴 +3.69 kB 🔴 +3.22 kB
assets/WidgetCurve-CJKyPzZZ.js (removed) 12 kB 🟢 -12 kB 🟢 -3.85 kB 🟢 -3.48 kB
assets/WidgetCurve-DNTvq_SD.js (new) 12 kB 🔴 +12 kB 🔴 +3.85 kB 🔴 +3.48 kB
assets/TeamWorkspacesDialogContent-BcU5nNIs.js (new) 11.1 kB 🔴 +11.1 kB 🔴 +3.33 kB 🔴 +2.96 kB
assets/TeamWorkspacesDialogContent-DvhvDNTi.js (removed) 11.1 kB 🟢 -11.1 kB 🟢 -3.33 kB 🟢 -2.98 kB
assets/nodeTemplates-BY4narpy.js (new) 9.58 kB 🔴 +9.58 kB 🔴 +3.37 kB 🔴 +2.97 kB
assets/nodeTemplates-DyFUneAJ.js (removed) 9.58 kB 🟢 -9.58 kB 🟢 -3.37 kB 🟢 -2.97 kB
assets/InviteMemberDialogContent-CD2hgh20.js (new) 7.77 kB 🔴 +7.77 kB 🔴 +2.45 kB 🔴 +2.15 kB
assets/InviteMemberDialogContent-CfZJqkNW.js (removed) 7.77 kB 🟢 -7.77 kB 🟢 -2.45 kB 🟢 -2.15 kB
assets/Load3DConfiguration-Caj3ePe_.js (removed) 6.6 kB 🟢 -6.6 kB 🟢 -2.04 kB 🟢 -1.78 kB
assets/Load3DConfiguration-CVI0hSBn.js (new) 6.6 kB 🔴 +6.6 kB 🔴 +2.04 kB 🔴 +1.78 kB
assets/onboardingCloudRoutes-C0BKfjJg.js (removed) 6.53 kB 🟢 -6.53 kB 🟢 -2.04 kB 🟢 -1.74 kB
assets/onboardingCloudRoutes-dKPLxnzX.js (new) 6.53 kB 🔴 +6.53 kB 🔴 +2.04 kB 🔴 +1.75 kB
assets/WidgetWithControl-vTiXCuQI.js (new) 5.99 kB 🔴 +5.99 kB 🔴 +2.38 kB 🔴 +2.13 kB
assets/WidgetWithControl-zQzZrRGA.js (removed) 5.99 kB 🟢 -5.99 kB 🟢 -2.38 kB 🟢 -2.11 kB
assets/CreateWorkspaceDialogContent-OncOa_4A.js (removed) 5.95 kB 🟢 -5.95 kB 🟢 -2.15 kB 🟢 -1.88 kB
assets/CreateWorkspaceDialogContent-P4Hrne1y.js (new) 5.95 kB 🔴 +5.95 kB 🔴 +2.15 kB 🔴 +1.87 kB
assets/FreeTierDialogContent-DoFtcuSp.js (new) 5.82 kB 🔴 +5.82 kB 🔴 +2.04 kB 🔴 +1.81 kB
assets/FreeTierDialogContent-DxCZpQ0d.js (removed) 5.82 kB 🟢 -5.82 kB 🟢 -2.05 kB 🟢 -1.81 kB
assets/EditWorkspaceDialogContent-CE5Jekvw.js (new) 5.75 kB 🔴 +5.75 kB 🔴 +2.11 kB 🔴 +1.84 kB
assets/EditWorkspaceDialogContent-DBO9zu4Z.js (removed) 5.75 kB 🟢 -5.75 kB 🟢 -2.11 kB 🟢 -1.84 kB
assets/WidgetTextarea-DkYXgUfQ.js (new) 5.53 kB 🔴 +5.53 kB 🔴 +2.17 kB 🔴 +1.91 kB
assets/WidgetTextarea-wSbzdwB0.js (removed) 5.53 kB 🟢 -5.53 kB 🟢 -2.17 kB 🟢 -1.92 kB
assets/Preview3d-DTw058QB.js (removed) 5.36 kB 🟢 -5.36 kB 🟢 -1.79 kB 🟢 -1.56 kB
assets/Preview3d-JfVp-1gH.js (new) 5.36 kB 🔴 +5.36 kB 🔴 +1.79 kB 🔴 +1.56 kB
assets/ValueControlPopover-C-L2RzXq.js (removed) 5.33 kB 🟢 -5.33 kB 🟢 -1.93 kB 🟢 -1.73 kB
assets/ValueControlPopover-CDIarg5C.js (new) 5.33 kB 🔴 +5.33 kB 🔴 +1.93 kB 🔴 +1.74 kB
assets/CancelSubscriptionDialogContent-BK_PKhCU.js (new) 5.22 kB 🔴 +5.22 kB 🔴 +1.95 kB 🔴 +1.7 kB
assets/CancelSubscriptionDialogContent-Bp1UNeeG.js (removed) 5.22 kB 🟢 -5.22 kB 🟢 -1.95 kB 🟢 -1.7 kB
assets/DeleteWorkspaceDialogContent-CGXCNUg_.js (new) 4.65 kB 🔴 +4.65 kB 🔴 +1.79 kB 🔴 +1.55 kB
assets/DeleteWorkspaceDialogContent-DCJ84ssM.js (removed) 4.65 kB 🟢 -4.65 kB 🟢 -1.79 kB 🟢 -1.55 kB
assets/LeaveWorkspaceDialogContent-By_6I36g.js (new) 4.48 kB 🔴 +4.48 kB 🔴 +1.73 kB 🔴 +1.5 kB
assets/LeaveWorkspaceDialogContent-CZ8hRGcx.js (removed) 4.48 kB 🟢 -4.48 kB 🟢 -1.74 kB 🟢 -1.51 kB
assets/RemoveMemberDialogContent-BmcwhCXC.js (removed) 4.46 kB 🟢 -4.46 kB 🟢 -1.69 kB 🟢 -1.47 kB
assets/RemoveMemberDialogContent-pcIeArif.js (new) 4.46 kB 🔴 +4.46 kB 🔴 +1.69 kB 🔴 +1.47 kB
assets/tierBenefits-C4CVL3ML.js (new) 4.45 kB 🔴 +4.45 kB 🔴 +1.58 kB 🔴 +1.36 kB
assets/tierBenefits-CYjfq_7r.js (removed) 4.45 kB 🟢 -4.45 kB 🟢 -1.58 kB 🟢 -1.36 kB
assets/RevokeInviteDialogContent-1VE36NIF.js (removed) 4.37 kB 🟢 -4.37 kB 🟢 -1.7 kB 🟢 -1.48 kB
assets/RevokeInviteDialogContent-DPvFshlg.js (new) 4.37 kB 🔴 +4.37 kB 🔴 +1.7 kB 🔴 +1.48 kB
assets/InviteMemberUpsellDialogContent-Bn97rBtB.js (removed) 4.27 kB 🟢 -4.27 kB 🟢 -1.56 kB 🟢 -1.37 kB
assets/InviteMemberUpsellDialogContent-BniyLZ8f.js (new) 4.27 kB 🔴 +4.27 kB 🔴 +1.56 kB 🔴 +1.37 kB
assets/cloudSessionCookie-CFho_Hq_.js (new) 4.12 kB 🔴 +4.12 kB 🔴 +1.49 kB 🔴 +1.3 kB
assets/cloudSessionCookie-JUUJgAQZ.js (removed) 4.12 kB 🟢 -4.12 kB 🟢 -1.49 kB 🟢 -1.3 kB
assets/saveMesh-fK9AkNbt.js (removed) 3.92 kB 🟢 -3.92 kB 🟢 -1.68 kB 🟢 -1.48 kB
assets/saveMesh-v7ADhC-h.js (new) 3.92 kB 🔴 +3.92 kB 🔴 +1.68 kB 🔴 +1.47 kB
assets/Media3DTop-BcPUfJsz.js (removed) 3.85 kB 🟢 -3.85 kB 🟢 -1.62 kB 🟢 -1.43 kB
assets/Media3DTop-Bj4haXYN.js (new) 3.85 kB 🔴 +3.85 kB 🔴 +1.62 kB 🔴 +1.43 kB
assets/GlobalToast-D-P_nPhX.js (new) 3.05 kB 🔴 +3.05 kB 🔴 +1.25 kB 🔴 +1.07 kB
assets/GlobalToast-L0qD3dTO.js (removed) 3.05 kB 🟢 -3.05 kB 🟢 -1.26 kB 🟢 -1.1 kB
assets/SubscribeToRun-tWskb2oE.js (removed) 2.13 kB 🟢 -2.13 kB 🟢 -983 B 🟢 -880 B
assets/SubscribeToRun-XKuXimBF.js (new) 2.13 kB 🔴 +2.13 kB 🔴 +982 B 🔴 +876 B
assets/MediaAudioTop-BLpUkcX9.js (new) 2.02 kB 🔴 +2.02 kB 🔴 +983 B 🔴 +835 B
assets/MediaAudioTop-DK0qHiik.js (removed) 2.02 kB 🟢 -2.02 kB 🟢 -983 B 🟢 -829 B
assets/CloudRunButtonWrapper-_XMLy7Wq.js (new) 1.99 kB 🔴 +1.99 kB 🔴 +909 B 🔴 +807 B
assets/CloudRunButtonWrapper-wI670lOZ.js (removed) 1.99 kB 🟢 -1.99 kB 🟢 -908 B 🟢 -801 B
assets/graphHasMissingNodes-Dum-aLUN.js (removed) 1.83 kB 🟢 -1.83 kB 🟢 -861 B 🟢 -750 B
assets/graphHasMissingNodes-JzVN4usq.js (new) 1.83 kB 🔴 +1.83 kB 🔴 +862 B 🔴 +755 B
assets/cloudBadges-4r8WJqUW.js (new) 1.77 kB 🔴 +1.77 kB 🔴 +891 B 🔴 +772 B
assets/cloudBadges-lz6UBuij.js (removed) 1.77 kB 🟢 -1.77 kB 🟢 -889 B 🟢 -792 B
assets/cloudSubscription-BgU1AaeE.js (new) 1.68 kB 🔴 +1.68 kB 🔴 +812 B 🔴 +702 B
assets/cloudSubscription-BNfs8Qnm.js (removed) 1.68 kB 🟢 -1.68 kB 🟢 -812 B 🟢 -710 B
assets/previousFullPath-BEVIYNi9.js (removed) 1.53 kB 🟢 -1.53 kB 🟢 -695 B 🟢 -601 B
assets/previousFullPath-DaZzDR8K.js (new) 1.53 kB 🔴 +1.53 kB 🔴 +695 B 🔴 +603 B
assets/Load3D-DXKOSX8f.js (new) 1.34 kB 🔴 +1.34 kB 🔴 +607 B 🔴 +540 B
assets/Load3D-EtnbyXQT.js (removed) 1.34 kB 🟢 -1.34 kB 🟢 -612 B 🟢 -546 B
assets/nightlyBadges-BRaiJ3Am.js (removed) 1.29 kB 🟢 -1.29 kB 🟢 -657 B 🟢 -585 B
assets/nightlyBadges-UKhY8PQM.js (new) 1.29 kB 🔴 +1.29 kB 🔴 +659 B 🔴 +586 B
assets/Load3dViewerContent-BB8MfLfZ.js (new) 1.23 kB 🔴 +1.23 kB 🔴 +563 B 🔴 +504 B
assets/Load3dViewerContent-C53k28P3.js (removed) 1.23 kB 🟢 -1.23 kB 🟢 -564 B 🟢 -496 B
assets/SubscriptionPanelContentWorkspace-C1x-t4NS.js (new) 1.15 kB 🔴 +1.15 kB 🔴 +534 B 🔴 +467 B
assets/SubscriptionPanelContentWorkspace-DSw2csls.js (removed) 1.15 kB 🟢 -1.15 kB 🟢 -535 B 🟢 -467 B
assets/WidgetLegacy-C1JDplXt.js (new) 978 B 🔴 +978 B 🔴 +482 B 🔴 +429 B
assets/WidgetLegacy-CKHHvyxl.js (removed) 978 B 🟢 -978 B 🟢 -481 B 🟢 -427 B
assets/changeTracker-B3TsF5bD.js (removed) 952 B 🟢 -952 B 🟢 -470 B 🟢 -418 B
assets/changeTracker-BObYkg4y.js (new) 952 B 🔴 +952 B 🔴 +471 B 🔴 +421 B

Status: 55 added / 55 removed / 79 unchanged

⚡ Performance Report

canvas-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 60.2 MB heap
canvas-mouse-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 56.5 MB heap
canvas-zoom-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 64.4 MB heap
dom-widget-clipping: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 46.8 MB heap
large-graph-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 53.3 MB heap
large-graph-pan: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 64.7 MB heap
large-graph-zoom: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 59.1 MB heap
minimap-idle: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 53.9 MB heap
subgraph-dom-widget-clipping: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 47.3 MB heap
subgraph-idle: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 60.1 MB heap
subgraph-mouse-sweep: · 60.0 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 52.1 MB heap
viewport-pan-sweep: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 72.2 MB heap
vue-large-graph-idle: · 58.1 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 158.2 MB heap
vue-large-graph-pan: · 58.1 avg FPS · 59.5 P5 FPS ✅ (target: ≥52) · 0ms TBT · 172.2 MB heap
workflow-execution: · 60.0 avg FPS · 59.9 P5 FPS ✅ (target: ≥52) · 0ms TBT · 48.1 MB heap

⚠️ 1 regression detected

Metric Baseline PR (median) Δ Sig
subgraph-mouse-sweep: task duration 910ms 907ms -0% ⚠️ z=2.0
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 +0%
canvas-idle: layout duration 0ms 0ms +0%
canvas-idle: style recalc duration 9ms 9ms -4% z=-2.0
canvas-idle: layout count 0 0 +0%
canvas-idle: style recalc count 11 11 +0% z=-0.3
canvas-idle: task duration 348ms 348ms -0% z=-1.5
canvas-idle: script duration 22ms 22ms -1% z=-1.5
canvas-idle: TBT 0ms 0ms +0%
canvas-idle: heap used 61.2 MB 60.2 MB -2%
canvas-idle: DOM nodes 21 21 +0% z=-1.2
canvas-idle: event listeners 6 6 +0% z=-1.2
canvas-mouse-sweep: avg frame time 17ms 17ms +0% z=-0.4
canvas-mouse-sweep: p95 frame time 17ms 17ms -1%
canvas-mouse-sweep: layout duration 4ms 4ms +2% z=0.2
canvas-mouse-sweep: style recalc duration 43ms 46ms +5% z=0.9
canvas-mouse-sweep: layout count 12 12 +0%
canvas-mouse-sweep: style recalc count 81 83 +2% z=1.8
canvas-mouse-sweep: task duration 983ms 976ms -1% z=1.9
canvas-mouse-sweep: script duration 137ms 134ms -2% z=-0.3
canvas-mouse-sweep: TBT 0ms 0ms +0%
canvas-mouse-sweep: heap used 56.3 MB 56.5 MB +0%
canvas-mouse-sweep: DOM nodes 65 67 +3% z=1.8
canvas-mouse-sweep: event listeners 6 6 +0% z=-0.6
canvas-zoom-sweep: avg frame time 17ms 17ms +0% z=0.5
canvas-zoom-sweep: p95 frame time 17ms 17ms -1%
canvas-zoom-sweep: layout duration 1ms 1ms -14% z=-2.9
canvas-zoom-sweep: style recalc duration 18ms 17ms -4% z=-1.4
canvas-zoom-sweep: layout count 6 6 +0%
canvas-zoom-sweep: style recalc count 32 32 +0% z=1.6
canvas-zoom-sweep: task duration 310ms 285ms -8% z=-1.8
canvas-zoom-sweep: script duration 27ms 25ms -8% z=-0.8
canvas-zoom-sweep: TBT 0ms 0ms +0%
canvas-zoom-sweep: heap used 64.2 MB 64.4 MB +0%
canvas-zoom-sweep: DOM nodes 80 80 +0% z=1.0
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 10ms +6% z=0.5
dom-widget-clipping: layout count 0 0 +0%
dom-widget-clipping: style recalc count 13 14 +8% z=1.8
dom-widget-clipping: task duration 354ms 357ms +1% z=-0.4
dom-widget-clipping: script duration 64ms 66ms +4% z=-0.5
dom-widget-clipping: TBT 0ms 0ms +0%
dom-widget-clipping: heap used 47.0 MB 46.8 MB -1%
dom-widget-clipping: DOM nodes 22 23 +5% z=0.6
dom-widget-clipping: event listeners 2 2 +0% variance too high
large-graph-idle: avg frame time 17ms 17ms +0% z=-0.2
large-graph-idle: p95 frame time 17ms 17ms +0%
large-graph-idle: layout duration 0ms 0ms +0%
large-graph-idle: style recalc duration 10ms 10ms +8% z=-1.8
large-graph-idle: layout count 0 0 +0%
large-graph-idle: style recalc count 10 11 +10% z=-1.9
large-graph-idle: task duration 545ms 531ms -3% z=-0.2
large-graph-idle: script duration 101ms 96ms -4% z=-0.6
large-graph-idle: TBT 0ms 0ms +0%
large-graph-idle: heap used 52.8 MB 53.3 MB +1%
large-graph-idle: DOM nodes -255 -255 +0% z=-309.4
large-graph-idle: event listeners -123 -127 +3% z=-25.1
large-graph-pan: avg frame time 17ms 17ms -0% z=-0.8
large-graph-pan: p95 frame time 17ms 17ms +1%
large-graph-pan: layout duration 0ms 0ms +0%
large-graph-pan: style recalc duration 16ms 17ms +2% z=-0.8
large-graph-pan: layout count 0 0 +0%
large-graph-pan: style recalc count 68 70 +3% z=0.7
large-graph-pan: task duration 1073ms 1056ms -2% z=-0.6
large-graph-pan: script duration 400ms 385ms -4% z=-1.2
large-graph-pan: TBT 0ms 0ms +0%
large-graph-pan: heap used 65.1 MB 64.7 MB -1%
large-graph-pan: DOM nodes -261 -259 -1% z=-168.5
large-graph-pan: event listeners -127 -125 -2% z=-156.9
large-graph-zoom: avg frame time 17ms 17ms +0%
large-graph-zoom: p95 frame time 17ms 17ms +1%
large-graph-zoom: layout duration 7ms 7ms -2%
large-graph-zoom: style recalc duration 16ms 17ms +8%
large-graph-zoom: layout count 60 60 +0%
large-graph-zoom: style recalc count 66 66 +0%
large-graph-zoom: task duration 1385ms 1317ms -5%
large-graph-zoom: script duration 518ms 490ms -5%
large-graph-zoom: TBT 0ms 0ms +0%
large-graph-zoom: heap used 61.0 MB 59.1 MB -3%
large-graph-zoom: DOM nodes -264 -263 -0%
large-graph-zoom: event listeners -123 -123 +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 9ms 8ms -8% z=-1.4
minimap-idle: layout count 0 0 +0%
minimap-idle: style recalc count 9 10 +11% z=0.6
minimap-idle: task duration 536ms 522ms -3% z=-0.1
minimap-idle: script duration 97ms 99ms +2% z=0.1
minimap-idle: TBT 0ms 0ms +0%
minimap-idle: heap used 53.9 MB 53.9 MB -0%
minimap-idle: DOM nodes -261 -258 -1% z=-202.6
minimap-idle: event listeners -127 -127 +0% z=-199.3
subgraph-dom-widget-clipping: avg frame time 17ms 17ms -0% z=-0.9
subgraph-dom-widget-clipping: p95 frame time 17ms 17ms +0%
subgraph-dom-widget-clipping: layout duration 0ms 0ms +0%
subgraph-dom-widget-clipping: style recalc duration 14ms 12ms -11% z=-0.6
subgraph-dom-widget-clipping: layout count 0 0 +0%
subgraph-dom-widget-clipping: style recalc count 49 48 -2% z=0.1
subgraph-dom-widget-clipping: task duration 370ms 355ms -4% z=-1.3
subgraph-dom-widget-clipping: script duration 132ms 123ms -6% z=-0.8
subgraph-dom-widget-clipping: TBT 0ms 0ms +0%
subgraph-dom-widget-clipping: heap used 47.3 MB 47.3 MB +0%
subgraph-dom-widget-clipping: DOM nodes 23 22 -4% z=-0.2
subgraph-dom-widget-clipping: event listeners 8 8 +0% z=-1.4
subgraph-idle: avg frame time 17ms 17ms +0% z=0.4
subgraph-idle: p95 frame time 17ms 17ms +0%
subgraph-idle: layout duration 0ms 0ms +0%
subgraph-idle: style recalc duration 10ms 11ms +5% z=0.7
subgraph-idle: layout count 0 0 +0%
subgraph-idle: style recalc count 11 11 +0% z=0.2
subgraph-idle: task duration 370ms 333ms -10% z=-1.2
subgraph-idle: script duration 18ms 17ms -4% z=-1.2
subgraph-idle: TBT 0ms 0ms +0%
subgraph-idle: heap used 60.1 MB 60.1 MB +0%
subgraph-idle: DOM nodes 22 22 +0% z=0.1
subgraph-idle: event listeners 6 6 +0% variance too high
subgraph-mouse-sweep: avg frame time 17ms 17ms +0% z=0.4
subgraph-mouse-sweep: p95 frame time 17ms 17ms +1%
subgraph-mouse-sweep: layout duration 5ms 4ms -10% z=-1.1
subgraph-mouse-sweep: style recalc duration 48ms 46ms -4% z=1.2
subgraph-mouse-sweep: layout count 16 16 +0%
subgraph-mouse-sweep: style recalc count 85 84 -1% z=2.0
subgraph-mouse-sweep: task duration 910ms 907ms -0% ⚠️ z=2.0
subgraph-mouse-sweep: script duration 109ms 100ms -8% z=-0.1
subgraph-mouse-sweep: TBT 0ms 0ms +0%
subgraph-mouse-sweep: heap used 52.5 MB 52.1 MB -1%
subgraph-mouse-sweep: DOM nodes 73 73 +0% z=2.7
subgraph-mouse-sweep: event listeners 6 6 +0% variance too high
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 46ms 43ms -6%
viewport-pan-sweep: layout count 0 0 +0%
viewport-pan-sweep: style recalc count 252 252 +0%
viewport-pan-sweep: task duration 3713ms 3717ms +0%
viewport-pan-sweep: script duration 1263ms 1239ms -2%
viewport-pan-sweep: TBT 0ms 0ms +0%
viewport-pan-sweep: heap used 73.1 MB 72.2 MB -1%
viewport-pan-sweep: DOM nodes -254 -256 +1%
viewport-pan-sweep: event listeners -111 -111 +0%
vue-large-graph-idle: avg frame time 17ms 17ms +0%
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 12296ms 11397ms -7%
vue-large-graph-idle: script duration 626ms 568ms -9%
vue-large-graph-idle: TBT 0ms 0ms +0%
vue-large-graph-idle: heap used 158.3 MB 158.2 MB -0%
vue-large-graph-idle: DOM nodes -8331 -8331 +0%
vue-large-graph-idle: event listeners -16462 -16464 +0%
vue-large-graph-pan: avg frame time 17ms 17ms +0%
vue-large-graph-pan: p95 frame time 17ms 17ms +1%
vue-large-graph-pan: layout duration 0ms 0ms +0%
vue-large-graph-pan: style recalc duration 14ms 13ms -10%
vue-large-graph-pan: layout count 0 0 +0%
vue-large-graph-pan: style recalc count 70 65 -7%
vue-large-graph-pan: task duration 14487ms 13928ms -4%
vue-large-graph-pan: script duration 844ms 848ms +0%
vue-large-graph-pan: TBT 0ms 0ms +0%
vue-large-graph-pan: heap used 152.4 MB 172.2 MB +13%
vue-large-graph-pan: DOM nodes -8331 -8331 +0%
vue-large-graph-pan: event listeners -16460 -16463 +0%
workflow-execution: avg frame time 17ms 17ms -0% z=-0.4
workflow-execution: p95 frame time 17ms 17ms -1%
workflow-execution: layout duration 1ms 1ms +2% z=-1.0
workflow-execution: style recalc duration 24ms 23ms -1% z=-0.4
workflow-execution: layout count 5 5 +0% z=0.1
workflow-execution: style recalc count 16 17 +6% z=-0.4
workflow-execution: task duration 123ms 123ms -0% z=0.0
workflow-execution: script duration 27ms 29ms +6% z=0.0
workflow-execution: TBT 0ms 0ms +0%
workflow-execution: heap used 47.7 MB 48.1 MB +1%
workflow-execution: DOM nodes 156 156 +0% z=-0.7
workflow-execution: event listeners 71 71 +0% z=4.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-04-03T08:35:02.717Z",
  "gitSha": "e5ec4f2b2e272e70b400077741a8b433098d5bec",
  "branch": "test/curve-widget-E2E-test-plan",
  "measurements": [
    {
      "name": "canvas-idle",
      "durationMs": 2013.3200000000215,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 8.717000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 333.801,
      "heapDeltaBytes": 20305732,
      "heapUsedBytes": 63153916,
      "domNodes": 21,
      "jsHeapTotalBytes": 23068672,
      "scriptDurationMs": 21.816,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-idle",
      "durationMs": 2038.657999999998,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 10.829000000000002,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 379.5230000000001,
      "heapDeltaBytes": 20436280,
      "heapUsedBytes": 63320356,
      "domNodes": 22,
      "jsHeapTotalBytes": 22806528,
      "scriptDurationMs": 26.358,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-idle",
      "durationMs": 2023.7509999999475,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 9.036999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 347.73900000000003,
      "heapDeltaBytes": 20359628,
      "heapUsedBytes": 63126440,
      "domNodes": 20,
      "jsHeapTotalBytes": 22806528,
      "scriptDurationMs": 21.427000000000003,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 2054.3420000000197,
      "styleRecalcs": 83,
      "styleRecalcDurationMs": 47.64300000000001,
      "layouts": 12,
      "layoutDurationMs": 3.7720000000000002,
      "taskDurationMs": 1016.5999999999999,
      "heapDeltaBytes": 16728744,
      "heapUsedBytes": 59206780,
      "domNodes": 67,
      "jsHeapTotalBytes": 23592960,
      "scriptDurationMs": 141.22199999999998,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 1999.2129999999975,
      "styleRecalcs": 83,
      "styleRecalcDurationMs": 45.557,
      "layouts": 12,
      "layoutDurationMs": 3.657,
      "taskDurationMs": 975.782,
      "heapDeltaBytes": 16746412,
      "heapUsedBytes": 59237784,
      "domNodes": 69,
      "jsHeapTotalBytes": 22806528,
      "scriptDurationMs": 133.422,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "canvas-mouse-sweep",
      "durationMs": 2007.1920000000318,
      "styleRecalcs": 81,
      "styleRecalcDurationMs": 42.227000000000004,
      "layouts": 12,
      "layoutDurationMs": 3.58,
      "taskDurationMs": 958.265,
      "heapDeltaBytes": 16294628,
      "heapUsedBytes": 59101876,
      "domNodes": 65,
      "jsHeapTotalBytes": 23068672,
      "scriptDurationMs": 133.709,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1739.6160000000123,
      "styleRecalcs": 31,
      "styleRecalcDurationMs": 16.654000000000003,
      "layouts": 6,
      "layoutDurationMs": 0.6629999999999999,
      "taskDurationMs": 285.073,
      "heapDeltaBytes": 24976156,
      "heapUsedBytes": 67552804,
      "domNodes": 80,
      "jsHeapTotalBytes": 20709376,
      "scriptDurationMs": 24.758000000000003,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1748.646000000008,
      "styleRecalcs": 32,
      "styleRecalcDurationMs": 16.944,
      "layouts": 6,
      "layoutDurationMs": 0.49700000000000005,
      "taskDurationMs": 285.023,
      "heapDeltaBytes": 24722728,
      "heapUsedBytes": 68554688,
      "domNodes": 81,
      "jsHeapTotalBytes": 20447232,
      "scriptDurationMs": 23.526999999999997,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "canvas-zoom-sweep",
      "durationMs": 1755.1009999999678,
      "styleRecalcs": 32,
      "styleRecalcDurationMs": 18.401,
      "layouts": 6,
      "layoutDurationMs": 0.513,
      "taskDurationMs": 317.14300000000003,
      "heapDeltaBytes": 15361672,
      "heapUsedBytes": 67171664,
      "domNodes": 80,
      "jsHeapTotalBytes": 23068672,
      "scriptDurationMs": 26.01,
      "eventListeners": 19,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 581.1029999999846,
      "styleRecalcs": 13,
      "styleRecalcDurationMs": 9.009,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 357.382,
      "heapDeltaBytes": 6476564,
      "heapUsedBytes": 49061024,
      "domNodes": 22,
      "jsHeapTotalBytes": 13107200,
      "scriptDurationMs": 66.19500000000001,
      "eventListeners": 2,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 587.1779999999944,
      "styleRecalcs": 14,
      "styleRecalcDurationMs": 10.303,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 345.472,
      "heapDeltaBytes": 6893476,
      "heapUsedBytes": 49373340,
      "domNodes": 23,
      "jsHeapTotalBytes": 13107200,
      "scriptDurationMs": 66.10199999999999,
      "eventListeners": 2,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "dom-widget-clipping",
      "durationMs": 569.927000000007,
      "styleRecalcs": 14,
      "styleRecalcDurationMs": 10.493,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 365.27099999999996,
      "heapDeltaBytes": 6550796,
      "heapUsedBytes": 49008420,
      "domNodes": 24,
      "jsHeapTotalBytes": 12845056,
      "scriptDurationMs": 68.585,
      "eventListeners": 2,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2028.3870000000093,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 11.113,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 564.508,
      "heapDeltaBytes": 2827964,
      "heapUsedBytes": 53428424,
      "domNodes": -255,
      "jsHeapTotalBytes": 15659008,
      "scriptDurationMs": 106.274,
      "eventListeners": -125,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2034.421000000009,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 9.687999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 522.918,
      "heapDeltaBytes": 5412084,
      "heapUsedBytes": 55916892,
      "domNodes": -255,
      "jsHeapTotalBytes": 16183296,
      "scriptDurationMs": 94.464,
      "eventListeners": -127,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-idle",
      "durationMs": 2053.886000000034,
      "styleRecalcs": 12,
      "styleRecalcDurationMs": 10.362,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 531.1909999999999,
      "heapDeltaBytes": 5018604,
      "heapUsedBytes": 55840896,
      "domNodes": -256,
      "jsHeapTotalBytes": 15659008,
      "scriptDurationMs": 96.327,
      "eventListeners": -127,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2139.251999999999,
      "styleRecalcs": 70,
      "styleRecalcDurationMs": 18.258,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1050.691,
      "heapDeltaBytes": 15925544,
      "heapUsedBytes": 67808860,
      "domNodes": -259,
      "jsHeapTotalBytes": 18223104,
      "scriptDurationMs": 384.88700000000006,
      "eventListeners": -125,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2151.235999999983,
      "styleRecalcs": 70,
      "styleRecalcDurationMs": 16.462,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1055.698,
      "heapDeltaBytes": 19275300,
      "heapUsedBytes": 71319408,
      "domNodes": -260,
      "jsHeapTotalBytes": 17960960,
      "scriptDurationMs": 383.197,
      "eventListeners": -125,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "large-graph-pan",
      "durationMs": 2163.6590000000524,
      "styleRecalcs": 69,
      "styleRecalcDurationMs": 16.618000000000006,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 1097.223,
      "heapDeltaBytes": 13531100,
      "heapUsedBytes": 65614400,
      "domNodes": -259,
      "jsHeapTotalBytes": 19009536,
      "scriptDurationMs": 400.818,
      "eventListeners": -125,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66999999999998,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3147.4570000000313,
      "styleRecalcs": 67,
      "styleRecalcDurationMs": 17.438000000000002,
      "layouts": 60,
      "layoutDurationMs": 7.116,
      "taskDurationMs": 1299.216,
      "heapDeltaBytes": 7758992,
      "heapUsedBytes": 61982768,
      "domNodes": -262,
      "jsHeapTotalBytes": 17231872,
      "scriptDurationMs": 488.205,
      "eventListeners": -125,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3181.2590000000114,
      "styleRecalcs": 65,
      "styleRecalcDurationMs": 14.811000000000002,
      "layouts": 60,
      "layoutDurationMs": 6.7059999999999995,
      "taskDurationMs": 1317.9270000000001,
      "heapDeltaBytes": 10082856,
      "heapUsedBytes": 65315988,
      "domNodes": -266,
      "jsHeapTotalBytes": 15921152,
      "scriptDurationMs": 504.385,
      "eventListeners": -123,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.670000000000012,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "large-graph-zoom",
      "durationMs": 3163.793000000055,
      "styleRecalcs": 66,
      "styleRecalcDurationMs": 17.556999999999995,
      "layouts": 60,
      "layoutDurationMs": 7.431,
      "taskDurationMs": 1316.749,
      "heapDeltaBytes": 7170400,
      "heapUsedBytes": 61646104,
      "domNodes": -263,
      "jsHeapTotalBytes": 17494016,
      "scriptDurationMs": 490.407,
      "eventListeners": -123,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333335,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 2017.4449999999524,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 8.434000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 518.5519999999999,
      "heapDeltaBytes": 3820832,
      "heapUsedBytes": 56436496,
      "domNodes": -259,
      "jsHeapTotalBytes": 16445440,
      "scriptDurationMs": 94.81600000000002,
      "eventListeners": -125,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "minimap-idle",
      "durationMs": 2047.2689999999716,
      "styleRecalcs": 10,
      "styleRecalcDurationMs": 8.333,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 521.679,
      "heapDeltaBytes": 4301040,
      "heapUsedBytes": 56469204,
      "domNodes": -258,
      "jsHeapTotalBytes": 16183296,
      "scriptDurationMs": 98.858,
      "eventListeners": -127,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "minimap-idle",
      "durationMs": 2054.8410000000104,
      "styleRecalcs": 9,
      "styleRecalcDurationMs": 9.006,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 565.529,
      "heapDeltaBytes": 4462512,
      "heapUsedBytes": 56798172,
      "domNodes": -258,
      "jsHeapTotalBytes": 15134720,
      "scriptDurationMs": 110.85600000000001,
      "eventListeners": -127,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 538.5489999999891,
      "styleRecalcs": 47,
      "styleRecalcDurationMs": 10.267,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 342.623,
      "heapDeltaBytes": 6226076,
      "heapUsedBytes": 49320464,
      "domNodes": 19,
      "jsHeapTotalBytes": 13369344,
      "scriptDurationMs": 123.313,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 550.0370000000316,
      "styleRecalcs": 48,
      "styleRecalcDurationMs": 12.158000000000001,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 354.895,
      "heapDeltaBytes": 6681140,
      "heapUsedBytes": 49704044,
      "domNodes": 22,
      "jsHeapTotalBytes": 13631488,
      "scriptDurationMs": 123.295,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-dom-widget-clipping",
      "durationMs": 581.7459999999528,
      "styleRecalcs": 48,
      "styleRecalcDurationMs": 13.13,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 378.444,
      "heapDeltaBytes": 6819356,
      "heapUsedBytes": 49565448,
      "domNodes": 22,
      "jsHeapTotalBytes": 13107200,
      "scriptDurationMs": 129.53799999999998,
      "eventListeners": 8,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2003.7649999999871,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 10.995,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 341.617,
      "heapDeltaBytes": 19909764,
      "heapUsedBytes": 62999584,
      "domNodes": 22,
      "jsHeapTotalBytes": 22806528,
      "scriptDurationMs": 17.705,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.699999999999818
    },
    {
      "name": "subgraph-idle",
      "durationMs": 2013.875999999982,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 13.408999999999999,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 332.702,
      "heapDeltaBytes": 19928432,
      "heapUsedBytes": 63084412,
      "domNodes": 22,
      "jsHeapTotalBytes": 23330816,
      "scriptDurationMs": 17.151,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-idle",
      "durationMs": 1998.9799999999605,
      "styleRecalcs": 11,
      "styleRecalcDurationMs": 10.544999999999998,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 332.901,
      "heapDeltaBytes": 19851672,
      "heapUsedBytes": 63017620,
      "domNodes": 22,
      "jsHeapTotalBytes": 23068672,
      "scriptDurationMs": 14.492,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1976.9929999999931,
      "styleRecalcs": 84,
      "styleRecalcDurationMs": 44.649,
      "layouts": 16,
      "layoutDurationMs": 4.2620000000000005,
      "taskDurationMs": 879.5869999999999,
      "heapDeltaBytes": 11905112,
      "heapUsedBytes": 54599992,
      "domNodes": 73,
      "jsHeapTotalBytes": 22544384,
      "scriptDurationMs": 100.08600000000001,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1992.7149999999756,
      "styleRecalcs": 88,
      "styleRecalcDurationMs": 48.016,
      "layouts": 16,
      "layoutDurationMs": 4.442000000000001,
      "taskDurationMs": 906.6930000000001,
      "heapDeltaBytes": 11898212,
      "heapUsedBytes": 54644868,
      "domNodes": 74,
      "jsHeapTotalBytes": 22544384,
      "scriptDurationMs": 97.74199999999999,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.800000000000182
    },
    {
      "name": "subgraph-mouse-sweep",
      "durationMs": 1988.9670000000024,
      "styleRecalcs": 84,
      "styleRecalcDurationMs": 46.458,
      "layouts": 16,
      "layoutDurationMs": 4.3580000000000005,
      "taskDurationMs": 908.2130000000001,
      "heapDeltaBytes": 11906292,
      "heapUsedBytes": 54972084,
      "domNodes": 73,
      "jsHeapTotalBytes": 22544384,
      "scriptDurationMs": 101.861,
      "eventListeners": 6,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8174.937,
      "styleRecalcs": 251,
      "styleRecalcDurationMs": 41.288000000000004,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3833.5699999999997,
      "heapDeltaBytes": 20099908,
      "heapUsedBytes": 70965276,
      "domNodes": -257,
      "jsHeapTotalBytes": 28446720,
      "scriptDurationMs": 1455.1070000000002,
      "eventListeners": -107,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8183.799000000022,
      "styleRecalcs": 252,
      "styleRecalcDurationMs": 43.116,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3523.5150000000003,
      "heapDeltaBytes": 27587516,
      "heapUsedBytes": 78143472,
      "domNodes": -256,
      "jsHeapTotalBytes": 19795968,
      "scriptDurationMs": 1212.834,
      "eventListeners": -111,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "viewport-pan-sweep",
      "durationMs": 8164.369000000079,
      "styleRecalcs": 252,
      "styleRecalcDurationMs": 45.09,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 3717.2190000000005,
      "heapDeltaBytes": 25078024,
      "heapUsedBytes": 75659492,
      "domNodes": -256,
      "jsHeapTotalBytes": 19533824,
      "scriptDurationMs": 1238.872,
      "eventListeners": -111,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.66333333333332,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 11374.510999999984,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 11364.1,
      "heapDeltaBytes": -34260996,
      "heapUsedBytes": 163406600,
      "domNodes": -8331,
      "jsHeapTotalBytes": 23945216,
      "scriptDurationMs": 548.4630000000001,
      "eventListeners": -16464,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.223333333333358,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 11407.489999999996,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 11396.961,
      "heapDeltaBytes": -28864076,
      "heapUsedBytes": 165870996,
      "domNodes": -8331,
      "jsHeapTotalBytes": 26566656,
      "scriptDurationMs": 567.542,
      "eventListeners": -16464,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.666666666666668,
      "p95FrameDurationMs": 16.700000000000728
    },
    {
      "name": "vue-large-graph-idle",
      "durationMs": 12012.553000000025,
      "styleRecalcs": 0,
      "styleRecalcDurationMs": 0,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 12002.359,
      "heapDeltaBytes": -45927212,
      "heapUsedBytes": 165878560,
      "domNodes": -8330,
      "jsHeapTotalBytes": 27353088,
      "scriptDurationMs": 597.779,
      "eventListeners": -16466,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 18.333333333333332,
      "p95FrameDurationMs": 16.799999999999272
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 13953.480000000014,
      "styleRecalcs": 65,
      "styleRecalcDurationMs": 12.445999999999986,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 13928.448,
      "heapDeltaBytes": -7114048,
      "heapUsedBytes": 186491880,
      "domNodes": -8333,
      "jsHeapTotalBytes": 25956352,
      "scriptDurationMs": 848.064,
      "eventListeners": -16463,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.223333333333358,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 14155.929000000015,
      "styleRecalcs": 68,
      "styleRecalcDurationMs": 12.934999999999974,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 14131.770999999999,
      "heapDeltaBytes": -15903148,
      "heapUsedBytes": 180543292,
      "domNodes": -8331,
      "jsHeapTotalBytes": -520192,
      "scriptDurationMs": 859.0740000000001,
      "eventListeners": -16492,
      "totalBlockingTimeMs": 60,
      "frameDurationMs": 17.219999999999953,
      "p95FrameDurationMs": 16.80000000000291
    },
    {
      "name": "vue-large-graph-pan",
      "durationMs": 13809.871000000043,
      "styleRecalcs": 64,
      "styleRecalcDurationMs": 13.013999999999971,
      "layouts": 0,
      "layoutDurationMs": 0,
      "taskDurationMs": 13786.841,
      "heapDeltaBytes": -34488496,
      "heapUsedBytes": 174312368,
      "domNodes": -8331,
      "jsHeapTotalBytes": 27004928,
      "scriptDurationMs": 845.876,
      "eventListeners": -16460,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 17.776666666666642,
      "p95FrameDurationMs": 33.29999999999927
    },
    {
      "name": "workflow-execution",
      "durationMs": 450.9819999999536,
      "styleRecalcs": 17,
      "styleRecalcDurationMs": 26.669,
      "layouts": 5,
      "layoutDurationMs": 1.437,
      "taskDurationMs": 123.88000000000001,
      "heapDeltaBytes": 4721844,
      "heapUsedBytes": 50584932,
      "domNodes": 165,
      "jsHeapTotalBytes": 524288,
      "scriptDurationMs": 29.137999999999998,
      "eventListeners": 71,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "p95FrameDurationMs": 16.799999999999727
    },
    {
      "name": "workflow-execution",
      "durationMs": 447.89700000001176,
      "styleRecalcs": 17,
      "styleRecalcDurationMs": 23.415000000000003,
      "layouts": 5,
      "layoutDurationMs": 1.2889999999999997,
      "taskDurationMs": 118.13999999999997,
      "heapDeltaBytes": 4505436,
      "heapUsedBytes": 50456580,
      "domNodes": 156,
      "jsHeapTotalBytes": 262144,
      "scriptDurationMs": 27.953000000000007,
      "eventListeners": 71,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "p95FrameDurationMs": 16.700000000000273
    },
    {
      "name": "workflow-execution",
      "durationMs": 445.5880000000434,
      "styleRecalcs": 16,
      "styleRecalcDurationMs": 22.09,
      "layouts": 5,
      "layoutDurationMs": 1.399,
      "taskDurationMs": 122.86,
      "heapDeltaBytes": 4494412,
      "heapUsedBytes": 49101904,
      "domNodes": 156,
      "jsHeapTotalBytes": 786432,
      "scriptDurationMs": 29.360000000000003,
      "eventListeners": 71,
      "totalBlockingTimeMs": 0,
      "frameDurationMs": 16.663333333333338,
      "p95FrameDurationMs": 16.700000000000273
    }
  ]
}

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (5)
browser_tests/tests/vueNodes/widgets/curve/curveWidget.spec.ts (2)

8-11: Double setup() call may cause redundant navigation.

The comfyPageFixture already calls comfyPage.setup() before yielding to tests. Calling setup() again in beforeEach triggers another full page reload and initialization sequence. If VueNodes setting needs to be enabled before setup, consider using setupSettings API before fixture setup or restructuring.

If the double setup is intentional (to apply the VueNodes setting), consider documenting why.

Alternative: Use settings in fixture or clarify intent

If the setting must be applied fresh each test, this is acceptable but adds test overhead. If it's intended to be a one-time setup, the setting could potentially be added to the fixture's setupSettings call.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@browser_tests/tests/vueNodes/widgets/curve/curveWidget.spec.ts` around lines
8 - 11, The test calls comfyPage.setup() in beforeEach even though the comfyPage
fixture already runs setup; remove the redundant call or move the setting
earlier: either delete the comfyPage.setup() call in test.beforeEach and rely on
the fixture, or ensure the VueNodes flag is applied before fixture setup by
using the fixture's setupSettings or calling
comfyPage.settings.setSetting('Comfy.VueNodes.Enabled', true) inside the fixture
initialization (instead of in beforeEach); update or document the intent where
comfyPage.setup() and comfyPage.settings.setSetting are used (or keep both only
if you add a comment explaining why a second setup is required).

112-140: Test misplaced under "Dragging control points" section.

The "no points when disabled" test (lines 112-140) is nested under the "Dragging control points" describe block, but it tests disabled widget behavior, not dragging. There's also a similar test in the dedicated "Disabled state" section (lines 216-223).

Consider either:

  • Moving this test to the "Disabled state" section, or
  • Removing one of the duplicate disabled-state tests if they cover the same behavior
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@browser_tests/tests/vueNodes/widgets/curve/curveWidget.spec.ts` around lines
112 - 140, The test "no points when disabled" in the Curve widget spec is
misplaced under the "Dragging control points" describe block and duplicates
coverage in the "Disabled state" section; either move the test (the whole
test(...) block named 'no points when disabled' that uses curveWidget('Curve' )
and comfyPage.page.evaluate(...) to set widget.options.disabled = true) into the
"Disabled state" describe block, or remove the duplicate test in that section so
only one test asserts await
expect(helper.svgLocator.locator('circle')).toHaveCount(0); keep the test body
and helper usage intact when relocating.
browser_tests/fixtures/helpers/CurveWidgetHelper.ts (2)

12-16: Magic numbers could benefit from named constants or brief comments.

The viewBoxExtent = 1.08 and padFraction = 0.04 values appear in both clickAt and dragPoint. A brief comment explaining these values (presumably matching the SVG viewBox setup in the curve widget component) would help maintainability.

Example: Extract constants with documentation
+// Curve widget SVG viewBox is "0 0 1.08 1.08" with 0.04 unit padding
+const VIEW_BOX_EXTENT = 1.08
+const PAD_FRACTION = 0.04 / VIEW_BOX_EXTENT

 export class CurveWidgetHelper {
   // ...
   async clickAt(curveX: number, curveY: number): Promise<void> {
     const box = await this.svgLocator.boundingBox()
     if (!box) throw new Error('SVG not found')
-    const viewBoxExtent = 1.08
-    const padFraction = 0.04 / viewBoxExtent
-    const usableSize = box.width / viewBoxExtent
+    const usableSize = box.width / VIEW_BOX_EXTENT
-    const screenX = box.x + box.width * padFraction + curveX * usableSize
+    const screenX = box.x + box.width * PAD_FRACTION + curveX * usableSize
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@browser_tests/fixtures/helpers/CurveWidgetHelper.ts` around lines 12 - 16,
Extract the repeated magic numbers into well-named constants (e.g.,
VIEW_BOX_EXTENT = 1.08 and PAD = 0.04) and add a brief comment explaining they
correspond to the SVG viewBox scaling and inner padding used by the CurveWidget
rendering; update both clickAt and dragPoint to use these constants (and compute
padFraction = PAD / VIEW_BOX_EXTENT and usableSize = box.width /
VIEW_BOX_EXTENT) so the intent is clear and the values are maintained in one
place.

53-60: Consider using Playwright's native right-click for more realistic interaction.

The current implementation dispatches a low-level pointerdown event with button: 2. This may not trigger all the event handlers that a real right-click would (e.g., contextmenu event, pointerup).

Since SVG elements in Vue-rendered widgets are not occluded by the canvas overlay, the standard Playwright pattern should work. As per coding guidelines, dispatchEvent('contextmenu') is only needed for canvas-level DOM widgets.

Suggested: Use native click with right button
 async rightClickPoint(pointIndex: number): Promise<void> {
   const circle = this.svgLocator.locator('circle').nth(pointIndex)
-  await circle.dispatchEvent('pointerdown', {
-    bubbles: true,
-    cancelable: true,
-    button: 2
-  })
+  await circle.click({ button: 'right' })
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@browser_tests/fixtures/helpers/CurveWidgetHelper.ts` around lines 53 - 60,
The rightClickPoint helper currently fakes a right-click by dispatching a
'pointerdown' on the circle locator which can miss higher-level events; replace
the manual dispatch with Playwright's native click on the circle locator (use
circle.click({ button: 'right' }) or numeric button: 2) so the full sequence
(pointerdown/pointerup/contextmenu/etc.) is emitted; update the rightClickPoint
method to await that click and remove the manual dispatchEvent usage against
svgLocator.locator('circle').
browser_tests/fixtures/ComfyPage.ts (1)

495-503: Type handling inconsistency with nodeTitleOrId parameter.

The fixture signature accepts string | number, but the implementation casts to string and passes to getNodeByTitle. If a numeric node ID is passed, this will look up by title string (e.g., "1" instead of node ID 1), which may not find the intended node.

Consider either:

  1. Restricting the parameter type to string only, or
  2. Adding logic to handle numeric IDs via a different lookup method
Option 1: Simplify to string-only
-  curveWidget: async ({ comfyPage, page }, use) => {
-    await use((nodeTitleOrId: string | number) => {
-      const node = comfyPage.vueNodes.getNodeByTitle(nodeTitleOrId as string)
+  curveWidget: async ({ comfyPage, page }, use) => {
+    await use((nodeTitle: string) => {
+      const node = comfyPage.vueNodes.getNodeByTitle(nodeTitle)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@browser_tests/fixtures/ComfyPage.ts` around lines 495 - 503, The fixture
curveWidget accepts nodeTitleOrId: string | number but always casts to string
and calls comfyPage.vueNodes.getNodeByTitle, which will mis-handle numeric IDs;
update the implementation to branch on typeof nodeTitleOrId (or change the
parameter to string-only): if it's a number call the appropriate ID lookup
(e.g., comfyPage.vueNodes.getNodeById or equivalent) and if it's a string call
comfyPage.vueNodes.getNodeByTitle so the correct node is returned; ensure the
exported fixture signature matches the chosen behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@browser_tests/fixtures/helpers/CurveWidgetHelper.ts`:
- Around line 62-73: The getCurveData method fails to find curve widgets because
it compares widget.type to 'CURVE' (uppercase); update both checks inside the
page.evaluate callback in getCurveData to compare to lowercase 'curve' (i.e.,
change n.widgets?.some((w) => w.type === 'CURVE') and the subsequent .find((w)
=> w.type === 'CURVE') to use 'curve') so the widget search matches the actual
widget.type values.

In `@browser_tests/tests/vueNodes/widgets/curve/curveWidget.spec.ts`:
- Around line 142-150: The test creates widgets with type 'curve' (lowercase)
but CurveWidgetHelper.getCurveData() checks for w.type === 'CURVE' (uppercase),
causing it to return undefined; update CurveWidgetHelper.getCurveData() to match
the test by using lowercase comparison (e.g., w.type === 'curve') or normalize
both sides (e.g., w.type?.toLowerCase() === 'curve') so the helper reliably
finds the widget created by the tests.
- Around line 243-271: The test injects widget data after reload instead of
verifying actual save persistence; change the flow in the 'Persistence' test to
(1) use curveWidget('Curve').clickAt(...) to add the point via the UI, (2) call
the workflow save helper (e.g. comfyPage.workflow.saveWorkflow()) to persist the
change, (3) reload the workflow via
comfyPage.workflow.loadWorkflow('vueNodes/widgets/curve_widget') (or perform a
full page reload), and (4) assert the persisted data by checking
comfyPage.vueNodes.getNodeByTitle('Curve').locator('circle') has the expected
count; remove the manual page.evaluate injection of node.addWidget and ensure
you invoke the real save API/state rather than injecting after reload.

---

Nitpick comments:
In `@browser_tests/fixtures/ComfyPage.ts`:
- Around line 495-503: The fixture curveWidget accepts nodeTitleOrId: string |
number but always casts to string and calls comfyPage.vueNodes.getNodeByTitle,
which will mis-handle numeric IDs; update the implementation to branch on typeof
nodeTitleOrId (or change the parameter to string-only): if it's a number call
the appropriate ID lookup (e.g., comfyPage.vueNodes.getNodeById or equivalent)
and if it's a string call comfyPage.vueNodes.getNodeByTitle so the correct node
is returned; ensure the exported fixture signature matches the chosen behavior.

In `@browser_tests/fixtures/helpers/CurveWidgetHelper.ts`:
- Around line 12-16: Extract the repeated magic numbers into well-named
constants (e.g., VIEW_BOX_EXTENT = 1.08 and PAD = 0.04) and add a brief comment
explaining they correspond to the SVG viewBox scaling and inner padding used by
the CurveWidget rendering; update both clickAt and dragPoint to use these
constants (and compute padFraction = PAD / VIEW_BOX_EXTENT and usableSize =
box.width / VIEW_BOX_EXTENT) so the intent is clear and the values are
maintained in one place.
- Around line 53-60: The rightClickPoint helper currently fakes a right-click by
dispatching a 'pointerdown' on the circle locator which can miss higher-level
events; replace the manual dispatch with Playwright's native click on the circle
locator (use circle.click({ button: 'right' }) or numeric button: 2) so the full
sequence (pointerdown/pointerup/contextmenu/etc.) is emitted; update the
rightClickPoint method to await that click and remove the manual dispatchEvent
usage against svgLocator.locator('circle').

In `@browser_tests/tests/vueNodes/widgets/curve/curveWidget.spec.ts`:
- Around line 8-11: The test calls comfyPage.setup() in beforeEach even though
the comfyPage fixture already runs setup; remove the redundant call or move the
setting earlier: either delete the comfyPage.setup() call in test.beforeEach and
rely on the fixture, or ensure the VueNodes flag is applied before fixture setup
by using the fixture's setupSettings or calling
comfyPage.settings.setSetting('Comfy.VueNodes.Enabled', true) inside the fixture
initialization (instead of in beforeEach); update or document the intent where
comfyPage.setup() and comfyPage.settings.setSetting are used (or keep both only
if you add a comment explaining why a second setup is required).
- Around line 112-140: The test "no points when disabled" in the Curve widget
spec is misplaced under the "Dragging control points" describe block and
duplicates coverage in the "Disabled state" section; either move the test (the
whole test(...) block named 'no points when disabled' that uses
curveWidget('Curve' ) and comfyPage.page.evaluate(...) to set
widget.options.disabled = true) into the "Disabled state" describe block, or
remove the duplicate test in that section so only one test asserts await
expect(helper.svgLocator.locator('circle')).toHaveCount(0); keep the test body
and helper usage intact when relocating.
🪄 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: CHILL

Plan: Pro

Run ID: c5e040da-0490-4c4c-ba74-297a994aefde

📥 Commits

Reviewing files that changed from the base of the PR and between 17d2870 and fd6eb57.

📒 Files selected for processing (4)
  • browser_tests/assets/vueNodes/widgets/curve_widget.json
  • browser_tests/fixtures/ComfyPage.ts
  • browser_tests/fixtures/helpers/CurveWidgetHelper.ts
  • browser_tests/tests/vueNodes/widgets/curve/curveWidget.spec.ts

Comment on lines +62 to +73
async getCurveData(): Promise<
{ points: [number, number][]; interpolation: string } | undefined
> {
return this.page.evaluate(() => {
const node = window.app!.graph.nodes.find((n) =>
n.widgets?.some((w) => w.type === 'CURVE')
)
return node?.widgets?.find((w) => w.type === 'CURVE')?.value as
| { points: [number, number][]; interpolation: string }
| undefined
})
}
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.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for how curve widgets define their type in the codebase
rg -n "type.*['\"]curve['\"]" --type=ts --type=vue -i
rg -n "type.*['\"]CURVE['\"]" --type=ts --type=vue

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 125


🏁 Script executed:

#!/bin/bash
# Search for curve widget type definitions - fix syntax
rg -i "type.*curve" --type ts --type py -A 2 -B 2

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 7627


🏁 Script executed:

#!/bin/bash
# Look for CURVE widget definition specifically
rg "CURVE" -A 2 -B 2 --type ts --type py

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 4297


🏁 Script executed:

#!/bin/bash
# Check test file to see what widget type is actually used
fd "\.spec\.ts$" | xargs rg -l "curve\|CURVE" | head -5

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 52


🏁 Script executed:

#!/bin/bash
# Look for CurveWidget implementation
fd "Curve.*Widget" -type f

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 240


Change getCurveData widget type search from 'CURVE' to 'curve'

The method searches for w.type === 'CURVE', but widget objects have type set to lowercase 'curve'. The uppercase 'CURVE' is only used as a widget registry alias and in node definition schemas, not in the actual widget type property. This mismatch prevents the method from finding curve widgets. Update both checks to use lowercase 'curve'.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@browser_tests/fixtures/helpers/CurveWidgetHelper.ts` around lines 62 - 73,
The getCurveData method fails to find curve widgets because it compares
widget.type to 'CURVE' (uppercase); update both checks inside the page.evaluate
callback in getCurveData to compare to lowercase 'curve' (i.e., change
n.widgets?.some((w) => w.type === 'CURVE') and the subsequent .find((w) =>
w.type === 'CURVE') to use 'curve') so the widget search matches the actual
widget.type values.

Comment on lines +142 to +150
test('drag clamps to [0, 1]', async ({ curveWidget }) => {
const helper = curveWidget('Curve')
await helper.dragPoint(0, -0.5, 1.5)
const data = await helper.getCurveData()
expect(data?.points[0][0]).toBeGreaterThanOrEqual(-0.001)
expect(data?.points[0][0]).toBeLessThanOrEqual(1.001)
expect(data?.points[0][1]).toBeGreaterThanOrEqual(-0.001)
expect(data?.points[0][1]).toBeLessThanOrEqual(1.001)
})
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.

⚠️ Potential issue | 🟡 Minor

Widget type case mismatch between tests and helper.

The test adds widgets with type: 'curve' (lowercase, line 20-21, 277), but CurveWidgetHelper.getCurveData() searches for w.type === 'CURVE' (uppercase). This mismatch means getCurveData() will return undefined for widgets created by these tests.

Either the helper should use lowercase 'curve', or the test should add widgets with uppercase 'CURVE'.

Fix in CurveWidgetHelper.ts
-        n.widgets?.some((w) => w.type === 'CURVE')
+        n.widgets?.some((w) => w.type === 'curve')
       )
-      return node?.widgets?.find((w) => w.type === 'CURVE')?.value as
+      return node?.widgets?.find((w) => w.type === 'curve')?.value as
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@browser_tests/tests/vueNodes/widgets/curve/curveWidget.spec.ts` around lines
142 - 150, The test creates widgets with type 'curve' (lowercase) but
CurveWidgetHelper.getCurveData() checks for w.type === 'CURVE' (uppercase),
causing it to return undefined; update CurveWidgetHelper.getCurveData() to match
the test by using lowercase comparison (e.g., w.type === 'curve') or normalize
both sides (e.g., w.type?.toLowerCase() === 'curve') so the helper reliably
finds the widget created by the tests.

Comment on lines +243 to +271
test.describe('Persistence', { tag: '@workflow' }, () => {
test('data persists after save/reload', async ({
comfyPage,
curveWidget
}) => {
await curveWidget('Curve').clickAt(0.5, 0.8)
await comfyPage.workflow.loadWorkflow('vueNodes/widgets/curve_widget')
await comfyPage.page.evaluate(() => {
const graph = window.graph as TestGraphAccess
const node = graph._nodes_by_id['1']
node.addWidget(
'curve',
'tone_curve',
{
points: [
[0, 0],
[0.5, 0.8],
[1, 1]
],
interpolation: 'monotone_cubic'
},
() => {}
)
})
await expect(
comfyPage.vueNodes.getNodeByTitle('Curve').locator('circle')
).toHaveCount(3)
})
})
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.

⚠️ Potential issue | 🟡 Minor

Test doesn't actually verify persistence - it injects data after reload.

The test claims to verify "data persists after save/reload", but:

  1. Line 248 adds a point via UI
  2. Line 249 immediately reloads the workflow (discarding the UI change)
  3. Lines 250-266 manually inject widget data via page.evaluate
  4. Lines 267-269 assert the injected data renders

This tests rendering of injected data, not actual save/reload persistence. To test persistence, you'd need to:

  1. Add point via UI
  2. Save the workflow
  3. Reload the page/workflow
  4. Verify the point persists from saved state
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@browser_tests/tests/vueNodes/widgets/curve/curveWidget.spec.ts` around lines
243 - 271, The test injects widget data after reload instead of verifying actual
save persistence; change the flow in the 'Persistence' test to (1) use
curveWidget('Curve').clickAt(...) to add the point via the UI, (2) call the
workflow save helper (e.g. comfyPage.workflow.saveWorkflow()) to persist the
change, (3) reload the workflow via
comfyPage.workflow.loadWorkflow('vueNodes/widgets/curve_widget') (or perform a
full page reload), and (4) assert the persisted data by checking
comfyPage.vueNodes.getNodeByTitle('Curve').locator('circle') has the expected
count; remove the manual page.evaluate injection of node.addWidget and ensure
you invoke the real save API/state rather than injecting after reload.

@jtydhr88
Copy link
Copy Markdown
Collaborator

jtydhr88 commented Apr 4, 2026

I already have #10730 which included basic tests for curve, can you compare which one we should keep?

@jtydhr88
Copy link
Copy Markdown
Collaborator

jtydhr88 commented Apr 4, 2026

also, likely all yours tests failed, maybe it has the same issue I had before

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

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants