wait
在继续执行下一个命令之前,等待指定的毫秒数或等待别名的资源解析完成。
语法
cy.wait(time)
cy.wait(alias)
cy.wait(aliases)
cy.wait(time, options)
cy.wait(alias, options)
cy.wait(aliases, options)
// 为别名的拦截请求指定请求和响应类型
type UserReq = {}
type UserRes = {}
type ActivityReq = {}
type ActivityRes = {}
cy.intercept('/users/*').as('getUsers')
cy.intercept('/activities/*').as('getActivities')
// 作为模板类型:
cy.wait<UserReq, UserRes>('@getUsers').then(({ request, response }) => {
request.body // 类型为 UserReq
response.body // 类型为 UserRes
})
// 作为推断类型,使用 `cypress/types/net-stubbing` 中的 `Interception` 类型
cy.wait('@getUsers').then(
({ request, response }: Interception<UserReq, UserRes>) => {
request.body // 类型为 UserReq
response.body // 类型为 UserRes
}
)
// 当传递别名数组时,必须推断类型:
cy.wait(['@getUsers', 'getActivities']).then(
(
interceptions: Array<
Interception<UserReq | ActivityReq, UserRes | ActivityRes>
>
) => {
interceptions.forEach(({ request, response }) => {
request.body // 类型为 UserReq | ActivityReq
response.body // 类型为 UserRes | ActivityRes
})
}
)
用法
正确用法
cy.wait(500)
cy.wait('@getProfile')
参数
time (Number)
等待的毫秒数。
alias (String)
使用 .as()
命令定义的别名路由,并通过 @
字符和别名名称引用。
aliases (Array)
使用 .as()
命令定义的别名路由数组,并通过 @
字符和别名名称引用。
options (Object)
传入一个选项对象以更改 cy.wait()
的默认行为。
选项 | 默认值 | 描述 |
---|---|---|
log | true | 在 命令日志 中显示命令 |
timeout | requestTimeout , responseTimeout | 等待 cy.wait() 解析的超时时间,超过则 超时 |
requestTimeout | requestTimeout | 覆盖此请求的全局 requestTimeout 。默认为 timeout 。 |
responseTimeout | responseTimeout | 覆盖此请求的全局 responseTimeout 。默认为 timeout 。 |
生成结果
当给定 time
参数时:
cy.wait()
返回与传入时相同的主题。- 在
.wait()
之后链接依赖于该主题的进一步命令是 不安全的。
当给定 alias
参数时:
cy.wait()
返回一个包含请求的HTTP请求和响应属性的对象。
示例
时间
等待任意毫秒数:
cy.wait(2000) // 等待2秒
您几乎 不需要 等待任意时间。在Cypress中总有更好的表达方式。
阅读关于 最佳实践 的更多信息。
此外,在调试测试代码时,使用 cy.debug()
或 cy.pause()
通常更加方便。
别名
关于别名的详细解释,请阅读更多关于等待路由的信息。
等待特定请求响应
- 端到端测试
- 组件测试
// 等待别名 'getAccount' 响应
// 不更改或存根其响应
cy.intercept('/accounts/*').as('getAccount')
cy.visit('/accounts/123')
cy.wait('@getAccount').then((interception) => {
// 现在可以访问包含请求体、
// 响应体、状态等的低级拦截对象
})
// 等待别名 'getAccount' 响应
// 不更改或存根其响应
cy.intercept('/accounts/*').as('getAccount')
cy.mount(<Account />)
cy.wait('@getAccount').then((interception) => {
// 现在可以访问包含请求体、
// 响应体、状态等的低级拦截对象
})
等待自动递增的响应
每次我们使用 cy.wait()
等待一个别名时,Cypress会等待第n个匹配的请求。
// 存根对书籍请求的空响应
cy.intercept('GET', '/books', []).as('getBooks')
cy.get('#search').type('Peter Pan')
// 等待第一个响应完成
cy.wait('@getBooks')
// 结果应为空,因为我们
// 首先返回了一个空数组
cy.get('#book-results').should('be.empty')
// 现在请求(再次别名为 `getBooks`)将返回一本书
cy.intercept('GET', '/books', [{ name: 'Peter Pan' }]).as('getBooks')
cy.get('#search').type('Peter Pan')
// 当我们再次等待 'getBooks' 时,Cypress
// 会自动知道等待第二个响应
cy.wait('@getBooks')
// 第二次我们返回了一本书
cy.get('#book-results').should('have.length', 1)
别名数组
可以传递一个别名数组,Cypress会在解析前等待所有请求完成。
当传递一个别名数组给 cy.wait()
时,Cypress会在给定的 requestTimeout
和 responseTimeout
内等待所有请求完成。
- 端到端测试
- 组件测试
cy.intercept('/users/*').as('getUsers')
cy.intercept('/activities/*').as('getActivities')
cy.intercept('/comments/*').as('getComments')
cy.visit('/dashboard')
cy.wait(['@getUsers', '@getActivities', '@getComments']).then(
(interceptions) => {
// interceptions 现在是一个匹配请求的数组
// interceptions[0] <-- getUsers
// interceptions[1] <-- getActivities
// interceptions[2] <-- getComments
}
)
cy.intercept('/users/*').as('getUsers')
cy.intercept('/activities/*').as('getActivities')
cy.intercept('/comments/*').as('getComments')
cy.mount(<Dashboard />)
cy.wait(['@getUsers', '@getActivities', '@getComments']).then(
(interceptions) => {
// interceptions 现在是一个匹配请求的数组
// interceptions[0] <-- getUsers
// interceptions[1] <-- getActivities
// interceptions[2] <-- getComments
}
)
使用 .spread()
将数组展开为多个参数。
cy.intercept('/users/*').as('getUsers')
cy.intercept('/activities/*').as('getActivities')
cy.intercept('/comments/*').as('getComments')
cy.wait(['@getUsers', '@getActivities', '@getComments']).spread(
(getUsers, getActivities, getComments) => {
// 每个拦截现在是一个单独的参数
}
)
注意事项
嵌套
Cypress会自动等待网络调用完成后再继续执行下一个命令。
// 反模式:将Cypress命令放在.then回调中
cy.wait('@alias')
.then(() => {
cy.get(...)
})
// 推荐做法:按顺序编写Cypress命令
cy.wait('@alias')
cy.get(...)
// 示例:在继续之前从cy.intercept()断言状态
cy.wait('@alias').its('response.statusCode').should('eq', 200)
cy.get(...)
阅读 指南:Cypress简介
超时
requestTimeout
和 responseTimeout
当与别名一起使用时,cy.wait()
会经历两个独立的“等待”阶段。
第一个阶段等待匹配的请求离开浏览器。此持续时间由 requestTimeout
选项配置,默认值为 5000
毫秒。
这意味着当您开始等待一个别名的请求时,Cypress将等待最多5秒以创建匹配的请求。如果未找到匹配的请求,您将看到类似以下的错误消息:

一旦Cypress检测到匹配的请求已开始,它将切换到第二个等待阶段。此持续时间由 responseTimeout
选项配置,默认值为 30000
毫秒。
这意味着Cypress现在将等待最多30秒以获取外部服务器对此请求的响应。如果未检测到响应,您将看到类似以下的错误消息:

这为您提供了两全其美的方案— —当请求从未发出时快速反馈错误,以及实际外部响应的更长等待时间。
使用别名数组
当传递一个别名数组给 cy.wait()
时,Cypress会在给定的 requestTimeout
和 responseTimeout
内等待所有请求完成。
规则
要求
- 当传递
time
参数时,cy.wait()
可以链接到cy
或另一个命令。 - 当传递
alias
参数时,cy.wait()
必须链接到cy
。
断言
cy.wait()
只会运行您链接的断言一次,并且不会 重试。
超时设置
cy.wait()
可能会因等待请求发出而超时。cy.wait()
可能会因等待响应返回而超时。
命令日志
等待对用户的PUT请求解析。
cy.intercept('PUT', /users/, {}).as('userPut')
cy.get('form').submit()
cy.wait('@userPut').its('request.url').should('include', 'users')
cy.wait()
将在命令日志中显示为:

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

历史
版本 | 变更 |
---|---|
3.1.3 | 添加了 requestTimeout 和 responseTimeout 选项 |
< 0.3.3 | 添加了 cy.wait() 命令 |