Skip to content

Conversation

@jennifer-shehane
Copy link
Member

@jennifer-shehane jennifer-shehane commented Nov 13, 2025

Additional details

Improves performance of hovering or pinning a command to highlight elements within a snapshot. The improvements would be most evident when the command queries A LOT of elements. There are a few strategies employed here:

  • Reducing the calls to getComputedStyles
  • Batching the calls to get offset for element we want to highlight - so the first 50 highlights WILL SHOW UP FIRST, and the other highlights will asynchronously come in. So, when the command shows as 'pinned', it is possible that all of the elements are not highlighted at that point.
  • Cancel the asynchronous calls to highlight the el when another call is made to highlight elements on another snapshot.

Steps to test

  • Open a test that targets 3,000 items that have distinct positions in the DOM

How has the user experience changed?

Before

When hovering/clicking to pin a snapshot that targets 3,000 elements completely locks up the UI for 15+ seconds. You cannot hover or pin any other snapshots during this time - or see any highlights.

Screen.Recording.2025-11-14.at.12.42.00.PM.mov

After

When hovering/clicking to pin a snapshot that targets 3,000 element - highlights and pinning shows up within 2 seconds (although ALL of the elements are not done highlighting). You can see when all of the elements finish highlighting in my video where the console.log logs when it's complete.

Screen.Recording.2025-11-14.at.12.38.48.PM.mov

You can click and hover around fairly quickly (feels a little laggy) since the previous batch of highlighting now cancels when you go to highlight other snapshots.

Screen.Recording.2025-11-14.at.12.48.46.PM.mov

PR Tasks


Note

Speeds up Command Log snapshot highlighting by caching computed styles, batching DOM/offset updates, and canceling stale operations; adds tests and updates changelog, plus minor driver blackout and dimensions optimizations.

  • Runner (AUT iframe):
    • Batch highlight rendering: collect containers off-DOM, append via DocumentFragment, then position in rAF batches using setOffset; cancel stale runs via an operation id.
    • _addElementBoxModelLayers now accepts optional dimensions, avoids getComputedStyle, applies transform/zIndex from getElementDimensions, stores positions in data-* for later offsetting; removed internal offset sizing helper.
    • highlightEl filters hidden/zero-size via cached offsetWidth/offsetHeight and display; removeHighlights uses native query/remove; DOM queries during restore are cached; _replaceHeadStyles accepts optional $head.
  • Utilities:
    • getElementDimensions calls getComputedStyle once, returns padding/border/margin, display, transform, zIndex, and offsetWidth/offsetHeight; setOffset and getOffset optimized (cached style, defaultView guard).
    • Added tests for getElementDimensions and _addElementBoxModelLayers to assert single getComputedStyle call and no extra calls when dimensions provided.
  • Driver:
    • blackout: replace string-built HTML with native div creation and cssText assignment.
    • dom/dimensions: cache getComputedStyle once; read numeric styles from cached declaration.
  • Docs:
    • Changelog entry for improved snapshot highlight performance in 15.7.1 (also noted under 15.7.0).

Written by Cursor Bugbot for commit 267486d. This will update automatically on new commits. Configure here.

@jennifer-shehane jennifer-shehane self-assigned this Nov 13, 2025
@jennifer-shehane jennifer-shehane changed the title perf: reduce calls to getComputedStyles for element dimension calculations perf: reduce calls to getComputedStyles for element dimension calculations (used for snapshots) Nov 13, 2025
@cypress
Copy link

cypress bot commented Nov 13, 2025

cypress    Run #67454

Run Properties:  status check passed Passed #67454  •  git commit 267486dca3: remove extra line
Project cypress
Branch Review snapshot-reduce-get-computed-style
Run status status check passed Passed #67454
Run duration 19m 19s
Commit git commit 267486dca3: remove extra line
Committer Jennifer Shehane
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 11
Tests that did not run due to a developer annotating a test with .skip  Pending 1098
Tests that did not run due to a failure in a mocha hook  Skipped 4
Tests that passed  Passing 26697
View all changes introduced in this branch ↗︎

