Skip to main content
Cypress应用

then

允许您处理从上一个命令中产生的结果对象。

info

注意: .then() 假设您已经熟悉核心概念,例如闭包

info

注意: 对于断言,优先使用带回调的 .should() 而不是 .then(),因为它们会自动重试直到不再抛出断言,但请注意差异

语法

.then(callbackFn)
.then(options, callbackFn)

用法

正确用法

cy.get('.nav').then(($nav) => {}) // 将 .nav 作为第一个参数传递
cy.location().then((loc) => {}) // 将位置对象作为第一个参数传递

参数

options (Object)

传入一个选项对象以更改 .then() 的默认行为。

选项默认值描述
timeoutdefaultCommandTimeout超时前等待 .then() 解析的时间

callbackFn (Function)

传入一个函数,该函数将上一个命令产生的结果作为其第一个参数。

生成结果 了解主题管理

回调函数返回的任何内容都将成为新的结果对象,并流入下一个命令(undefinednull 除外)。

  • 如果返回值是一系列 Cypress 命令(例如 return cy.get('button')),Cypress 将等待它们解析并使用它们的返回值作为新的结果对象。
  • 如果返回值是一个 Promise,Cypress 将等待它解析,并使用解析后的值作为新的结果对象以继续命令链。
  • 如果回调返回 undefinednull(或没有返回值),则回调函数中最后一个 Cypress 命令的结果将作为新的结果对象流入下一个命令。
  • 如果回调返回 undefinednull(或没有返回值)且回调未调用任何 Cypress 命令,则结果对象不会被修改,上一个结果对象将传递到下一个命令。

.then() 的回调函数不会重试。直接从回调返回 DOM 元素然后对它们使用进一步的命令是不安全的。相反,应使用 Cypress 查询来定位您感兴趣的元素以进行操作或断言。

示例

info

我们在核心概念指南中有更多示例,详细介绍了使用 .then() 存储、比较和调试值的各种方法。

DOM 元素

button 元素作为结果对象传递

cy.get('button').then(($btn) => {
const cls = $btn.attr('class')

cy.wrap($btn).click().should('not.have.class', cls)
})

从上一个命令传递数字作为结果对象

cy.wrap(1)
.then((num) => {
cy.wrap(num).should('equal', 1) // true
})
.should('equal', 1) // true

更改结果对象

使用另一个命令更改 el 结果对象

cy.get('button')
.then(($btn) => {
const cls = $btn.attr('class')

cy.wrap($btn).click().should('not.have.class', cls).find('i')
// 由于没有显式返回
// 最后一个 Cypress 命令的结果将作为结果对象传递
})
.should('have.class', 'spin') // 对 i 元素进行断言

使用另一个命令更改数字结果对象

cy.wrap(1).then((num) => {
cy.wrap(num)).should('equal', 1) // true
cy.wrap(2)
}).should('equal', 2) // true

通过返回更改数字结果对象

cy.wrap(1)
.then((num) => {
cy.wrap(num)
.should('equal', 1) // true
.then(() => {
return 2
})
})
.should('equal', 2) // true

返回 undefined 不会修改传递的结果对象

cy.get('form')
.then(($form) => {
console.log('form is:', $form)
// 此处返回 undefined,但 $form 将
// 作为结果对象传递以允许继续链式调用
})
.find('input')
.then(($input) => {
// 由于我们的 form 元素作为结果对象传递
// 并对其调用了 .find('input'),因此可以在此处获取 $input 元素
})

原始 HTMLElements 会被 jQuery 包装

cy.get('div')
.then(($div) => {
return $div[0] // 类型 => HTMLDivElement
})
.then(($div) => {
$div // 类型 => JQuery<HTMLDivElement>
})

Promises

Cypress 会等待 Promises 解析后再继续执行

使用 Q 的示例

cy.get('button')
.click()
.then(($button) => {
const p = Q.defer()

setTimeout(() => {
p.resolve()
}, 1000)

return p.promise
})

使用 bluebird 的示例

cy.get('button')
.click()
.then(($button) => {
return Promise.delay(1000)
})

使用 jQuery deferred 的示例

cy.get('button')
.click()
.then(($button) => {
const df = $.Deferred()

setTimeout(() => {
df.resolve()
}, 1000)

return df
})

注意事项

差异

.then().should()/.and() 有什么区别?

使用 .then() 允许你在回调函数中使用生成的主题(yielded subject),当你需要操作某些值或执行某些操作时应该使用它。

另一方面,当在 .should().and() 中使用回调函数时,会有特殊的逻辑来重新运行回调函数,直到其中没有断言抛出为止。你应当注意 .should().and() 回调函数中的副作用,避免你不希望被多次执行的操作。

规则

要求 了解命令链

  • .then() 需要链接到上一个命令。

断言 了解断言

  • .then() 只会运行一次您链接的断言,不会重试

超时设置 了解超时机制

  • .then() 可能会因等待您返回的 Promise 解析而超时。

命令日志

  • .then() 不会在命令日志中记录

历史

版本变更
0.14.0添加了 timeout 选项
< 0.3.3添加了 .then() 命令

另请参阅