Cypress - “失败是因为你混淆了异步和同步代码”

Mik*_*key -1 javascript recursion for-loop cypress

我有一个可以访问 API 的 Cypress 测试。返回一个项目列表,我希望它基本上进行轮询,直到我得到正确的原因(最多 30 次)。

返回的示例是

{
   "items":[
      {
         "reason":"incorrect"
      },
      {
         "reason":"correct"
      }
   ]
}
Run Code Online (Sandbox Code Playgroud)

我有以下函数,如果返回正确的原因,它会轮询并返回响应。否则会抛出错误

function pollStatusReason(id, reason, attempts = 0) {
    const url = `http://someurl/${id}`;

    if (attempts > 30) throw `Too many attempts to get reason: ${reason}`;

    return cy.request({
        method: 'GET',
        url: url,
    }).then((response) => {
        if (response.status != 200) {
            pollStatusReason(id, reason, attempts + 1);
        } else {
            const items = response.body.items;
            for (let i = 0; i < items.length; i++) {
                if (items[i].reason == reason) {
                    expect(reason).to.eq(items[i].reason);
                    return response
                } else {
                    cy.log('RETRYING TO GET STATUS REASON: ', reason);
                    cy.wait(5000); // Wait between attempts

                    pollStatusReason(id, reason, attempts + 1);
                }
            }
        };
    });
}

export default pollStatusReason;
Run Code Online (Sandbox Code Playgroud)

在测试中我只是调用 func

describe('Get items', () => {
  it('Get my items with the reason Correct', () => {
    pollStatusReason('123', 'correct').then((resp)=>{console.log(resp)})
  })
})
Run Code Online (Sandbox Code Playgroud)

但它似乎失败了

CypressError: `cy.then()` failed because you are mixing up async and sync code.
In your callback function you invoked 1 or more cy commands but then returned a synchronous value.
Cypress commands are asynchronous and it doesn't make sense to queue cy commands and yet return a synchronous value.
You likely forgot to properly chain the cy commands using another `cy.then()`.
The value you synchronously returned was: `Object{7}`
Run Code Online (Sandbox Code Playgroud)

奇怪的是,它并不总是失败。但如果有人有任何想法,请告诉我。我有一种与 for 循环有关的感觉

Ala*_*paz 5

由于错误抱怨return response 返回了同步值,请尝试添加cy.wrap()来克服它。

return cy.request({
  ...
  if (items[i].reason === reason) {   
    // get rid of expect() it's not needed
    return cy.wrap(response)
  }
  ...
Run Code Online (Sandbox Code Playgroud)

此外,每个响应有七个项目 - 这意味着该else部件将触发pollStatusReason七次,这不是您想要的

for (let i = 0; i < items.length; i++) {
  if (...) {
  } else { 
    cy.wait(5000)
    // spawning too many recursions per request
    pollStatusReason(id, reason, attempts + 1)
Run Code Online (Sandbox Code Playgroud)

使用单个表达式来检查原因代码,例如

function pollStatusReason(id, expectedReason, attempts = 0) {
  ...
  return cy.request(...).then(response => {
    ...

    // get rid of for loop 
    const found = Cypress._.find(items, {'reason': expectedReason})

    if (found) {
      return cy.wrap(response)
    } else {
      cy.wait(5000)

      // return the recursion result and also put recursion call on the queue 
      // since you use cy.wait() above 
      return cy.then(() => pollStatusReason(id, reason, attempts + 1))
    }
Run Code Online (Sandbox Code Playgroud)

参考lodash 查找