Warning

Partial Report: The results for the Application Quality reports may be incomplete.

UI Coverage  45.74%
  Untested elements 186  
  Tested elements 161  
Accessibility  98%
  Failed rules  4 critical   8 serious   2 moderate   2 minor
  Failed elements 101  

@jennifer-shehane jennifer-shehane changed the title perf: reduce calls to getComputedStyles for element dimension calculations (used for snapshots) perf: improve performance of pinning snapshots during hover / pin Nov 14, 2025
@@ -0,0 +1,137 @@
import { AutIframe } from './aut-iframe'
Copy link
Member Author

@jennifer-shehane jennifer-shehane Nov 14, 2025

Choose a reason for hiding this comment

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

I don't think these are in an optimal form for unit tests, but it doesn't seem we have vitest or any other convention here but Cypress tests. I'd like to have a test for this, so welcome to if there's a better way to do this.

@@ -0,0 +1,58 @@
import { getElementDimensions } from './dimensions'
Copy link
Member Author

Choose a reason for hiding this comment

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

Another 'unit' test

Comment on lines +11 to +17
const style = `border: none !important; margin: 0 !important; padding: 0 !important; position: absolute; top: ${top}px; left: ${left}px; width: ${width}px; height: ${height}px; background-color: black; z-index: 2147483647;`

const div = document.createElement('div')

div.className = '__cypress-blackout'
div.style.cssText = style
$body.append(div)
Copy link
Member Author

Choose a reason for hiding this comment

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

Probably not helpful much, but looked into this function a bit for the blackout of screenshots.


const getElementDimensions = ($el: JQuery<HTMLElement>) => {
const el: HTMLElement = $el.get(0)

Copy link
Member Author

Choose a reason for hiding this comment

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

We should consolidate these but I didn't want to get distracted with this.

@cacieprins
Copy link
Contributor

cacieprins commented Nov 19, 2025

Looks good.

Some thoughts on further performance improvement potential:

  • create an isolated container for the highlights, leveraging contain:layout, so that each fragment addition doesn't cause a reflow/recalc of the AUT
  • only render highlights for elements that are in view, using an IntersectionObserver to detect when elements that should be highlighted become visible (e.g., within the aut iframe scroll position)
  • use a canvas instead, so the browser layout engine need not be involved in painting the highlights - we just draw the highlights manually.

@jennifer-shehane
Copy link
Member Author

@cacieprins Love the ideas. I hadn't thought about intersection observer but that could be perfect - might need more robust tests. It's just painting SO many highlights that aren't even on the screen.

I'd probably prioritize perf improvements that apply to both run mode and open mode over diving deeper into the snapshot improvements though.

@jennifer-shehane
Copy link
Member Author

Oh I have some legit failures I need to fix in CT tests.

**Performance:**

- Limits the number of matched elements that are tested for visibility when added to a command log entry. Fixes a crash scenario related to rapid successive DOM additions in conjunction with a large number of elements returned from a query. Addressed in [#32937](https://github.com/cypress-io/cypress/pull/32937).
- Improved performance when viewing command snapshots in the Command Log. Element highlighting is now significantly faster, especially when highlighting multiple elements or complex pages. This is achieved by reducing redundant style calculations and batching DOM operations to minimize browser reflows. Addressed in [#32951](https://github.com/cypress-io/cypress/pull/32951).
Copy link

Choose a reason for hiding this comment

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

Bug: Duplicate changelog entry in two versions

The same performance improvement entry for PR #32951 appears in both version 15.7.1 (line 8) and version 15.7.0 (line 17). Since version 15.7.0 was already released on 11/19/2025, this entry should only appear in the unreleased version 15.7.1. The duplicate entry in 15.7.0 needs to be removed.

Fix in Cursor Fix in Web

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants