Cypress 如何处理异步操作?命令链和自动等待机制是什么?
Cypress 的命令不是立即执行,而是入队后按序串行执行。每个命令返回 chainable 对象,后续命令挂载到链条上形成命令队列,Cypress 依次取出执行并自动等待前置条件满足。自动等待指每个命令内建重试机制:cy.get() 会反复查询 DOM 直到元素存在且可见,cy.request() 会等待响应返回,默认超时 4 秒。开发者无需写 sleep 或显式等待,Cypress 在命令间自动处理异步时序。
追问
命令队列和 Promise 链有什么区别?
命令队列在 .then() 之前不会执行,是同步入队异步执行;Promise 链是立即执行。所以不能把 Cypress 命令赋值给变量:const el = cy.get('#btn') 拿到的是 chainable 不是元素,必须用 .then() 回调取值。
什么时候需要用 .then()?
需要访问命令返回值或混合同步逻辑时。比如从响应中提取 ID 再构造下一个请求。注意 .then() 内部的 cy 命令会重新入队,不会立即执行。
自动等待超时了怎么办?
可通过 { timeout: 10000 } 单独设置,或在 cypress.config.js 中配置 defaultCommandTimeout 全局调整。超时后命令失败,测试中断并截图。应优先用 should() 断言替代加大超时。
cy.wait() 和自动等待什么时候用?
自动等待覆盖 DOM 和 XHR 场景,一般够用。但 cy.intercept() 拦截请求后需 cy.wait('@alias') 确保请求完成再断言响应,这是显式等待的典型场景。
为什么不能在 .then() 外用 async/await?
Cypress 命令不在 Promise 上运行,await 一个 chainable 不会等命令执行完。混用 async/await 会导致时序错乱,Cypress 官方明确不推荐在命令链中使用 async/await。
写段代码
javascriptcy.intercept('GET', '/api/users').as('users'); cy.visit('/dashboard'); cy.wait('@users').its('response.statusCode').should('eq', 200); cy.get('#user-list').should('be.visible');