The thing about cypress that annoyed me the most was how it wasn't just using async/await syntax, generating more complex tests dynamically is super hard. Just try to write a test that follows links on a site dynamically, I couldn't figure it out.
Cypress requires developers to have a mental model of "calling a Cypress function actually adds an action to the back of a queue and immediately returns control flow without waiting for that action to run." And this is fine if you can express your waits and conditions declaratively - you give Cypress a plan, it decodes the plan from your Cypress code in milliseconds, and then will take as long as it needs to execute that plan.
And Cypress gives a great API surface where almost everything can be done with just this declarative API, and it enables them to show the full plan in a UI even while it's executing.
But if you actually need custom control flow, with code you control... you need to "pause" your action-enqueueing to let Cypress catch up. Which means you're going to be nesting callbacks, or sprinkling awaits in all the places that aren't logically awaiting, because you need an explicit yield point out of your JS block. Our team finds this rare enough that it's acceptable. But... yeah, it's far from a perfect solution.
I’m using cypress now and finally grokked the queue notion. But cypress is still flaky: very frequently the first character typed into an input element is lost (Firefox). Switched from Chrome to Firefox because Chrome would run out of memory after too many tests.
Both of these issues are well documented in git issues with hundreds of replies and work arounds that just don’t always work.
I’m ready to throw in the towel and rewrite everything in playwright. Maybe b I’ll have different issues there…
I had this issue too, are you using React? The problem I was having was to do with React re-rendering out of step with Cypress (which was going *too* fast).
I have only seen this issue with JS based VDOM frameworks.
If I write the code “cy.wait(…); console.log(“hi”); cy.whatever()” then the “whatever” will indeed be queued to run after the network request completes. But “hi” will have printed immediately before any of this happens! So if that log was, say, me wanting to condition on something that just loaded, I can’t assume it’s even set up at that point when my JS code is executing!
- The Test Runner lets you retrace your actions with a visual UI and interact with the page as you rewind, with access to Dev Tools the whole time. It also has an excellent tool for targeting elements. (Although you'll eventually lean more on Dev Tools once you're fluent with CSS selectors.)
- There's very little boilerplate for anything. Several useful libraries are packed in and available globally.
- You can easily spy on and interact with fetch and XHR on the page
- You can easily execute Node stuff
- They have a great Dashboard (their only pay feature)
This was the first time I was happy writing ui tests, Playwright is great!
(Though I don't use the recording tool at all this article focuses on I rather write the tests manually)