Skip to content

Commit

Permalink
fix pollution of :contains pseudo selector (#6434)
Browse files Browse the repository at this point in the history
* fix overriding :contains pseudo selector

* dont inject livereload inside spec iframe...

* add issue comment
  • Loading branch information
kuceb committed Feb 14, 2020
1 parent 42cc628 commit b8d6a6d
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 65 deletions.
64 changes: 2 additions & 62 deletions packages/driver/src/cy/commands/querying.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,10 @@
const _ = require('lodash')
const $ = require('jquery')
const Promise = require('bluebird')

const $dom = require('../../dom')
const $errUtils = require('../../cypress/error_utils')

const $expr = $.expr[':']

const $contains = $expr.contains

const restoreContains = () => {
return $expr.contains = $contains
}

const whitespaces = /\s+/g

module.exports = (Commands, Cypress, cy) => {
// restore initially when a run starts
restoreContains()

// restore before each test and whenever we stop
Cypress.on('test:before:run', restoreContains)
Cypress.on('stop', restoreContains)

Commands.addAll({
focused (options = {}) {
_.defaults(options, {
Expand Down Expand Up @@ -483,46 +465,9 @@ module.exports = (Commands, Cypress, cy) => {
options._log.set({ $el })
}

// When multiple space characters are considered as a single whitespace in all tags except <pre>.
const normalizeWhitespaces = (elem) => {
let testText = elem.textContent || elem.innerText || $.text(elem)

if (elem.tagName === 'PRE') {
return testText
}

return testText.replace(whitespaces, ' ')
}

if (_.isRegExp(text)) {
if (options.matchCase === false && !text.flags.includes('i')) {
text = new RegExp(text.source, text.flags + 'i') // eslint-disable-line prefer-template
}

// taken from jquery's normal contains method
$expr.contains = (elem) => {
let testText = normalizeWhitespaces(elem)

return text.test(testText)
}
}

if (_.isString(text)) {
$expr.contains = (elem) => {
let testText = normalizeWhitespaces(elem)

if (!options.matchCase) {
testText = testText.toLowerCase()
text = text.toLowerCase()
}

return testText.includes(text)
}
}

// find elements by the :contains psuedo selector
// find elements by the :cy-contains psuedo selector
// and any submit inputs with the attributeContainsWord selector
const selector = $dom.getContainsSelector(text, filter)
const selector = $dom.getContainsSelector(text, filter, options)

const resolveElements = () => {
const getOpts = _.extend(_.clone(options), {
Expand Down Expand Up @@ -563,11 +508,6 @@ module.exports = (Commands, Cypress, cy) => {

return Promise
.try(resolveElements)
// always restore contains in case
// we used a regexp!
.finally(() => {
restoreContains()
})
},
})

Expand Down
53 changes: 51 additions & 2 deletions packages/driver/src/dom/elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -945,16 +945,65 @@ const getElements = ($el) => {
return els
}

const getContainsSelector = (text, filter = '') => {
const whitespaces = /\s+/g

// When multiple space characters are considered as a single whitespace in all tags except <pre>.
const normalizeWhitespaces = (elem) => {
let testText = elem.textContent || elem.innerText || $(elem).text()

if (elem.tagName === 'PRE') {
return testText
}

return testText.replace(whitespaces, ' ')
}
const getContainsSelector = (text, filter = '', options: {
matchCase?: boolean
} = {}) => {
const $expr = $.expr[':']

const escapedText = $utils.escapeQuotes(text)

// they may have written the filter as
// comma separated dom els, so we want to search all
// https://github.com/cypress-io/cypress/issues/2407
const filters = filter.trim().split(',')

let cyContainsSelector

if (_.isRegExp(text)) {
if (options.matchCase === false && !text.flags.includes('i')) {
text = new RegExp(text.source, text.flags + 'i') // eslint-disable-line prefer-template
}

// taken from jquery's normal contains method
cyContainsSelector = function (elem) {
let testText = normalizeWhitespaces(elem)

return text.test(testText)
}
} else if (_.isString(text)) {
cyContainsSelector = function (elem) {
let testText = normalizeWhitespaces(elem)

if (!options.matchCase) {
testText = testText.toLowerCase()
text = text.toLowerCase()
}

return testText.includes(text)
}
} else {
cyContainsSelector = $expr.contains
}

// we set the `cy-contains` jquery selector which will only be used
// in the context of cy.contains(...) command and selector playground.
$expr['cy-contains'] = cyContainsSelector

const selectors = _.map(filters, (filter) => {
return `${filter}:not(script,style):contains('${escapedText}'), ${filter}[type='submit'][value~='${escapedText}']`
// use custom cy-contains selector that is registered above
return `${filter}:not(script,style):cy-contains('${escapedText}'), ${filter}[type='submit'][value~='${escapedText}']`
})

return selectors.join()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,26 @@ describe('src/cy/commands/assertions', () => {

cy.contains('Nested Find').should('have.length', 2)
})

// https://github.com/cypress-io/cypress/issues/6384
it('can chain contains assertions off of cy.contains', () => {
cy.timeout(100)
cy.contains('foo')
.should('not.contain', 'asdfasdf')

cy.contains('foo')
.should('contain', 'foo')

cy.contains(/foo/)
.should('not.contain', 'asdfsadf')

cy.contains(/foo/)
.should('contain', 'foo')

// this isn't valid: .should('contain') does not support regex
// cy.contains(/foo/)
// .should('contain', /foo/)
})
})

describe('have.class', () => {
Expand Down
1 change: 1 addition & 0 deletions packages/driver/test/cypress/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const fs = require('fs-extra')
const Promise = require('bluebird')
const webpack = require('@cypress/webpack-preprocessor')

process.env.NO_LIVERELOAD = '1'
const webpackOptions = require('@packages/runner/webpack.config.ts').default

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/web-config/webpack.config.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ execa.sync('rebuild-node-sass', { cwd: path.join(__dirname, './node_modules/.bin

const env = process.env.NODE_ENV === 'production' ? 'production' : 'development'
const args = process.argv.slice(2)
const liveReloadEnabled = !args.includes('--no-livereload')
const liveReloadEnabled = !(args.includes('--no-livereload') || process.env.NO_LIVERELOAD)
const watchModeEnabled = args.includes('--watch') || args.includes('-w')

// opt out of livereload with arg --no-livereload
Expand Down

4 comments on commit b8d6a6d

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on b8d6a6d Feb 14, 2020

Choose a reason for hiding this comment

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

Circle has built the linux x64 version of the Test Runner.

You can install this pre-release platform-specific build using instructions at https://on.cypress.io/installing-cypress#Install-pre-release-version.

You will need to use custom CYPRESS_INSTALL_BINARY url and install Cypress using an url instead of the version.

export CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/4.0.2/linux-x64/circle-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-255717/cypress.zip
npm install https://cdn.cypress.io/beta/npm/4.0.2/circle-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-255695/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on b8d6a6d Feb 14, 2020

Choose a reason for hiding this comment

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

Circle has built the linux x64 version of the Test Runner.

You can install this pre-release platform-specific build using instructions at https://on.cypress.io/installing-cypress#Install-pre-release-version.

You will need to use custom CYPRESS_INSTALL_BINARY url and install Cypress using an url instead of the version.

export CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/4.0.2/darwin-x64/circle-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-255826/cypress.zip
npm install https://cdn.cypress.io/beta/npm/4.0.2/circle-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-255757/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on b8d6a6d Feb 14, 2020

Choose a reason for hiding this comment

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

AppVeyor has built the win32 x64 version of the Test Runner.

You can install this pre-release platform-specific build using instructions at https://on.cypress.io/installing-cypress#Install-pre-release-version.

You will need to use custom CYPRESS_INSTALL_BINARY url and install Cypress using an url instead of the version.

Instructions are included below, depending on the shell you are using.

In Command Prompt (cmd.exe):

set CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/4.0.2/win32-x64/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.zip
npm install https://cdn.cypress.io/beta/npm/4.0.2/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.tgz

In PowerShell:

$env:CYPRESS_INSTALL_BINARY = https://cdn.cypress.io/beta/binary/4.0.2/win32-x64/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.zip
npm install https://cdn.cypress.io/beta/npm/4.0.2/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.tgz

In Git Bash:

export CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/4.0.2/win32-x64/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.zip
npm install https://cdn.cypress.io/beta/npm/4.0.2/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.tgz

Using cross-env:

If the above commands do not work for you, you can also try using cross-env:

npm i -g cross-env
cross-env CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/4.0.2/win32-x64/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.zip npm install https://cdn.cypress.io/beta/npm/4.0.2/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on b8d6a6d Feb 14, 2020

Choose a reason for hiding this comment

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

AppVeyor has built the win32 ia32 version of the Test Runner.

You can install this pre-release platform-specific build using instructions at https://on.cypress.io/installing-cypress#Install-pre-release-version.

You will need to use custom CYPRESS_INSTALL_BINARY url and install Cypress using an url instead of the version.

Instructions are included below, depending on the shell you are using.

In Command Prompt (cmd.exe):

set CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/4.0.2/win32-ia32/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.zip
npm install https://cdn.cypress.io/beta/npm/4.0.2/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.tgz

In PowerShell:

$env:CYPRESS_INSTALL_BINARY = https://cdn.cypress.io/beta/binary/4.0.2/win32-ia32/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.zip
npm install https://cdn.cypress.io/beta/npm/4.0.2/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.tgz

In Git Bash:

export CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/4.0.2/win32-ia32/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.zip
npm install https://cdn.cypress.io/beta/npm/4.0.2/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.tgz

Using cross-env:

If the above commands do not work for you, you can also try using cross-env:

npm i -g cross-env
cross-env CYPRESS_INSTALL_BINARY=https://cdn.cypress.io/beta/binary/4.0.2/win32-ia32/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.zip npm install https://cdn.cypress.io/beta/npm/4.0.2/appveyor-develop-b8d6a6d6eda6855cf4df4b6f1a21131594322816-30813380/cypress.tgz

Please sign in to comment.