Skip to main content
Cypress应用

and

创建一个断言。断言会作为前一个命令的一部分自动重试,直到通过或超时。

info

.should() 的别名

info

注意: .and() 假设你已经熟悉核心概念,例如断言

语法

.and(chainers)
.and(chainers, value)
.and(chainers, method, value)
.and(callbackFn)

用法

正确用法

cy.get('.err').should('be.empty').and('be.hidden') // 断言 '.err' 为空且隐藏

cy.contains('Login').and('be.visible') // 断言元素可见

cy.wrap({ foo: 'bar' })
.should('have.property', 'foo') // 断言 'foo' 属性存在
.and('eq', 'bar') // 断言 'foo' 属性值为 'bar'

错误用法

cy.and('eq', '42') // 不能从 'cy' 链式调用

cy.get('button').click().and('be.focused') // 不应从可能更新 DOM 的
// 操作命令链式调用

参数

chainers (字符串)

来自 ChaiChai-jQuerySinon-Chai 的任何有效链式断言。

value (字符串)

用于断言的值。

method (字符串)

在链式断言上调用的方法。

callbackFn (函数)

传入一个可以包含任意数量显式断言的函数。传递给函数的内容即为生成的内容。

生成结果 了解主题管理

  • 大多数情况下,.and() 返回与输入相同的主题。
  • .and() 是一个断言,可以安全地链式调用使用该主题的进一步命令。
cy.get('nav') // 返回 <nav>
.should('be.visible') // 返回 <nav>
.and('have.class', 'open') // 返回 <nav>

然而,某些链式断言会改变主题。在下面的例子中,.and() 返回字符串 sans-serif,因为链式断言 have.css, 'font-family' 改变了主题。

cy.get('nav') // 返回 <nav>
.should('be.visible') // 返回 <nav>
.and('have.css', 'font-family') // 返回 'sans-serif'
.and('match', /serif/) // 返回 'sans-serif'

示例

链式断言

对同一主题链式断言

cy.get('button').should('have.class', 'active').and('not.be.disabled')

当返回内容变化时链式断言

{/* 应用代码 */}
<ul>
<li>
<a href="users/123/edit">Edit User</a>
</li>
</ul>
cy.get('a')
.should('contain', 'Edit User') // 返回 <a>
.and('have.attr', 'href') // 返回 href 的字符串值
.and('match', /users/) // 返回 href 的字符串值
.and('not.include', '#') // 返回 href 的字符串值

方法和值

断言 href 等于 '/users'

cy.get('#header a')
.should('have.class', 'active')
.and('have.attr', 'href', '/users')

函数

验证多个 <p> 的长度、内容和类

.and() 传递一个函数可以让你对返回的主题进行断言。这让你有机会处理你想要断言的内容。

确保不要在回调函数中包含任何有副作用的代码。

回调函数会不断重试,直到其中的所有断言都不抛出错误为止。

<div>
<p class="text-primary">Hello World</p>
<p class="text-danger">You have an error</p>
<p class="text-default">Try again later</p>
</div>
cy.get('p')
.should('not.be.empty')
.and(($p) => {
// 应该找到 3 个元素
expect($p).to.have.length(3)

// 确保第一个元素包含某些文本内容
expect($p.first()).to.contain('Hello World')

// 使用 jQuery 的 map 获取所有类
// jQuery 的 map 返回一个新的 jQuery 对象
const classes = $p.map((i, el) => {
return Cypress.$(el).attr('class')
})

// 调用 classes.get() 将其转换为普通数组
expect(classes.get()).to.deep.eq([
'text-primary',
'text-danger',
'text-default',
])
})
info

使用回调函数不会改变主题

注意事项

Chai

与 Chai 的相似之处

如果你以前使用过 Chai,你会发现 .and() 与相同的流式断言语法匹配。

以这个显式断言为例:

expect({ foo: 'bar' }).to.have.property('foo').and.eq('bar')

.and() 复制了相同的断言行为。

主题

如何知道哪些断言会改变主题,哪些会保持主题不变?

来自 ChaiChai-jQuery 的链式断言总会记录它们的返回内容。

使用回调函数不会改变返回内容

无论何时使用回调函数,其返回值总是被忽略。Cypress 总是强制命令返回前一个 cy 命令的返回内容(在下面的例子中是 <button>

cy.get('button')
.should('be.active')
.and(($button) => {
expect({ foo: 'bar' }).to.deep.eq({ foo: 'bar' })

return { foo: 'bar' } // 返回值被忽略,.and() 返回 <button>
})
.then(($button) => {
// 可以对 <button> 进行任何操作
})

差异

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

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

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

规则

要求 了解命令链

  • .and() 需要从上一个命令链式调用。

超时设置 了解超时机制

  • .and() 会继续重试其指定的断言,直到超时。
cy.get('input', {timeout: 10000}).should('have.value', '10').and('have.class', 'error')

// 这里的超时设置会传递给 '.and()'
// 并且它会重试最多 10 秒
cy.get('input', {timeout: 10000}).should('have.value', 'US').and(($input) => {

// 这里的超时设置会传递给 '.and()'
// 除非断言提前抛出错误,
// 否则所有断言都会重试最多 10 秒
expect($input).to.not.be('disabled')
expect($input).to.not.have.class('error')
})

命令日志

对同一主题链式断言

cy.get('.list')
.find('input[type="checkbox"]')
.should('be.checked')
.and('not.be.disabled')

上面的命令会在命令日志中显示为:

断言的命令日志

当点击命令日志中的 assert 时,控制台会输出以下内容:

断言的 console.log

另请参阅