Skip to content

Commit 3250945

Browse files
sainthkhemilyrohrboughmjhenkes
authored
fix: cy.contains() ignores <style> and <script> without removing them. (#19424)
* fix * Merge tests. * fix * Apply suggestions from code review Co-authored-by: Emily Rohrbough <[email protected]> * kick off build again Co-authored-by: Emily Rohrbough <[email protected]> Co-authored-by: Matt Henkes <[email protected]>
1 parent 593d4b8 commit 3250945

File tree

3 files changed

+60
-20
lines changed

3 files changed

+60
-20
lines changed

packages/driver/cypress/fixtures/content-in-body.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,25 @@ <h1>Script and Style in the body</h1>
1717
h1 { font-size: 32px }
1818
</style>
1919
</div>
20+
21+
<!--
22+
// https://github.com/cypress-io/cypress/issues/19377
23+
Below is added to ensure `style`, `script` tags are not removed by `cy.contains()` command.
24+
-->
25+
<p>Hello</p>
26+
<button id="my_button_1" style="display: none;">I'm a button</button>
27+
<button id="my_button_2">Click me</button>
28+
<div id="result"></div>
29+
<style>
30+
button#my_button_1 {
31+
background-color: red;
32+
display: inline !important;
33+
}
34+
</style>
35+
<script id="my_script">
36+
document.getElementById('my_button_2').addEventListener('click', function() {
37+
document.getElementById('result').innerHTML = 'This is the result';
38+
});
39+
</script>
2040
</body>
2141
</html>

packages/driver/cypress/integration/commands/querying_spec.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,6 +1955,7 @@ space
19551955
})
19561956
})
19571957

1958+
// https://github.com/cypress-io/cypress/issues/14861
19581959
describe('ignores style and script tag in body', () => {
19591960
it('style', (done) => {
19601961
cy.on('fail', (err) => {
@@ -1977,6 +1978,35 @@ space
19771978
cy.visit('fixtures/content-in-body.html')
19781979
cy.contains('I am in the script tag in body', { timeout: 500 })
19791980
})
1981+
1982+
// https://github.com/cypress-io/cypress/issues/19377
1983+
describe('cy.contains() does not remove <style> and <script> tags', () => {
1984+
it('cy.contains() does not remove style tags from the DOM', () => {
1985+
cy.visit('fixtures/content-in-body.html')
1986+
1987+
cy.get('button#my_button_1').should('be.visible')
1988+
cy.contains('Hello').should('be.visible')
1989+
cy.get('button#my_button_1').should('be.visible')
1990+
})
1991+
1992+
it('cy.contains() does not remove script tags from the DOM', () => {
1993+
cy.visit('fixtures/content-in-body.html')
1994+
1995+
cy.window().then((win) => {
1996+
const scriptElement = win.document.getElementById('my_script')
1997+
1998+
expect(scriptElement?.id).to.equal('my_script')
1999+
})
2000+
2001+
cy.get('button#my_button_2').click()
2002+
cy.contains('This is the result').should('be.visible')
2003+
cy.window().then((win) => {
2004+
const scriptElement = win.document.getElementById('my_script')
2005+
2006+
expect(scriptElement?.id).to.equal('my_script')
2007+
})
2008+
})
2009+
})
19802010
})
19812011

19822012
describe('subject contains text nodes', () => {

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

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import $document from '../document'
44
import $jquery from '../jquery'
55
import { getTagName } from './elementHelpers'
66
import { isWithinShadowRoot, getShadowElementFromPoint } from './shadow'
7-
import { normalizeWhitespaces, escapeQuotes, isSelector } from './utils'
7+
import { normalizeWhitespaces, escapeQuotes } from './utils'
88

99
/**
1010
* Find Parents relative to an initial element
@@ -125,10 +125,16 @@ export const getFirstDeepestElement = ($el: JQuery, index = 0) => {
125125
const $current = $el.slice(index, index + 1)
126126
const $next = $el.slice(index + 1, index + 2)
127127

128-
if (!$next) {
128+
if (!$next || $current.length === 0) {
129129
return $current
130130
}
131131

132+
// https://github.com/cypress-io/cypress/issues/14861
133+
// filter out the <script> and <style> tags
134+
if ($current && ['SCRIPT', 'STYLE'].includes($current.prop('tagName'))) {
135+
return getFirstDeepestElement($el, index + 1)
136+
}
137+
132138
// does current contain next?
133139
if ($.contains($current.get(0), $next.get(0))) {
134140
return getFirstDeepestElement($el, index + 1)
@@ -217,20 +223,6 @@ export const getElements = ($el) => {
217223
return els
218224
}
219225

220-
// Remove <style> and <script> elements inside <body>. Even though the contains
221-
// selector avoids selecting them with :not(script,style), it will find the
222-
// text anyway and attribute it to the <body>
223-
// https://github.com/cypress-io/cypress/issues/14861
224-
const removeScriptAndStyleElements = (elem) => {
225-
const $elem = $(elem)
226-
227-
if (!isSelector($elem, 'body')) return elem
228-
229-
$elem.find('script,style').remove()
230-
231-
return $elem[0]
232-
}
233-
234226
export const getContainsSelector = (text, filter = '', options: {
235227
matchCase?: boolean
236228
} = {}) => {
@@ -252,14 +244,12 @@ export const getContainsSelector = (text, filter = '', options: {
252244

253245
// taken from jquery's normal contains method
254246
cyContainsSelector = function (elem) {
255-
elem = removeScriptAndStyleElements(elem)
256-
let testText = normalizeWhitespaces(elem)
247+
const testText = normalizeWhitespaces(elem)
257248

258249
return text.test(testText)
259250
}
260251
} else if (_.isString(text)) {
261252
cyContainsSelector = function (elem) {
262-
elem = removeScriptAndStyleElements(elem)
263253
let testText = normalizeWhitespaces(elem)
264254

265255
if (!options.matchCase) {
@@ -284,7 +274,7 @@ export const getContainsSelector = (text, filter = '', options: {
284274
const textToFind = escapedText.includes(`\'`) ? `"${escapedText}"` : `'${escapedText}'`
285275

286276
// use custom cy-contains selector that is registered above
287-
return `${filter}:not(script,style):cy-contains(${textToFind}), ${filter}[type='submit'][value~=${textToFind}]`
277+
return `${filter}:cy-contains(${textToFind}), ${filter}[type='submit'][value~=${textToFind}]`
288278
})
289279

290280
return selectors.join()

0 commit comments

Comments
 (0)