Skip to content

Commit ce17a44

Browse files
fix: issue with font flooding (#27860)
1 parent 154311a commit ce17a44

File tree

6 files changed

+78
-14
lines changed

6 files changed

+78
-14
lines changed

cli/CHANGELOG.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ _Released 09/19/2023 (PENDING)_
77

88
- Introduces new layout for Runs page providing additional run information. Addresses [#27203](https://github.com/cypress-io/cypress/issues/27203).
99

10+
**Bugfixes:**
11+
12+
- Fixed an issue where actionability checks trigger a flood of font requests. Removing the font requests has the potential to improve performance and removes clutter from Test Replay. Addressed in [#27860](https://github.com/cypress-io/cypress/pull/27860)
13+
1014
## 13.2.0
1115

1216
_Released 09/12/2023_
@@ -17,7 +21,7 @@ _Released 09/12/2023_
1721

1822
**Bugfixes:**
1923

20-
- Edge cases where `cy.intercept()` would not properly intercept and asset response bodies would not properly be captured for test replay have been addressed. Addressed in [#27771](https://github.com/cypress-io/cypress/pull/27771).
24+
- Edge cases where `cy.intercept()` would not properly intercept and asset response bodies would not properly be captured for Test Replay have been addressed. Addressed in [#27771](https://github.com/cypress-io/cypress/pull/27771).
2125
- Fixed an issue where `enter`, `keyup`, and `space` events were not triggering `click` events properly in some versions of Firefox. Addressed in [#27715](https://github.com/cypress-io/cypress/pull/27715).
2226
- Fixed a regression in `13.0.0` where tests using Basic Authorization can potentially hang indefinitely on chromium browsers. Addressed in [#27781](https://github.com/cypress-io/cypress/pull/27781).
2327
- Fixed a regression in `13.0.0` where component tests using an intercept that matches all requests can potentially hang indefinitely. Addressed in [#27788](https://github.com/cypress-io/cypress/pull/27788).
@@ -37,7 +41,7 @@ _Released 08/31/2023_
3741
**Bugfixes:**
3842

3943
- Fixed a regression introduced in Cypress [13.0.0](#13-0-0) where the [Module API](https://docs.cypress.io/guides/guides/module-api), [`after:run`](https://docs.cypress.io/api/plugins/after-run-api), and [`after:spec`](https://docs.cypress.io/api/plugins/after-spec-api) results did not include the `stats.skipped` field for each run result. Fixes [#27694](https://github.com/cypress-io/cypress/issues/27694). Addressed in [#27695](https://github.com/cypress-io/cypress/pull/27695).
40-
- Individual CDP errors that occur while capturing data for test replay will no longer prevent the entire run from being available. Addressed in [#27709](https://github.com/cypress-io/cypress/pull/27709).
44+
- Individual CDP errors that occur while capturing data for Test Replay will no longer prevent the entire run from being available. Addressed in [#27709](https://github.com/cypress-io/cypress/pull/27709).
4145
- Fixed an issue where the release date on the `v13` landing page was a day behind. Fixed in [#27711](https://github.com/cypress-io/cypress/pull/27711).
4246
- Fixed an issue where fatal protocol errors would leak between specs causing all subsequent specs to fail to upload protocol information. Fixed in [#27720](https://github.com/cypress-io/cypress/pull/27720)
4347
- Updated `plist` from `3.0.6` to `3.1.0` to address [CVE-2022-37616](https://github.com/advisories/GHSA-9pgh-qqpf-7wqj) and [CVE-2022-39353](https://github.com/advisories/GHSA-crh6-fp67-6883). Fixed in [#27710](https://github.com/cypress-io/cypress/pull/27710).

packages/driver/cypress/e2e/commands/actions/click.cy.js

+4
Original file line numberDiff line numberDiff line change
@@ -1678,12 +1678,16 @@ describe('src/cy/commands/actions/click', () => {
16781678
it('can scroll to and click elements in html with scroll-behavior: smooth', () => {
16791679
cy.get('html').invoke('css', 'scrollBehavior', 'smooth')
16801680
cy.get('#table tr:first').click()
1681+
// Validate that the scrollBehavior is still smooth even after the actionability fixes we do
1682+
cy.get('html').invoke('css', 'scrollBehavior').then((scrollBehavior) => expect(scrollBehavior).to.eq('smooth'))
16811683
})
16821684

16831685
// https://github.com/cypress-io/cypress/issues/3200
16841686
it('can scroll to and click elements in ancestor element with scroll-behavior: smooth', () => {
16851687
cy.get('#dom').invoke('css', 'scrollBehavior', 'smooth')
16861688
cy.get('#table tr:first').click()
1689+
// Validate that the scrollBehavior is still smooth even after the actionability fixes we do
1690+
cy.get('#dom').invoke('css', 'scrollBehavior').then((scrollBehavior) => expect(scrollBehavior).to.eq('smooth'))
16871691
})
16881692
})
16891693
})

packages/driver/cypress/e2e/dom/visibility.cy.ts

+24-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe('src/cypress/dom/visibility', () => {
5353
expect(fn()).to.be.true
5454
})
5555

56-
it('returns false window and body > window height', () => {
56+
it('returns false if window and body < window height', () => {
5757
cy.$$('body').html('<div>foo</div>')
5858

5959
const win = cy.state('window')
@@ -65,6 +65,29 @@ describe('src/cypress/dom/visibility', () => {
6565
expect(fn()).to.be.false
6666
})
6767

68+
it('returns true if document element and body > window height', function () {
69+
this.add('<div style="height: 1000px; width: 10px;" />')
70+
const documentElement = Cypress.dom.wrap(cy.state('document').documentElement)
71+
72+
const fn = () => {
73+
return dom.isScrollable(documentElement)
74+
}
75+
76+
expect(fn()).to.be.true
77+
})
78+
79+
it('returns false if document element and body < window height', () => {
80+
cy.$$('body').html('<div>foo</div>')
81+
82+
const documentElement = Cypress.dom.wrap(cy.state('document').documentElement)
83+
84+
const fn = () => {
85+
return dom.isScrollable(documentElement)
86+
}
87+
88+
expect(fn()).to.be.false
89+
})
90+
6891
it('returns false el is not scrollable', function () {
6992
const noScroll = this.add(`\
7093
<div style="height: 100px; overflow: auto;">

packages/driver/src/cy/actionability.ts

+33-11
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import $utils from './../cypress/utils'
88
import type { ElWindowPostion, ElViewportPostion, ElementPositioning } from '../dom/coordinates'
99
import $elements from '../dom/elements'
1010
import $errUtils from '../cypress/error_utils'
11+
import { callNativeMethod, getNativeProp } from '../dom/elements/nativeProps'
1112
const debug = debugFn('cypress:driver:actionability')
1213

1314
const delay = 50
@@ -460,24 +461,46 @@ const verify = function (cy, $el, config, options, callbacks: VerifyCallbacks) {
460461
// make scrolling occur instantly. we do this by adding a style tag
461462
// and then removing it after we finish scrolling
462463
// https://github.com/cypress-io/cypress/issues/3200
463-
const addScrollBehaviorFix = () => {
464-
let style
464+
const addScrollBehaviorFix = (element: JQuery<HTMLElement>) => {
465+
const affectedParents: Map<HTMLElement, string> = new Map()
465466

466467
try {
467-
const doc = $el.get(0).ownerDocument
468+
let parent: JQuery<HTMLElement> | null = element
468469

469-
style = doc.createElement('style')
470-
style.innerHTML = '* { scroll-behavior: inherit !important; }'
471-
// there's guaranteed to be a <script> tag, so that's the safest thing
472-
// to query for and add the style tag after
473-
doc.querySelector('script').after(style)
470+
do {
471+
if ($dom.isScrollable(parent)) {
472+
const parentElement = parent[0]
473+
const style = getNativeProp(parentElement, 'style')
474+
const styles = getComputedStyle(parentElement)
475+
476+
if (styles.scrollBehavior === 'smooth') {
477+
affectedParents.set(parentElement, callNativeMethod(style, 'getStyleProperty', 'scroll-behavior'))
478+
callNativeMethod(style, 'setStyleProperty', 'scroll-behavior', 'auto')
479+
}
480+
}
481+
482+
parent = $dom.getFirstScrollableParent(parent)
483+
} while (parent)
474484
} catch (err) {
475485
// the above shouldn't error, but out of an abundance of caution, we
476486
// ignore any errors since this fix isn't worth failing the test over
477487
}
478488

479489
return () => {
480-
if (style) style.remove()
490+
for (const [parent, value] of affectedParents) {
491+
const style = getNativeProp(parent, 'style')
492+
493+
if (value === '') {
494+
if (callNativeMethod(style, 'getStyleProperty', 'length') === 1) {
495+
callNativeMethod(parent, 'removeAttribute', 'style')
496+
} else {
497+
callNativeMethod(style, 'removeProperty', 'scroll-behavior')
498+
}
499+
} else {
500+
callNativeMethod(style, 'setStyleProperty', 'scroll-behavior', value)
501+
}
502+
}
503+
affectedParents.clear()
481504
}
482505
}
483506

@@ -500,8 +523,7 @@ const verify = function (cy, $el, config, options, callbacks: VerifyCallbacks) {
500523
if (options.scrollBehavior !== false) {
501524
// scroll the element into view
502525
const scrollBehavior = scrollBehaviorOptionsMap[options.scrollBehavior]
503-
504-
const removeScrollBehaviorFix = addScrollBehaviorFix()
526+
const removeScrollBehaviorFix = addScrollBehaviorFix($el)
505527

506528
debug('scrollIntoView:', $el[0])
507529
$el.get(0).scrollIntoView({ block: scrollBehavior })

packages/driver/src/dom/elements/complexElements.ts

+6
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,12 @@ export const isScrollable = ($el) => {
290290
return false
291291
}
292292

293+
const documentElement = $document.getDocumentFromElement(el).documentElement
294+
295+
if (el === documentElement) {
296+
return checkDocumentElement($window.getWindowByElement(el), el)
297+
}
298+
293299
// if we're any other element, we do some css calculations
294300
// to see that the overflow is correct and the scroll
295301
// area is larger than the actual height or width

packages/driver/src/dom/elements/nativeProps.ts

+5
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ const nativeGetters = {
207207
body: descriptor('Document', 'body').get,
208208
frameElement: Object.getOwnPropertyDescriptor(window, 'frameElement')!.get,
209209
maxLength: _getMaxLength,
210+
style: descriptor('HTMLElement', 'style').get,
210211
}
211212

212213
const nativeSetters = {
@@ -224,12 +225,16 @@ const nativeMethods = {
224225
execCommand: window.document.execCommand,
225226
getAttribute: window.Element.prototype.getAttribute,
226227
setAttribute: window.Element.prototype.setAttribute,
228+
removeAttribute: window.Element.prototype.removeAttribute,
227229
setSelectionRange: _nativeSetSelectionRange,
228230
modify: window.Selection.prototype.modify,
229231
focus: _nativeFocus,
230232
hasFocus: window.document.hasFocus,
231233
blur: _nativeBlur,
232234
select: _nativeSelect,
235+
getStyleProperty: window.CSSStyleDeclaration.prototype.getPropertyValue,
236+
setStyleProperty: window.CSSStyleDeclaration.prototype.setProperty,
237+
removeStyleProperty: window.CSSStyleDeclaration.prototype.removeProperty,
233238
}
234239

235240
export const getNativeProp = function<T, K extends keyof T> (obj: T, prop: K): T[K] {

0 commit comments

Comments
 (0)