0

I'm using a node library to execute api calls for test data setup and teardown. The library works as follows:

someApiServiceObject
.executeApiCall({... parameters})
.then(doSomethingWithResults())
.catch(() => { 
  // Here I would like to fail the test as something has gone wrong
})

If the request fails for some reason, I only learn about it by the Promise returning from executeApiCall function being rejected - hence the catch block.

But if I put throw new Error(); into the catch block or remove the catch block, I can see the (uncaught exception) Error: in the cypress console, but the test still passes.

Can someone advise me on how this case should be handled correctly?

The test:

it('List projects', () => {
    projectsApi.projectsList({})
      .then(() => {
        cy.log('Success');
      }).catch(() => {
        throw new Error();
      });
  });
Fody
  • 23,754
  • 3
  • 20
  • 37
Rehalus
  • 17
  • 4

1 Answers1

1

If you call someApiServiceObject.executeApiCall({...parameters}) in a task (since it's a node library), you should just be able to return the promise and Cypress handles failing the test. Don't catch() within the task.

module.exports = (on, config) => {
  on('task', {
    api(parameters) {
      return someApiServiceObject
        .executeApiCall({... parameters})
        .then(doSomethingWithResults())   
    },
  })
}

If that fails, follow this pattern Return number of files in the folder

module.exports = (on, config) => {
  on('task', {
    countFiles(folderName) {
      return new Promise((resolve, reject) => {
        someApiServiceObject
          .executeApiCall({... parameters})
          .then(doSomethingWithResults())
          .then((results) => resolve(results))
          .catch((err) => reject(err))
        })
      })
    },
  })
}

From comments, I think there's a assumption being made that .executeApiCall() must be returning a promise, but that may not be the case.

For example cy.get(...) has a .then(...) method, but it does not return a promise, it just has a .then() method.

If .executeApiCall() does actually return a promise, the first example is all you need. If it does not, you need to wrap the code.

Cypress will recognise a promise returned from a task, and use resolve or reject accordingly.

Fody
  • 23,754
  • 3
  • 20
  • 37
  • Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi May 05 '22 at 10:18
  • 1
    It's from the Cypress docs. – Fody May 05 '22 at 10:44
  • That's not a justification for writing bad code, it just means they should also fix their docs :-) – Bergi May 05 '22 at 19:36
  • LOL not just Cypress docs, see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#chained_promises). Where does this antipattern stuff come from? – TesterDick May 06 '22 at 00:38
  • 1
    I think there's a assumption being made that `someApiServiceObject.executeApiCall()` has to return a promise, but that would be erroneous. For example `cy.get(...).then(...)` does not return a promise, it just has a `.then()` method. If it does return a promise, the first example is all you need. If it does not, you need to wrap it. – Fody May 06 '22 at 02:40