{
  "doc": {
    "id": "app/guides/conditional-testing",
    "title": "Conditional Testing: Cypress Guide",
    "description": "Learn how to do conditional testing in Cypress without relying on the DOM.",
    "section": "app",
    "source_path": "/llm/markdown/app/guides/conditional-testing.md",
    "version": "24a73f8a97175663aaffd3b016289fb2a523a4ea",
    "updated_at": "2026-05-14T20:17:33.301Z",
    "headings": [
      {
        "id": "app/guides/conditional-testing#conditional-testing",
        "text": "Conditional Testing",
        "level": 1
      },
      {
        "id": "app/guides/conditional-testing#what-youll-learn",
        "text": "What you'll learn",
        "level": 5
      },
      {
        "id": "app/guides/conditional-testing#the-problem",
        "text": "The problem",
        "level": 2
      },
      {
        "id": "app/guides/conditional-testing#the-dom-is-unstable",
        "text": "The DOM is unstable",
        "level": 3
      },
      {
        "id": "app/guides/conditional-testing#the-situations",
        "text": "The situations",
        "level": 2
      },
      {
        "id": "app/guides/conditional-testing#server-side-rendering",
        "text": "Server side rendering",
        "level": 3
      },
      {
        "id": "app/guides/conditional-testing#client-side-rendering",
        "text": "Client side rendering",
        "level": 3
      },
      {
        "id": "app/guides/conditional-testing#the-strategies",
        "text": "The strategies",
        "level": 2
      },
      {
        "id": "app/guides/conditional-testing#a-b-campaign",
        "text": "A/B campaign[",
        "level": 3
      },
      {
        "id": "app/guides/conditional-testing#use-url-query-params",
        "text": "Use URL query params:",
        "level": 4
      },
      {
        "id": "app/guides/conditional-testing#use-the-server",
        "text": "Use the server:",
        "level": 4
      },
      {
        "id": "app/guides/conditional-testing#use-session-cookies",
        "text": "Use session cookies:",
        "level": 4
      },
      {
        "id": "app/guides/conditional-testing#embed-data-in-the-dom",
        "text": "Embed data in the DOM:",
        "level": 4
      },
      {
        "id": "app/guides/conditional-testing#welcome-wizard",
        "text": "Welcome wizard[",
        "level": 3
      },
      {
        "id": "app/guides/conditional-testing#use-the-url-to-control-it",
        "text": "Use the URL to control it:",
        "level": 4
      },
      {
        "id": "app/guides/conditional-testing#use-cookies-to-know-ahead-of-time",
        "text": "Use Cookies to know ahead of time:",
        "level": 4
      },
      {
        "id": "app/guides/conditional-testing#use-your-server-or-database",
        "text": "Use your server or database:",
        "level": 4
      },
      {
        "id": "app/guides/conditional-testing#embed-data-in-dom",
        "text": "Embed data in DOM:",
        "level": 4
      },
      {
        "id": "app/guides/conditional-testing#element-existence",
        "text": "Element existence",
        "level": 3
      },
      {
        "id": "app/guides/conditional-testing#dynamic-text",
        "text": "Dynamic text",
        "level": 3
      },
      {
        "id": "app/guides/conditional-testing#conditionally-check-whether-an-element-has-certain-text",
        "text": "Conditionally check whether an element has certain text:",
        "level": 4
      },
      {
        "id": "app/guides/conditional-testing#error-recovery",
        "text": "Error Recovery",
        "level": 2
      }
    ]
  },
  "chunks": [
    {
      "id": "app/guides/conditional-testing#what-youll-learn",
      "doc_id": "app/guides/conditional-testing",
      "heading": "What you'll learn",
      "heading_level": 5,
      "content_markdown": "##### What you'll learn\n\n*   Why conditional testing is difficult\n*   How to overcome the problems with conditional testing\n*   Strategies to achieve conditional testing without relying on the DOM\n*   How to recover from failed Cypress commands\n\nConditional testing refers to the common programming pattern:\n\nIf X, then Y, else Z\n\nMany of our users ask how to accomplish this in Cypress. **Here are some example use cases:**\n\n*   How do I do something different whether an element does or doesn't exist?\n*   My application does A/B testing, how do I account for that?\n*   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?\n*   Can I recover from failed Cypress commands like if a [cy.get()](/llm/markdown/api/commands/get.md) doesn't find an element?\n*   I'm trying to write dynamic tests that do something different based on the text on the page.\n*   I want to automatically find all `<a>` elements and based on which ones I find, I want to check that each link works.\n\nThe 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.\n\nLet's investigate why and how you can overcome these problems.\n",
      "section": "app",
      "anchors": [
        "what-youll-learn"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 289
    },
    {
      "id": "app/guides/conditional-testing#the-problem",
      "doc_id": "app/guides/conditional-testing",
      "heading": "The problem",
      "heading_level": 2,
      "content_markdown": "## The problem\n\nWeb applications are often highly dynamic and mutable. Their state and the DOM are continuously changing over a period of time.\n\nThe problem with conditional testing is that it can only be used when the state has stabilized. Knowing when state is stable in a web application is oftentimes difficult.\n\nTo 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.\n\nA human also has intuition. If you click a button and see a loading spinner, you will assume the state is in flux and will automatically wait for it to finish. A robot has no intuition - it will do exactly as it's programmed to do.\n\nTo illustrate this, let's take a straightforward example of trying to conditionally test unstable state.\n\n### The DOM is unstable\n\napp.js\n\n```\nconst random = Math.random() * 100 // random ms of timeconst btn = document.createElement('button')document.body.appendChild(btn)setTimeout(() => {  // add the class active after a random amount of time  btn.setAttribute('class', 'active')}, random)\n```\n\ntest.cy.js\n\n```\nit('does something different based on the class of the button', () => {  // RERUN THIS TEST OVER AND OVER AGAIN  // AND IT WILL SOMETIMES BE TRUE, AND  // SOMETIMES BE FALSE.  cy.get('button').then(($btn) => {    if ($btn.hasClass('active')) {      // do something if it's active    } else {      // do something else    }  })})\n```\n\nDo you see the problem here? This test is non-deterministic. The `<button>` will sometimes have the class `active` and sometimes not. In **most** cases, you can't rely on the state of the DOM to determine what you should conditionally do.\n\nThis is the heart of flaky tests. At Cypress we've designed our API to combat this type of flakiness at every step.\n",
      "section": "app",
      "anchors": [
        "the-problem"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 419
    },
    {
      "id": "app/guides/conditional-testing#the-dom-is-unstable",
      "doc_id": "app/guides/conditional-testing",
      "heading": "The DOM is unstable",
      "heading_level": 3,
      "content_markdown": "### The DOM is unstable\n\napp.js\n\n```\nconst random = Math.random() * 100 // random ms of timeconst btn = document.createElement('button')document.body.appendChild(btn)setTimeout(() => {  // add the class active after a random amount of time  btn.setAttribute('class', 'active')}, random)\n```\n\ntest.cy.js\n\n```\nit('does something different based on the class of the button', () => {  // RERUN THIS TEST OVER AND OVER AGAIN  // AND IT WILL SOMETIMES BE TRUE, AND  // SOMETIMES BE FALSE.  cy.get('button').then(($btn) => {    if ($btn.hasClass('active')) {      // do something if it's active    } else {      // do something else    }  })})\n```\n\nDo you see the problem here? This test is non-deterministic. The `<button>` will sometimes have the class `active` and sometimes not. In **most** cases, you can't rely on the state of the DOM to determine what you should conditionally do.\n\nThis is the heart of flaky tests. At Cypress we've designed our API to combat this type of flakiness at every step.\n",
      "section": "app",
      "anchors": [
        "the-dom-is-unstable"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 209
    },
    {
      "id": "app/guides/conditional-testing#the-situations",
      "doc_id": "app/guides/conditional-testing",
      "heading": "The situations",
      "heading_level": 2,
      "content_markdown": "## The situations\n\nThe **only** way to do conditional testing on the DOM is if you're 100% sure that the state has \"settled\" and there is no possible way for it to change.\n\nThat is it! In any other circumstance you will have flaky tests if you try to rely on the state of the DOM for conditional testing.\n\n**Let's explore a few examples.**\n\n### Server side rendering\n\nIf your application is server side rendered without JavaScript that asynchronously modifies the DOM - congratulations, you can do conditional testing on the DOM!\n\nWhy? Because if the DOM is not going to change after the `load` event occurs, then it can accurately represent a stable state of truth.\n\nYou can safely skip down to the bottom where we provide examples of conditional testing.\n\n### Client side rendering\n\nHowever, in most applications - when the `load` event occurs, that doesn't usually mean everything is rendered on the screen. It is usually at this moment that your scripts begin to load dynamic content and begin to render asynchronously.\n\nUnfortunately, it's not possible for you to use the DOM to do conditional testing. To do this would require you to know with 100% guarantee that your application has finished all asynchronous rendering and that there are no pending network requests, setTimeouts, intervals, postMessage, or async/await code.\n\nThis is difficult to do without making changes to your application. In other words, you cannot do conditional testing safely if you want your tests to run 100% consistently.\n\nBut do not fret - there are workarounds to still achieve conditional testing **without** relying on the DOM. You have to _anchor_ yourself to another piece of truth that is not mutable.\n",
      "section": "app",
      "anchors": [
        "the-situations"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 377
    },
    {
      "id": "app/guides/conditional-testing#server-side-rendering",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Server side rendering",
      "heading_level": 3,
      "content_markdown": "### Server side rendering\n\nIf your application is server side rendered without JavaScript that asynchronously modifies the DOM - congratulations, you can do conditional testing on the DOM!\n\nWhy? Because if the DOM is not going to change after the `load` event occurs, then it can accurately represent a stable state of truth.\n\nYou can safely skip down to the bottom where we provide examples of conditional testing.\n",
      "section": "app",
      "anchors": [
        "server-side-rendering"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 91
    },
    {
      "id": "app/guides/conditional-testing#client-side-rendering",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Client side rendering",
      "heading_level": 3,
      "content_markdown": "### Client side rendering\n\nHowever, in most applications - when the `load` event occurs, that doesn't usually mean everything is rendered on the screen. It is usually at this moment that your scripts begin to load dynamic content and begin to render asynchronously.\n\nUnfortunately, it's not possible for you to use the DOM to do conditional testing. To do this would require you to know with 100% guarantee that your application has finished all asynchronous rendering and that there are no pending network requests, setTimeouts, intervals, postMessage, or async/await code.\n\nThis is difficult to do without making changes to your application. In other words, you cannot do conditional testing safely if you want your tests to run 100% consistently.\n\nBut do not fret - there are workarounds to still achieve conditional testing **without** relying on the DOM. You have to _anchor_ yourself to another piece of truth that is not mutable.\n",
      "section": "app",
      "anchors": [
        "client-side-rendering"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 201
    },
    {
      "id": "app/guides/conditional-testing#the-strategies",
      "doc_id": "app/guides/conditional-testing",
      "heading": "The strategies",
      "heading_level": 2,
      "content_markdown": "## The strategies\n\nIf you're unable to guarantee that the DOM is stable - there are other ways you can do conditional testing or work around the problems inherent with it.\n\n**You could:**\n\n*   Remove the need to ever do conditional testing.\n*   Force your application to behave deterministically.\n*   Check other sources of truth (like your server or database).\n*   Embed data into other places (cookies / local storage) to evaluate.\n*   Add data to the DOM that you can evaluate to know how to proceed.\n\nLet's explore some examples of conditional testing that will pass or fail 100% of the time.\n\n### A/B campaign[\n\nEnd-to-End Only\n\n](/llm/markdown/app/core-concepts/testing-types.md#What-is-E2E-Testing)\n\nIn this example let's assume you visit your website and the content will be different based on which A/B campaign your server decides to send. Perhaps it's based on geo-location, IP address, time of day, locale, or other factors that are difficult to control. How can you write tests in this manner?\n\nControl which campaign gets sent, or provide a reliable means to know which one it is.\n\n#### Use URL query params:\n\n```\n// tell your back end server which campaign you want sent// so you can deterministically know what it is ahead of timecy.visit('https://example.cypress.io?campaign=A')// tests...cy.visit('https://example.cypress.io?campaign=B')// tests...cy.visit('https://example.cypress.io?campaign=C')// tests...\n```\n\nNow there is not even a need to do conditional testing since you're able to know ahead of time what campaign was sent. Yes, this may require server side updates, but you have to make an untestable app testable if you want to test it!\n\n#### Use the server:\n\nAlternatively, if your server saves the campaign with a session, you could ask your server to tell you which campaign you are on.\n\n```\n// this sends us the session cookiescy.visit('https://example.cypress.io')// assuming this sends us back// the campaign informationcy.request('https://example.cypress.io/me')  .its('body.campaign')  .then((campaign) => {    // runs different cypress test code    // based on the type of campaign    return campaigns.test(campaign)  })\n```\n\n#### Use session cookies:\n\nAnother way to test this is if your server sent the campaign in a session cookie that you could read off.\n\n```\ncy.visit('https://example.cypress.io')cy.getCookie('campaign').then((campaign) => {  return campaigns.test(campaign)})\n```\n\n#### Embed data in the DOM:\n\nAnother valid strategy would be to embed data directly into the DOM - but do so in a way where this data is **always** present and query-able. It would have to be present 100% of the time, else this would not work.\n\n```\ncy.get('html')  .should('have.attr', 'data-campaign')  .then((campaign) => {    return campaigns.test(campaign)  })\n```\n\n### Welcome wizard[\n\nEnd-to-End Only\n\n](/llm/markdown/app/core-concepts/testing-types.md#What-is-E2E-Testing)\n\nIn this example, let's imagine you're running a bunch of tests and each time you load your application, it may show a \"Welcome Wizard\" modal.\n\nIn this situation, you want to close the wizard when it is present and ignore it if it is not.\n\nThe problem with this is that if the wizard renders asynchronously (as it likely does) you cannot use the DOM to conditionally dismiss it.\n\nOnce again - we will need another reliable way to achieve this without involving the DOM.\n\nThese patterns are pretty much the same as before:\n\n#### Use the URL to control it:\n\n```\n// dont show the wizardcy.visit('https://example.cypress.io?wizard=0')\n```\n\n```\n// show the wizardcy.visit('https://example.cypress.io?wizard=1')\n```\n\nWe'd likely need to update our client side code to check whether this query param is present. Now we know ahead of time whether it will or will not be shown.\n\n#### Use Cookies to know ahead of time:\n\nIn the case where you cannot control it, you can still conditionally dismiss it **if** you know whether it is going to be shown.\n\n```\ncy.visit('https://example.cypress.io')cy.getCookie('showWizard').then((val) => {  if (val) {    // dismiss the wizard conditionally by enqueuing these    // three additional commands    cy.get('#wizard').contains('Close').click()  }})\n```\n\n#### Use your server or database:\n\nIf you store and/or persist whether to show the wizard on the server, then ask it.\n\n```\ncy.visit('https://example.cypress.io')cy.request('https://example.cypress.io/me')  .its('body.showWizard')  .then((val) => {    if (val) {      // dismiss the wizard conditionally by enqueuing these      // three additional commands      cy.get('#wizard').contains('Close').click()    }  })\n```\n\nAlternatively, if you are creating users, it might take less time to create the user and set whether you want the wizard to be shown ahead of time. That would avoid this check later.\n\n#### Embed data in DOM:\n\nAnother valid strategy would be to embed data directly into the DOM but to do so in a way that the data is **always** present and query-able. The data would have to be present 100% of the time, otherwise this strategy would not work.\n\n```\ncy.get('html')  .should('have.attr', 'data-wizard')  .then((wizard) => {    if (wizard) {      // dismiss the wizard conditionally by enqueuing these      // three additional commands      cy.get('#wizard').contains('Close').click()    }  })\n```\n\n### Element existence\n\nIn the case where you **are** trying to use the DOM to do conditional testing, you can utilize the ability to synchronously query for elements in Cypress to create control flow.\n\nIn the event you didn't read a word above and skipped down here, we'll reiterate it one more time:\n\nYou cannot do conditional testing on the DOM unless you are either:\n\n*   Server side rendering with no asynchronous JavaScript.\n*   Using client side JavaScript that **only** ever does synchronous rendering.\n\nIt's crucial that you understand how your application works else you will write flaky tests.\n\nLet's imagine we have a scenario where our application may do two separate things that we're unable to control. In other words you tried every strategy above and for whatever reason you were unable to know ahead of time what your application will do.\n\nTesting this in Cypress is possible.\n\napp.js\n\n```\n$('button').on('click', (e) => {  // do something synchronously randomly  if (Math.random() < 0.5) {    // append an input    $('<input />').appendTo($('body'))  } else {    // or append a textarea    $('<textarea />').appendTo($('body'))  }})\n```\n\ntest.cy.js\n\n```\n// click the button causing the new elements to appearcy.get('button').click()cy.get('body')  .then(($body) => {    // synchronously query from body    // to find which element was created    if ($body.find('input').length) {      // input was found, do something else here      return 'input'    }    // else assume it was textarea    return 'textarea'  })  .then((selector) => {    // selector is a string that represents    // the selector we could use to find it    cy.get(selector).type(`found the element by selector ${selector}`)  })\n```\n\nWe'll reiterate one more time. Had the `<input>` or the `<textarea>` been rendered asynchronously, you couldn't use the pattern above. You'd have to involve arbitrary delays which won't work in every situation, will slow down your tests, and will still leave chances that your tests are flaky.\n\nCypress is built around creating **reliable tests**. The secret to writing good tests is to provide as much \"state\" and \"facts\" to Cypress and to \"guard it\" from issuing new commands until your application has reached the desired state it needs to proceed.\n\nDoing conditional testing adds a huge problem - that the test writers themselves are unsure what the given state will be. In those situations, the only reliable way to have accurate tests is to embed this dynamic state in a reliable and consistent way.\n\nIf you're not sure if you've written a potentially flaky test, there's a way to figure it out. Repeat the test an excessive number of times, and then repeat by modifying the Developer Tools to throttle the Network and the CPU. This will create different loads that simulate different environments (like CI). If you've written a good test, it will pass or fail 100% of the time.\n\n```\nCypress._.times(100, (i) => {  it(`num ${i + 1} - test the thing conditionally`, () => {    // do the conditional bits 100 times  })})\n```\n\n### Dynamic text\n\nThe pattern of doing something conditionally based on whether or not certain text is present is identical to element existence above.\n\n#### Conditionally check whether an element has certain text:\n\n```\n// this only works if there's 100% guarantee// body has fully rendered without any pending changes// to its statecy.get('body').then(($body) => {    // synchronously ask for the body's text    // and do something based on whether it includes    // another string    if ($body.text().includes('some string')) {      // yup found it      cy.get(...).should(...)    } else {      // nope not here      cy.get(...).should(...)    }  })\n```\n",
      "section": "app",
      "anchors": [
        "the-strategies"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 1801
    },
    {
      "id": "app/guides/conditional-testing#a-b-campaign",
      "doc_id": "app/guides/conditional-testing",
      "heading": "A/B campaign[",
      "heading_level": 3,
      "content_markdown": "### A/B campaign[\n\nEnd-to-End Only\n\n](/llm/markdown/app/core-concepts/testing-types.md#What-is-E2E-Testing)\n\nIn this example let's assume you visit your website and the content will be different based on which A/B campaign your server decides to send. Perhaps it's based on geo-location, IP address, time of day, locale, or other factors that are difficult to control. How can you write tests in this manner?\n\nControl which campaign gets sent, or provide a reliable means to know which one it is.\n\n#### Use URL query params:\n\n```\n// tell your back end server which campaign you want sent// so you can deterministically know what it is ahead of timecy.visit('https://example.cypress.io?campaign=A')// tests...cy.visit('https://example.cypress.io?campaign=B')// tests...cy.visit('https://example.cypress.io?campaign=C')// tests...\n```\n\nNow there is not even a need to do conditional testing since you're able to know ahead of time what campaign was sent. Yes, this may require server side updates, but you have to make an untestable app testable if you want to test it!\n\n#### Use the server:\n\nAlternatively, if your server saves the campaign with a session, you could ask your server to tell you which campaign you are on.\n\n```\n// this sends us the session cookiescy.visit('https://example.cypress.io')// assuming this sends us back// the campaign informationcy.request('https://example.cypress.io/me')  .its('body.campaign')  .then((campaign) => {    // runs different cypress test code    // based on the type of campaign    return campaigns.test(campaign)  })\n```\n\n#### Use session cookies:\n\nAnother way to test this is if your server sent the campaign in a session cookie that you could read off.\n\n```\ncy.visit('https://example.cypress.io')cy.getCookie('campaign').then((campaign) => {  return campaigns.test(campaign)})\n```\n\n#### Embed data in the DOM:\n\nAnother valid strategy would be to embed data directly into the DOM - but do so in a way where this data is **always** present and query-able. It would have to be present 100% of the time, else this would not work.\n\n```\ncy.get('html')  .should('have.attr', 'data-campaign')  .then((campaign) => {    return campaigns.test(campaign)  })\n```\n",
      "section": "app",
      "anchors": [
        "a-b-campaign"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 408
    },
    {
      "id": "app/guides/conditional-testing#use-url-query-params",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Use URL query params:",
      "heading_level": 4,
      "content_markdown": "#### Use URL query params:\n\n```\n// tell your back end server which campaign you want sent// so you can deterministically know what it is ahead of timecy.visit('https://example.cypress.io?campaign=A')// tests...cy.visit('https://example.cypress.io?campaign=B')// tests...cy.visit('https://example.cypress.io?campaign=C')// tests...\n```\n\nNow there is not even a need to do conditional testing since you're able to know ahead of time what campaign was sent. Yes, this may require server side updates, but you have to make an untestable app testable if you want to test it!\n",
      "section": "app",
      "anchors": [
        "use-url-query-params"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 103
    },
    {
      "id": "app/guides/conditional-testing#use-the-server",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Use the server:",
      "heading_level": 4,
      "content_markdown": "#### Use the server:\n\nAlternatively, if your server saves the campaign with a session, you could ask your server to tell you which campaign you are on.\n\n```\n// this sends us the session cookiescy.visit('https://example.cypress.io')// assuming this sends us back// the campaign informationcy.request('https://example.cypress.io/me')  .its('body.campaign')  .then((campaign) => {    // runs different cypress test code    // based on the type of campaign    return campaigns.test(campaign)  })\n```\n",
      "section": "app",
      "anchors": [
        "use-the-server"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 85
    },
    {
      "id": "app/guides/conditional-testing#use-session-cookies",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Use session cookies:",
      "heading_level": 4,
      "content_markdown": "#### Use session cookies:\n\nAnother way to test this is if your server sent the campaign in a session cookie that you could read off.\n\n```\ncy.visit('https://example.cypress.io')cy.getCookie('campaign').then((campaign) => {  return campaigns.test(campaign)})\n```\n",
      "section": "app",
      "anchors": [
        "use-session-cookies"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 43
    },
    {
      "id": "app/guides/conditional-testing#embed-data-in-the-dom",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Embed data in the DOM:",
      "heading_level": 4,
      "content_markdown": "#### Embed data in the DOM:\n\nAnother valid strategy would be to embed data directly into the DOM - but do so in a way where this data is **always** present and query-able. It would have to be present 100% of the time, else this would not work.\n\n```\ncy.get('html')  .should('have.attr', 'data-campaign')  .then((campaign) => {    return campaigns.test(campaign)  })\n```\n",
      "section": "app",
      "anchors": [
        "embed-data-in-the-dom"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 79
    },
    {
      "id": "app/guides/conditional-testing#welcome-wizard",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Welcome wizard[",
      "heading_level": 3,
      "content_markdown": "### Welcome wizard[\n\nEnd-to-End Only\n\n](/llm/markdown/app/core-concepts/testing-types.md#What-is-E2E-Testing)\n\nIn this example, let's imagine you're running a bunch of tests and each time you load your application, it may show a \"Welcome Wizard\" modal.\n\nIn this situation, you want to close the wizard when it is present and ignore it if it is not.\n\nThe problem with this is that if the wizard renders asynchronously (as it likely does) you cannot use the DOM to conditionally dismiss it.\n\nOnce again - we will need another reliable way to achieve this without involving the DOM.\n\nThese patterns are pretty much the same as before:\n\n#### Use the URL to control it:\n\n```\n// dont show the wizardcy.visit('https://example.cypress.io?wizard=0')\n```\n\n```\n// show the wizardcy.visit('https://example.cypress.io?wizard=1')\n```\n\nWe'd likely need to update our client side code to check whether this query param is present. Now we know ahead of time whether it will or will not be shown.\n\n#### Use Cookies to know ahead of time:\n\nIn the case where you cannot control it, you can still conditionally dismiss it **if** you know whether it is going to be shown.\n\n```\ncy.visit('https://example.cypress.io')cy.getCookie('showWizard').then((val) => {  if (val) {    // dismiss the wizard conditionally by enqueuing these    // three additional commands    cy.get('#wizard').contains('Close').click()  }})\n```\n\n#### Use your server or database:\n\nIf you store and/or persist whether to show the wizard on the server, then ask it.\n\n```\ncy.visit('https://example.cypress.io')cy.request('https://example.cypress.io/me')  .its('body.showWizard')  .then((val) => {    if (val) {      // dismiss the wizard conditionally by enqueuing these      // three additional commands      cy.get('#wizard').contains('Close').click()    }  })\n```\n\nAlternatively, if you are creating users, it might take less time to create the user and set whether you want the wizard to be shown ahead of time. That would avoid this check later.\n\n#### Embed data in DOM:\n\nAnother valid strategy would be to embed data directly into the DOM but to do so in a way that the data is **always** present and query-able. The data would have to be present 100% of the time, otherwise this strategy would not work.\n\n```\ncy.get('html')  .should('have.attr', 'data-wizard')  .then((wizard) => {    if (wizard) {      // dismiss the wizard conditionally by enqueuing these      // three additional commands      cy.get('#wizard').contains('Close').click()    }  })\n```\n",
      "section": "app",
      "anchors": [
        "welcome-wizard"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 481
    },
    {
      "id": "app/guides/conditional-testing#use-the-url-to-control-it",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Use the URL to control it:",
      "heading_level": 4,
      "content_markdown": "#### Use the URL to control it:\n\n```\n// dont show the wizardcy.visit('https://example.cypress.io?wizard=0')\n```\n\n```\n// show the wizardcy.visit('https://example.cypress.io?wizard=1')\n```\n\nWe'd likely need to update our client side code to check whether this query param is present. Now we know ahead of time whether it will or will not be shown.\n",
      "section": "app",
      "anchors": [
        "use-the-url-to-control-it"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 68
    },
    {
      "id": "app/guides/conditional-testing#use-cookies-to-know-ahead-of-time",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Use Cookies to know ahead of time:",
      "heading_level": 4,
      "content_markdown": "#### Use Cookies to know ahead of time:\n\nIn the case where you cannot control it, you can still conditionally dismiss it **if** you know whether it is going to be shown.\n\n```\ncy.visit('https://example.cypress.io')cy.getCookie('showWizard').then((val) => {  if (val) {    // dismiss the wizard conditionally by enqueuing these    // three additional commands    cy.get('#wizard').contains('Close').click()  }})\n```\n",
      "section": "app",
      "anchors": [
        "use-cookies-to-know-ahead-of-time"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 72
    },
    {
      "id": "app/guides/conditional-testing#use-your-server-or-database",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Use your server or database:",
      "heading_level": 4,
      "content_markdown": "#### Use your server or database:\n\nIf you store and/or persist whether to show the wizard on the server, then ask it.\n\n```\ncy.visit('https://example.cypress.io')cy.request('https://example.cypress.io/me')  .its('body.showWizard')  .then((val) => {    if (val) {      // dismiss the wizard conditionally by enqueuing these      // three additional commands      cy.get('#wizard').contains('Close').click()    }  })\n```\n\nAlternatively, if you are creating users, it might take less time to create the user and set whether you want the wizard to be shown ahead of time. That would avoid this check later.\n",
      "section": "app",
      "anchors": [
        "use-your-server-or-database"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 108
    },
    {
      "id": "app/guides/conditional-testing#embed-data-in-dom",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Embed data in DOM:",
      "heading_level": 4,
      "content_markdown": "#### Embed data in DOM:\n\nAnother valid strategy would be to embed data directly into the DOM but to do so in a way that the data is **always** present and query-able. The data would have to be present 100% of the time, otherwise this strategy would not work.\n\n```\ncy.get('html')  .should('have.attr', 'data-wizard')  .then((wizard) => {    if (wizard) {      // dismiss the wizard conditionally by enqueuing these      // three additional commands      cy.get('#wizard').contains('Close').click()    }  })\n```\n",
      "section": "app",
      "anchors": [
        "embed-data-in-dom"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 100
    },
    {
      "id": "app/guides/conditional-testing#element-existence",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Element existence",
      "heading_level": 3,
      "content_markdown": "### Element existence\n\nIn the case where you **are** trying to use the DOM to do conditional testing, you can utilize the ability to synchronously query for elements in Cypress to create control flow.\n\nIn the event you didn't read a word above and skipped down here, we'll reiterate it one more time:\n\nYou cannot do conditional testing on the DOM unless you are either:\n\n*   Server side rendering with no asynchronous JavaScript.\n*   Using client side JavaScript that **only** ever does synchronous rendering.\n\nIt's crucial that you understand how your application works else you will write flaky tests.\n\nLet's imagine we have a scenario where our application may do two separate things that we're unable to control. In other words you tried every strategy above and for whatever reason you were unable to know ahead of time what your application will do.\n\nTesting this in Cypress is possible.\n\napp.js\n\n```\n$('button').on('click', (e) => {  // do something synchronously randomly  if (Math.random() < 0.5) {    // append an input    $('<input />').appendTo($('body'))  } else {    // or append a textarea    $('<textarea />').appendTo($('body'))  }})\n```\n\ntest.cy.js\n\n```\n// click the button causing the new elements to appearcy.get('button').click()cy.get('body')  .then(($body) => {    // synchronously query from body    // to find which element was created    if ($body.find('input').length) {      // input was found, do something else here      return 'input'    }    // else assume it was textarea    return 'textarea'  })  .then((selector) => {    // selector is a string that represents    // the selector we could use to find it    cy.get(selector).type(`found the element by selector ${selector}`)  })\n```\n\nWe'll reiterate one more time. Had the `<input>` or the `<textarea>` been rendered asynchronously, you couldn't use the pattern above. You'd have to involve arbitrary delays which won't work in every situation, will slow down your tests, and will still leave chances that your tests are flaky.\n\nCypress is built around creating **reliable tests**. The secret to writing good tests is to provide as much \"state\" and \"facts\" to Cypress and to \"guard it\" from issuing new commands until your application has reached the desired state it needs to proceed.\n\nDoing conditional testing adds a huge problem - that the test writers themselves are unsure what the given state will be. In those situations, the only reliable way to have accurate tests is to embed this dynamic state in a reliable and consistent way.\n\nIf you're not sure if you've written a potentially flaky test, there's a way to figure it out. Repeat the test an excessive number of times, and then repeat by modifying the Developer Tools to throttle the Network and the CPU. This will create different loads that simulate different environments (like CI). If you've written a good test, it will pass or fail 100% of the time.\n\n```\nCypress._.times(100, (i) => {  it(`num ${i + 1} - test the thing conditionally`, () => {    // do the conditional bits 100 times  })})\n```\n",
      "section": "app",
      "anchors": [
        "element-existence"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 649
    },
    {
      "id": "app/guides/conditional-testing#dynamic-text",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Dynamic text",
      "heading_level": 3,
      "content_markdown": "### Dynamic text\n\nThe pattern of doing something conditionally based on whether or not certain text is present is identical to element existence above.\n\n#### Conditionally check whether an element has certain text:\n\n```\n// this only works if there's 100% guarantee// body has fully rendered without any pending changes// to its statecy.get('body').then(($body) => {    // synchronously ask for the body's text    // and do something based on whether it includes    // another string    if ($body.text().includes('some string')) {      // yup found it      cy.get(...).should(...)    } else {      // nope not here      cy.get(...).should(...)    }  })\n```\n",
      "section": "app",
      "anchors": [
        "dynamic-text"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 125
    },
    {
      "id": "app/guides/conditional-testing#conditionally-check-whether-an-element-has-certain-text",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Conditionally check whether an element has certain text:",
      "heading_level": 4,
      "content_markdown": "#### Conditionally check whether an element has certain text:\n\n```\n// this only works if there's 100% guarantee// body has fully rendered without any pending changes// to its statecy.get('body').then(($body) => {    // synchronously ask for the body's text    // and do something based on whether it includes    // another string    if ($body.text().includes('some string')) {      // yup found it      cy.get(...).should(...)    } else {      // nope not here      cy.get(...).should(...)    }  })\n```\n",
      "section": "app",
      "anchors": [
        "conditionally-check-whether-an-element-has-certain-text"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 93
    },
    {
      "id": "app/guides/conditional-testing#error-recovery",
      "doc_id": "app/guides/conditional-testing",
      "heading": "Error Recovery",
      "heading_level": 2,
      "content_markdown": "## Error Recovery\n\nMany of our users ask how they can recover from failed commands.\n\n> If I had error handling, I could try to find X and if X fails go find Y\n\nBecause error handling is a common idiom in most programming languages, and especially in Node, it seems reasonable to expect to do that in Cypress.\n\nHowever, this is really the same question as asking to do conditional testing, but wrapped up in a slightly different implementation detail.\n\nFor instance you may want to do this:\n\nThe following code is not valid.\n\n```\n//! You cannot add error handling to Cypress commands//! This code is just for demonstration purposescy.get('button')  .contains('hello')  .catch((err) => {    // oh no the button wasn't found    // (or something else failed)    cy.get('somethingElse').click()  })\n```\n\nIf you've been reading along, then you should already have a grasp on why trying to implement conditional code with asynchronous rendering is not a good idea. If the test writer cannot accurately predict the given state of the system, then neither can Cypress. Error handling offers no additional proof this can be done deterministically.\n\nYou should think of failed commands in Cypress as akin to uncaught exceptions in server side code. It's not possible to try to recover in those scenarios because the system has transitioned to an unreliable state. Instead you generally always opt to crash and log. When Cypress fails the test - that is exactly what it is doing. Bailing out, skipping any remaining commands in the test, and logging out the failure.\n\nBut... for the sake of the argument, let's imagine for a moment you did have error handling in Cypress.\n\nEnabling this would mean that for every single command, it would recover from errors, but only after each applicable command timeout was reached. Since timeouts start at 4 seconds (and exceed from there), this means that it would only fail after a long, long time.\n\nLet's reimagine our \"Welcome Wizard\" example from before.\n\nThe following code is not valid.\n\n```\n//! You cannot add error handling to Cypress commands.//! This code is just for demonstration purposesfunction keepCalmAndCarryOn () {  cy.get(...).should(...).click()}cy  .get('#wizard').contains('Close').click()  .catch((err) => {    // no problem, i guess the wizard didn't exist    // or something... no worries    keepCalmAndCarryOn()  })  .then(keepCalmAndCarryOn)\n```\n\nIn the **best** case scenario, we have wasted at LEAST 4 seconds waiting on the `<#wizard>` element to possibly exist before we errored and continued on.\n\nBut in the **worst** case scenario we have a situation where the `<#wizard>` **was** going to be rendered, but it didn't render within our given timeout. Let's assume this was due to a pending network request or WebSocket message or a queued timer, or anything else.\n\nIn this situation, not only did we wait a long period of time, but when the `<#wizard>` element was eventually shown it's likely caused an error downstream on other commands.\n\nIf you cannot accurately know the state of your application then no matter what programming idioms you have available - **you cannot write 100% deterministic tests**.\n",
      "section": "app",
      "anchors": [
        "error-recovery"
      ],
      "path": "/llm/json/chunked/app/guides/conditional-testing.json",
      "token_estimate": 676
    }
  ]
}