mirror of
https://github.com/cypress-io/cypress.git
synced 2026-01-30 02:54:27 -06:00
Fix issue where cy.wrap does not respect timeout option (#7284)
* Testing remove all * Add functionality to wrap's timeout option * Fix issues with assertions and promise time outs * cleanup, modify error message * update error msg * fix test after error msg correction * restore coffee changes * fix after merge: modify decaffed files * Fix error messages and update tests Co-authored-by: Ben Kucera <14625260+Bkucera@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
const _ = require('lodash')
|
||||
const Promise = require('bluebird')
|
||||
|
||||
const $dom = require('../../dom')
|
||||
const $errUtils = require('../../cypress/error_utils')
|
||||
|
||||
module.exports = (Commands, Cypress, cy) => {
|
||||
Commands.addAll({ prevSubject: 'optional' }, {
|
||||
@@ -33,7 +35,13 @@ module.exports = (Commands, Cypress, cy) => {
|
||||
wrap (arg, options = {}) {
|
||||
const userOptions = options
|
||||
|
||||
options = _.defaults({}, userOptions, { log: true })
|
||||
options = _.defaults({}, userOptions, {
|
||||
log: true,
|
||||
timeout: Cypress.config('defaultCommandTimeout'),
|
||||
})
|
||||
|
||||
// we'll handle the timeout ourselves
|
||||
cy.clearTimeout()
|
||||
|
||||
if (options.log !== false) {
|
||||
options._log = Cypress.log({
|
||||
@@ -45,14 +53,28 @@ module.exports = (Commands, Cypress, cy) => {
|
||||
}
|
||||
}
|
||||
|
||||
const resolveWrap = () => {
|
||||
return cy.verifyUpcomingAssertions(arg, options, {
|
||||
onRetry: resolveWrap,
|
||||
return Promise.resolve(arg)
|
||||
.timeout(options.timeout)
|
||||
.catch(Promise.TimeoutError, () => {
|
||||
$errUtils.throwErrByPath('wrap.timed_out', {
|
||||
args: { timeout: options.timeout },
|
||||
})
|
||||
.return(arg)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
$errUtils.throwErr(err, {
|
||||
onFail: options._log,
|
||||
})
|
||||
})
|
||||
.then((subject) => {
|
||||
const resolveWrap = () => {
|
||||
return cy.verifyUpcomingAssertions(subject, options, {
|
||||
onRetry: resolveWrap,
|
||||
})
|
||||
.return(subject)
|
||||
}
|
||||
|
||||
return resolveWrap()
|
||||
return resolveWrap()
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ const create = function (specWindow, Cypress, Cookies, state, config, log) {
|
||||
state('nestedIndex', state('index'))
|
||||
|
||||
return command.get('args')
|
||||
}).all()
|
||||
})
|
||||
|
||||
.then((args) => {
|
||||
// store this if we enqueue new commands
|
||||
|
||||
@@ -661,7 +661,7 @@ module.exports = {
|
||||
message: stripIndent`\
|
||||
${cmd('{{cmd}}')} timed out after waiting \`{{timeout}}ms\`.
|
||||
|
||||
Your callback function returned a promise which never resolved.
|
||||
Your callback function returned a promise that never resolved.
|
||||
|
||||
The callback function was:
|
||||
|
||||
@@ -1798,6 +1798,19 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
|
||||
wrap: {
|
||||
timed_out: {
|
||||
message: stripIndent`
|
||||
${cmd('wrap')} timed out waiting \`{{timeout}}ms\` to complete.
|
||||
|
||||
You called \`cy.wrap()\` with a promise that never resolved.
|
||||
|
||||
To increase the timeout, use \`{ timeout: number }\`
|
||||
`,
|
||||
docsUrl: 'https://on.cypress.io/wrap',
|
||||
},
|
||||
},
|
||||
|
||||
xhr: {
|
||||
aborted: 'This XHR was aborted by your code -- check this stack trace below.',
|
||||
missing: '`XMLHttpRequest#xhr` is missing.',
|
||||
|
||||
@@ -1955,7 +1955,7 @@ describe('src/cy/commands/connectors', () => {
|
||||
cy.on('fail', (err) => {
|
||||
// get + each
|
||||
expect(this.logs.length).to.eq(2)
|
||||
expect(err.message).to.include('`cy.each()` timed out after waiting `50ms`.\n\nYour callback function returned a promise which never resolved.')
|
||||
expect(err.message).to.include('`cy.each()` timed out after waiting `50ms`.\n\nYour callback function returned a promise that never resolved.')
|
||||
expect(err.docsUrl).to.include('https://on.cypress.io/each')
|
||||
|
||||
done()
|
||||
|
||||
@@ -191,7 +191,32 @@ describe('src/cy/commands/misc', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('can extend the default timeout', () => {
|
||||
Cypress.config('defaultCommandTimeout', 100)
|
||||
|
||||
const timeoutPromise = new Promise((resolve, reject) => {
|
||||
return setTimeout(() => {
|
||||
resolve(null)
|
||||
})
|
||||
}, 200)
|
||||
|
||||
cy.wrap(timeoutPromise, { timeout: 300 })
|
||||
})
|
||||
|
||||
describe('errors', () => {
|
||||
beforeEach(function () {
|
||||
this.logs = []
|
||||
|
||||
cy.on('log:added', (attrs, log) => {
|
||||
if (attrs.name === 'wrap') {
|
||||
this.lastLog = log
|
||||
this.logs.push(log)
|
||||
}
|
||||
})
|
||||
|
||||
return null
|
||||
})
|
||||
|
||||
it('throws when wrapping an array of windows', (done) => {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.scrollTo()` failed because it requires a DOM element.')
|
||||
@@ -219,6 +244,61 @@ describe('src/cy/commands/misc', () => {
|
||||
cy.wrap([doc]).screenshot()
|
||||
})
|
||||
})
|
||||
|
||||
it('throws when exceeding default timeout', function (done) {
|
||||
Cypress.config('defaultCommandTimeout', 100)
|
||||
|
||||
cy.on('fail', (err) => {
|
||||
expect(this.logs.length).to.eq(1)
|
||||
expect(err.message).to.include('`cy.wrap()` timed out waiting `100ms` to complete.')
|
||||
expect(err.message).to.include('You called `cy.wrap()` with a promise that never resolved.')
|
||||
expect(err.message).to.include('To increase the timeout, use `{ timeout: number }`')
|
||||
expect(this.lastLog.get('error')).to.eq(err)
|
||||
done()
|
||||
})
|
||||
|
||||
const timeoutPromise = new Promise((resolve) => {
|
||||
setTimeout((() => {
|
||||
resolve(null)
|
||||
}), 200)
|
||||
})
|
||||
|
||||
cy.wrap(timeoutPromise)
|
||||
})
|
||||
|
||||
it('throws when exceeding custom timeout', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(this.logs.length).to.eq(1)
|
||||
expect(err.message).to.include('`cy.wrap()` timed out waiting `100ms` to complete.')
|
||||
expect(err.message).to.include('You called `cy.wrap()` with a promise that never resolved.')
|
||||
expect(err.message).to.include('To increase the timeout, use `{ timeout: number }`')
|
||||
expect(this.lastLog.get('error')).to.eq(err)
|
||||
done()
|
||||
})
|
||||
|
||||
const timeoutPromise = new Promise((resolve) => {
|
||||
setTimeout((() => {
|
||||
resolve(null)
|
||||
}), 200)
|
||||
})
|
||||
|
||||
cy.wrap(timeoutPromise, { timeout: 100 })
|
||||
})
|
||||
|
||||
it('logs once when promise parameter is rejected', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(this.logs.length).to.eq(1)
|
||||
expect(err.message).to.include('custom error')
|
||||
expect(this.lastLog.get('error')).to.eq(err)
|
||||
done()
|
||||
})
|
||||
|
||||
const rejectedPromise = new Promise((resolve, reject) => {
|
||||
reject(new Error('custom error'))
|
||||
})
|
||||
|
||||
cy.wrap(rejectedPromise)
|
||||
})
|
||||
})
|
||||
|
||||
describe('.log', () => {
|
||||
|
||||
Reference in New Issue
Block a user