diff --git a/source/_data/sidebar.yml b/source/_data/sidebar.yml index 5b0b307ffb..e2caa32bf3 100644 --- a/source/_data/sidebar.yml +++ b/source/_data/sidebar.yml @@ -10,11 +10,10 @@ guides: core-concepts: introduction-to-cypress: introduction-to-cypress.html writing-and-organizing-tests: writing-and-organizing-tests.html - overview-of-the-gui: overview-of-the-gui.html interacting-with-elements: interacting-with-elements.html + overview-of-the-gui: overview-of-the-gui.html aliases-and-references: aliases-and-references.html - screenshots-and-videos: screenshots-and-videos.html - launching-browsers: launching-browsers.html + conditional-testing: conditional-testing.html guides: command-line: command-line.html debugging: debugging.html @@ -22,6 +21,8 @@ guides: continuous-integration: continuous-integration.html environment-variables: environment-variables.html stubs-spies-and-clocks: stubs-spies-and-clocks.html + screenshots-and-videos: screenshots-and-videos.html + launching-browsers: launching-browsers.html web-security: web-security.html reporters: reporters.html # advanced-cypress: diff --git a/source/guides/core-concepts/conditional-testing.md b/source/guides/core-concepts/conditional-testing.md new file mode 100644 index 0000000000..f7cdee9ba3 --- /dev/null +++ b/source/guides/core-concepts/conditional-testing.md @@ -0,0 +1,446 @@ +--- +title: Conditional Testing +comments: false +--- + +Conditional testing refers to the common programming pattern: + +> If X, then Y, else Z + +Many of our users ask how to accomplish this seemingly simple idiom in Cypress. + +Here are some example use cases: + +- How do I do something different whether an element does or doesn't exist? +- My application does A/B testing, how do I account for that? +- My users receive a "welcome wizard", but existing ones don't. Can I always close the wizard in case it's shown, and ignore it when it's not? +- Can I recover from failed Cypress commands like if a `cy.get()` doesn't find an element? +- I'm trying to write dynamic tests that do something different based on text on the page. +- I want to automatically find all `` elements, and based on which ones I found, I want to check that each link works. + +The problem is - while first appearing simple, writing tests in this fashion often leads to flaky tests, random failures, and difficult to track down edge cases. + +Let's investigate why and how you can overcome these problems... + +# The Problem + +These days modern JS applications are highly dynamic and mutable. Their state, and the DOM are continuously changing over a period of time. + +The problem with **conditional testing** is that it can only be used when the state has stabilized. In modern day applications, knowing when state is stable is oftentimes impossible. + +To a human - if something changes 10ms, or 100ms from now, we may not even notice this change and assume the state was always the same. + +To a robot - even 10ms represents billions+ of clock cycles. The timescale difference is incredible. + +A human also has intuition. If you click a button and see a loading spinner, you'll assume the state is in flux and will automatically wait for it to finish. + +To a robot, they have no intuition - they'll do exactly as they're programmed to do. + +To illustrate this, let's take a very simple example of trying to conditionally test unstable state. + +## The DOM is unstable + +```js +// your app code + +// random amount of time +const random = Math.random() * 100 + +// create a