{
  "doc": {
    "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress",
    "title": "Migrate from Selenium to Cypress: complete migration guide",
    "description": "Step-by-step guide to migrate Selenium WebDriver tests to Cypress. Map locators, waits, WebDriver lifecycle, assertions, alerts, frames, network stubbing, Page Objects, Grid, and CI side by side.",
    "section": "app",
    "source_path": "/llm/markdown/app/get-started/migrate-from-another-tool/selenium-to-cypress.md",
    "version": "e4f4d57da4cfedd520d3d465137d387fd54b532f",
    "updated_at": "2026-09-08T17:49:12.214Z",
    "headings": [
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#migrating-from-selenium-to-cypress",
        "text": "Migrating from Selenium to Cypress",
        "level": 1
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#quick-conversion-example",
        "text": "Quick conversion example",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#key-differences-at-a-glance",
        "text": "Key differences at a glance",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#confirm-your-target-language",
        "text": "Confirm your target language",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#installing-cypress",
        "text": "Installing Cypress",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#configuration-migration",
        "text": "Configuration migration",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#command-line-migration",
        "text": "Command line migration",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#passing-environment-variables-and-secrets",
        "text": "Passing environment variables and secrets",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#browser-and-driver-management",
        "text": "Browser and driver management",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#browser-launch-options",
        "text": "Browser launch options",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#reproducible-ci-browser-versions",
        "text": "Reproducible CI browser versions",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#starting-your-application-under-test",
        "text": "Starting your application under test",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#test-structure-and-runner-migration",
        "text": "Test structure and runner migration",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#deleting-the-webdriver-lifecycle",
        "text": "Deleting the WebDriver lifecycle",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#execution-model-waits-and-retry-ability",
        "text": "Execution model, waits, and retry-ability",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#choosing-a-selector-strategy",
        "text": "Choosing a selector strategy",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#finding-multiple-elements",
        "text": "Finding multiple elements",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#interactions",
        "text": "Interactions",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#click-type-and-clear",
        "text": "Click, type, and clear",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#dropdowns-checkboxes-and-radios",
        "text": "Dropdowns, checkboxes, and radios",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#hover-right-click-double-click-and-keyboard",
        "text": "Hover, right-click, double-click, and keyboard",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#scrolling-and-viewport",
        "text": "Scrolling and viewport",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#assertions",
        "text": "Assertions",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#network-spying-and-stubbing",
        "text": "Network spying and stubbing",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#wait-for-a-request-deterministically",
        "text": "Wait for a request deterministically",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#stub-a-response",
        "text": "Stub a response",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#authentication",
        "text": "Authentication",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#alerts-confirms-and-prompts",
        "text": "Alerts, confirms, and prompts",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#frames-and-iframes",
        "text": "Frames and iframes",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#multiple-tabs-and-windows",
        "text": "Multiple tabs and windows",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#file-uploads-and-downloads",
        "text": "File uploads and downloads",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#upload",
        "text": "Upload",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#download",
        "text": "Download",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#screenshots",
        "text": "Screenshots",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#api-testing",
        "text": "API testing",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#reusable-code-patterns",
        "text": "Reusable code patterns",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#page-object-model",
        "text": "Page Object Model",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#data-driven-tests",
        "text": "Data-driven tests",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#migrating-a-cucumber-suite",
        "text": "Migrating a Cucumber suite",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#replacing-selenium-grid",
        "text": "Replacing Selenium Grid",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#smart-orchestration",
        "text": "Smart Orchestration",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#debugging-ci-with-test-replay",
        "text": "Debugging CI with Test Replay",
        "level": 3
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#integration-with-your-ci-cd-pipeline",
        "text": "Integration with your CI/CD pipeline",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#cheat-sheet",
        "text": "Cheat sheet",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#conclusion",
        "text": "Conclusion",
        "level": 2
      },
      {
        "id": "app/get-started/migrate-from-another-tool/selenium-to-cypress#see-also",
        "text": "See also",
        "level": 2
      }
    ]
  },
  "content": {
    "type": "root",
    "children": [
      {
        "type": "heading",
        "depth": 1,
        "children": [
          {
            "type": "text",
            "value": "Migrating from Selenium to Cypress"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This guide helps you translate Selenium WebDriver tests to Cypress. It covers the core execution-model differences, the WebDriver lifecycle you can delete, locator and assertion mappings, and patterns for waits, network stubbing, alerts, frames, authentication, and CI."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The biggest conceptual shift is not syntax. Cypress runs inside the browser alongside your application, rather than driving it remotely over the WebDriver protocol. That single difference is what lets Cypress "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/core-concepts/retry-ability.md",
            "children": [
              {
                "type": "text",
                "value": "wait automatically"
              }
            ]
          },
          {
            "type": "text",
            "value": ", stub network traffic, and time-travel through your tests, and it is why most of the `wait`, `driver`, and `switchTo` machinery in a Selenium suite simply disappears."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Most migrations are incremental. You do not need to migrate all tests at once. Cypress and Selenium can coexist in the same repository during a transition."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Jump to the "
          },
          {
            "type": "link",
            "title": null,
            "url": "#Cheat-sheet",
            "children": [
              {
                "type": "text",
                "value": "cheat sheet"
              }
            ]
          },
          {
            "type": "text",
            "value": " for a quick reference."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Quick conversion example"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Here's a side-by-side comparison showing how a Selenium test translates to Cypress. The Selenium examples throughout this guide use the JavaScript bindings (`selenium-webdriver`) with Mocha, but the same patterns apply to the Java, Python, C#, and Ruby bindings."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "authorization.test.js"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { Builder, By, until } = require('selenium-webdriver')\nconst assert = require('assert')\n\ndescribe('Authorization', function () {\n  let driver\n\n  beforeEach(async function () {\n    driver = await new Builder().forBrowser('chrome').build()\n  })\n\n  afterEach(async function () {\n    await driver.quit()\n  })\n\n  it('signs up', async function () {\n    await driver.get('http://localhost:3000/signup')\n\n    await driver.findElement(By.id('email')).sendKeys('user@email.com')\n    await driver.findElement(By.id('confirm-email')).sendKeys('user@email.com')\n    await driver.findElement(By.id('password')).sendKeys('testPassword1234')\n\n    await driver.findElement(By.css('button[type=submit]')).click()\n\n    await driver.wait(until.urlContains('/signup/success'), 10000)\n    const url = await driver.getCurrentUrl()\n    assert(url.includes('/signup/success'))\n  })\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "authorization.cy.js"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "describe('Authorization', () => {\n  it('signs up', () => {\n    // No driver setup or teardown. Cypress manages the browser\n    cy.visit('/signup')\n\n    cy.get('[data-testid=\"email\"]').type('user@email.com')\n    cy.get('[data-testid=\"confirm-email\"]').type('user@email.com')\n    cy.get('[data-testid=\"password\"]').type('testPassword1234')\n\n    cy.get('button[type=submit]').click()\n\n    // No explicit wait needed; the assertion retries until it passes\n    cy.url().should('include', '/signup/success')\n  })\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "authorization.cy.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "describe('Authorization', () => {\n  it('signs up', () => {\n    // No driver setup or teardown. Cypress manages the browser\n    cy.visit('/signup')\n\n    cy.get('[data-testid=\"email\"]').type('user@email.com')\n    cy.get('[data-testid=\"confirm-email\"]').type('user@email.com')\n    cy.get('[data-testid=\"password\"]').type('testPassword1234')\n\n    cy.get('button[type=submit]').click()\n\n    // No explicit wait needed; the assertion retries until it passes\n    cy.url().should('include', '/signup/success')\n  })\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Notice what disappeared: the `Builder` and `driver` setup, the `beforeEach`/`afterEach` lifecycle, the `driver.quit()`, the `await` on every call, and the explicit `driver.wait(until...)`. Cypress opens and closes the browser for you and retries commands and assertions automatically."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Key differences at a glance"
          }
        ]
      },
      {
        "type": "table",
        "align": [
          null,
          null,
          null
        ],
        "children": [
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Concern"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Selenium"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Language"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Java, Python, C#, JavaScript, Ruby"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript / TypeScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Where tests run"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Out of process, driving the browser over the WebDriver protocol"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Inside the browser, in the same run loop as your app"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Browser lifecycle"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "You create and quit the `driver`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Managed by Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Drivers"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "ChromeDriver/GeckoDriver etc. (via Selenium Manager or WebDriverManager)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "None"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Waiting"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Implicit + explicit waits (`driver.wait()`, `until`)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Built-in "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/core-concepts/retry-ability.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "retry-ability"
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Test runner"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "JUnit / TestNG / pytest / NUnit / Mocha"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/core-concepts/writing-and-organizing-tests.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Mocha"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " (`describe`/`it`)"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Assertions"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Provided by the test runner or a matcher library"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Built-in "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/references/assertions.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Chai"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " `.should()` / `expect()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Network control"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Not built in (requires a proxy like BrowserMob)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/api/commands/intercept.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "`cy.intercept()`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " built in"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Cross-machine scale"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Selenium Grid"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/cloud/get-started/introduction.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Cypress Cloud"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " parallelization"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Debugging CI runs"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Logs, screenshots"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/cloud/features/test-replay.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Test Replay"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": ", time-travel, screenshots, videos"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Confirm your target language"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium is a multi-language framework; Cypress tests are written in JavaScript or TypeScript and run in Node. This is the most important planning decision in a Selenium migration:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "From JavaScript/TypeScript Selenium (WebDriverJS): the language stays the same. You are translating one API to another."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "From Java, Python, C#, or Ruby: the tests must be rewritten, not transpiled. Any helper code, data builders, or business logic that lives in your test framework (not your application) has to be reimplemented in JavaScript/TypeScript. Identify this shared code early; it is often the most time-consuming part of the migration, not the tests themselves."
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "TypeScript is recommended for teams coming from a statically typed language like Java or C#, since it preserves type safety. See "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/tooling/typescript-support.md",
            "children": [
              {
                "type": "text",
                "value": "TypeScript support"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Installing Cypress"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Add Cypress to your project (or to a new `e2e/` project alongside your existing Selenium suite) as a dev dependency."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "npm"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Yarn"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "pnpm"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Bun"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "npm install cypress --save-dev"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "yarn add cypress --dev"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "pnpm add --save-dev cypress"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "bun add --dev cypress"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Unlike Selenium, Cypress does not download or manage separate browser drivers (ChromeDriver, GeckoDriver). It uses browsers already installed on your machine, and bundles Electron so you can run tests immediately after installation with no additional setup."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Once installed, open the Cypress app to complete initial configuration:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "npm"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Yarn"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "pnpm"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Bun"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "npx cypress open"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "yarn cypress open"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "pnpm cypress open"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "bunx cypress open"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The Cypress App walks you through choosing a testing type (end-to-end or component) and generates a starter `cypress.config.js` (or `.ts`) file plus a `cypress/` directory in your project root."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If you are writing tests in TypeScript, add a `tsconfig.json` inside the `cypress/` folder so Cypress globals (`cy`, `Cypress`) type-check:"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "cypress/tsconfig.json"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "{\n  \"compilerOptions\": {\n    \"types\": [\"cypress\", \"node\"]\n  },\n  \"include\": [\"**/*.ts\"]\n}"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Configuration migration"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium has no single configuration file. Its \"configuration\" is spread across driver-setup code, `Options`/`DesiredCapabilities`, implicit-wait settings, and build-tool files (`pom.xml`, `build.gradle`, `pytest.ini`, `testng.xml`). Cypress consolidates the equivalent settings into one "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/references/configuration.md",
            "children": [
              {
                "type": "text",
                "value": "`cypress.config.js`/`.ts`"
              }
            ]
          },
          {
            "type": "text",
            "value": " file."
          }
        ]
      },
      {
        "type": "table",
        "align": [
          null,
          null
        ],
        "children": [
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Selenium concept"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Cypress configuration"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Base/application URL (usually hard-coded or in a properties file)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`e2e.baseUrl`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.manage().timeouts().implicitlyWait(...)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`defaultCommandTimeout`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.manage().window().setSize(...)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`viewportWidth` / `viewportHeight`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Page-load timeout (`pageLoadTimeout`)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`pageLoadTimeout`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Test file locations (`testng.xml`, test source folders)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`e2e.specPattern` (a glob)"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Screenshot/video output directories"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`screenshotsFolder` / `videosFolder`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Retry count (surefire/TestNG `retryAnalyzer`, pytest-rerunfailures)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`retries.runMode` / `retries.openMode`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Global setup/teardown hooks"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`e2e.setupNodeEvents`"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "cypress.config.js"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { defineConfig } = require('cypress')\n\nmodule.exports = defineConfig({\n  viewportWidth: 1280,\n  viewportHeight: 720,\n  e2e: {\n    baseUrl: 'http://localhost:3000',\n    specPattern: 'cypress/e2e/**/*.cy.js',\n    defaultCommandTimeout: 10000,\n    retries: {\n      runMode: 2,\n      openMode: 0,\n    },\n  },\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "cypress.config.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { defineConfig } from 'cypress'\n\nexport default defineConfig({\n  viewportWidth: 1280,\n  viewportHeight: 720,\n  e2e: {\n    baseUrl: 'http://localhost:3000',\n    specPattern: 'cypress/e2e/**/*.cy.ts',\n    defaultCommandTimeout: 10000,\n    retries: {\n      runMode: 2,\n      openMode: 0,\n    },\n  },\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "With `baseUrl` set, `cy.visit('/signup')` resolves against it, the equivalent of concatenating a base URL onto every `driver.get(...)` call."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The official "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/eslint-plugin-cypress",
            "children": [
              {
                "type": "text",
                "value": "`eslint-plugin-cypress`"
              }
            ]
          },
          {
            "type": "text",
            "value": " catches Cypress anti-patterns that a linter can flag in-editor: hard-coded `cy.wait(<number>)` calls (the Cypress equivalent of a `driver.sleep()`), assigning command return values, and unsafe chaining. Install it early so mistranslated Selenium patterns surface as you migrate. See the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/eslint-plugin-cypress#rules",
            "children": [
              {
                "type": "text",
                "value": "full rules list"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Command line migration"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium tests run through a test runner. With the JavaScript bindings that is typically Mocha or Jest, launched with `npm test`. Cypress ships its own binary."
          }
        ]
      },
      {
        "type": "table",
        "align": [
          null,
          null,
          null
        ],
        "children": [
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Task"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Selenium (Mocha/Jest)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Run all tests (headless)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`npm test`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cypress run`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Open interactive mode"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "(none)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cypress open`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Run a single spec"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`mocha --grep` / runner filter"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cypress run --spec \"path/to/file.cy.ts\"`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Choose a browser"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`forBrowser('chrome')` in code"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cypress run --browser chrome`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Run headed"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "default (headless via options)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cypress run --headed`"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Executing `cypress run` initiates a headless run (by default against the bundled Electron browser). Upon completion, a table details the tests per spec file, the failed/skipped/passed counts, and run times, with a summary of the whole run."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "npm"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Yarn"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "pnpm"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Bun"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "npx cypress run"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "yarn cypress run"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "pnpm cypress run"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "bunx cypress run"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "See "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/references/command-line.md",
            "children": [
              {
                "type": "text",
                "value": "Command Line"
              }
            ]
          },
          {
            "type": "text",
            "value": " for the full flag reference."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Passing environment variables and secrets"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium suites typically read credentials from `process.env` or a `.env` file. In Cypress, use "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/env.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.env()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " for sensitive values (credentials, tokens) and "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/cypress-api/expose.md",
            "children": [
              {
                "type": "text",
                "value": "`Cypress.expose()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " for non-sensitive config (feature flags, public URLs)."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "cypress.config.js"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "module.exports = defineConfig({\n  env: {\n    USER_NAME: process.env.USER_NAME,\n    PASSWORD: process.env.PASSWORD,\n  },\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "cypress.config.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "export default defineConfig({\n  env: {\n    USER_NAME: process.env.USER_NAME,\n    PASSWORD: process.env.PASSWORD,\n  },\n})"
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "login.cy.js"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "it('logs in', () => {\n  cy.env(['USER_NAME', 'PASSWORD']).then(({ USER_NAME, PASSWORD }) => {\n    cy.visit('/login')\n    cy.get('[data-testid=\"username\"]').type(USER_NAME)\n    cy.get('[data-testid=\"password\"]').type(PASSWORD, { log: false })\n  })\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "login.cy.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "it('logs in', () => {\n  cy.env(['USER_NAME', 'PASSWORD']).then(({ USER_NAME, PASSWORD }) => {\n    cy.visit('/login')\n    cy.get('[data-testid=\"username\"]').type(USER_NAME)\n    cy.get('[data-testid=\"password\"]').type(PASSWORD, { log: false })\n  })\n})"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Browser and driver management"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This is one of the largest simplifications in the migration. Selenium needs a browser-specific driver binary (ChromeDriver, GeckoDriver, EdgeDriver), resolved by Selenium Manager, WebDriverManager, or a manual download, and often paired with `Options`/`DesiredCapabilities`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "All of that goes away. Cypress uses the browsers installed on the machine and needs no driver binaries. To see which browsers Cypress detects:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "npm"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Yarn"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "pnpm"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Bun"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "npx cypress info"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "yarn cypress info"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "pnpm cypress info"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "bunx cypress info"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Delete any driver-download dependency (`webdrivermanager`, `selenium-manager` config, `chromedriver` npm package) and the code that configured it."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Browser launch options"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium `ChromeOptions`/`FirefoxOptions` (arguments, preferences, extensions) map to the "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/node-events/browser-launch-api.md",
            "children": [
              {
                "type": "text",
                "value": "`before:browser:launch`"
              }
            ]
          },
          {
            "type": "text",
            "value": " event configured in `setupNodeEvents`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const chrome = require('selenium-webdriver/chrome')\n\nconst options = new chrome.Options()\noptions.addArguments('--disable-gpu')\n\nconst driver = await new Builder()\n  .forBrowser('chrome')\n  .setChromeOptions(options)\n  .build()"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "cypress.config.js"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { defineConfig } = require('cypress')\n\nmodule.exports = defineConfig({\n  e2e: {\n    setupNodeEvents(on) {\n      on('before:browser:launch', (browser, launchOptions) => {\n        if (browser.family === 'chromium' && browser.name !== 'electron') {\n          launchOptions.args.push('--disable-gpu')\n        }\n        return launchOptions\n      })\n    },\n  },\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "cypress.config.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "export default defineConfig({\n  e2e: {\n    setupNodeEvents(on) {\n      on('before:browser:launch', (browser, launchOptions) => {\n        if (browser.family === 'chromium' && browser.name !== 'electron') {\n          launchOptions.args.push('--disable-gpu')\n        }\n        return launchOptions\n      })\n    },\n  },\n})"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Reproducible CI browser versions"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Because Cypress uses system browsers, Cypress publishes official Docker images with specific browser versions pre-installed, replacing the driver-vs-browser version-matching that Selenium CI requires."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "See "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/cypress-docker-images",
            "children": [
              {
                "type": "text",
                "value": "cypress-docker-images"
              }
            ]
          },
          {
            "type": "text",
            "value": " for all tags, and "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/references/launching-browsers.md",
            "children": [
              {
                "type": "text",
                "value": "Launching Browsers"
              }
            ]
          },
          {
            "type": "text",
            "value": " for local browser selection."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Starting your application under test"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium suites usually assume the application is already running (started by CI or a developer). Cypress makes the same assumption: it does not start your app, it visits the `baseUrl` you configured."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If you need to boot the app as part of the test command, use "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/bahmutov/start-server-and-test",
            "children": [
              {
                "type": "text",
                "value": "`start-server-and-test`"
              }
            ]
          },
          {
            "type": "text",
            "value": ", which starts your server, waits for the URL to respond, runs Cypress, then shuts the server down."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "package.json"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "{\n  \"scripts\": {\n    \"cy:run\": \"start-server-and-test start http://localhost:3000 'cypress run'\"\n  }\n}"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Test structure and runner migration"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium relies on an external test runner for structure. Cypress uses "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/core-concepts/writing-and-organizing-tests.md",
            "children": [
              {
                "type": "text",
                "value": "Mocha's"
              }
            ]
          },
          {
            "type": "text",
            "value": " BDD interface, which provides `describe()` and `it()` globally, so there is nothing to import."
          }
        ]
      },
      {
        "type": "table",
        "align": [
          null,
          null
        ],
        "children": [
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Selenium (JUnit 5 / TestNG / pytest)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Test class"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`describe('...', () => {})`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`@Test` method / `def test_...`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`it('...', () => {})`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`@BeforeEach` / `setup()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`beforeEach(() => {})`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`@AfterEach` / `teardown()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`afterEach(() => {})`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`@BeforeAll` / `setup_class`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`before(() => {})`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`@AfterAll` / `teardown_class`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`after(() => {})`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`@Disabled` / `@pytest.mark.skip`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`it.skip('...', () => {})`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Run one test in isolation"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`it.only('...', () => {})`"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "A Selenium test class maps naturally to a `describe` block, and each `@Test` method becomes an `it`. Where Selenium relies on `@BeforeEach` to create a fresh `driver`, Cypress starts each test with clean browser state automatically, so `beforeEach` is used for app-level setup (visiting a page, seeding data, logging in) rather than browser setup."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "general-information.cy.js"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "describe('General information', () => {\n  beforeEach(() => {\n    cy.visit('/dashboard')\n  })\n\n  it('shows the header', () => {\n    cy.get('[data-testid=\"header\"]').should('be.visible')\n  })\n\n  it('shows the footer', () => {\n    cy.get('[data-testid=\"footer\"]').should('be.visible')\n  })\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "general-information.cy.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "describe('General information', () => {\n  beforeEach(() => {\n    cy.visit('/dashboard')\n  })\n\n  it('shows the header', () => {\n    cy.get('[data-testid=\"header\"]').should('be.visible')\n  })\n\n  it('shows the footer', () => {\n    cy.get('[data-testid=\"footer\"]').should('be.visible')\n  })\n})"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Deleting the WebDriver lifecycle"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Every Selenium test creates and disposes of a `driver`. In Cypress this code is obsolete. Remove it entirely rather than translating it."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const driver = await new Builder().forBrowser('chrome').build()\n// ... test body, with driver.wait(...) for explicit waits ...\nawait driver.quit()"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// Nothing. Cypress creates and disposes of the browser for you.\n// Explicit waits become retry-ability (see below)."
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "`RemoteWebDriver` and Selenium Grid `Capabilities` plumbing (for running against a hub) is likewise removed. Cypress scales across machines through "
          },
          {
            "type": "link",
            "title": null,
            "url": "#Replacing-Selenium-Grid",
            "children": [
              {
                "type": "text",
                "value": "Cypress Cloud"
              }
            ]
          },
          {
            "type": "text",
            "value": ", not a Grid you operate."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Execution model, waits, and retry-ability"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium waits are the single biggest source of flakiness and boilerplate, and they are almost entirely unnecessary in Cypress."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Implicit waits (`setTimeouts({ implicit })`) → replaced by "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/references/configuration.md#Timeouts",
                    "children": [
                      {
                        "type": "text",
                        "value": "`defaultCommandTimeout`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": ", which applies to every command."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Explicit waits (`driver.wait()` + `until`) → replaced by automatic "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/core-concepts/retry-ability.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "retry-ability"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": ": `cy.get()` retries until the element exists, and `.should()` retries until the assertion passes."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.sleep()` → delete it. Do not translate a sleep into `cy.wait(<number>)`. Assert on the condition you were waiting for instead."
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "table",
        "align": [
          null,
          null
        ],
        "children": [
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Selenium"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.wait(until.elementIsVisible(el))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('be.visible')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.wait(until.elementIsEnabled(el))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).click()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.wait(until.elementLocated(by))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel)` (retries until present)"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.wait(until.elementTextContains(el, 'Saved'))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('contain', 'Saved')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.wait(until.urlContains('/home'))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.url().should('include', '/home')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.sleep(3000)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "remove; assert on the resulting state"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const button = driver.findElement(By.id('myButton'))\nawait driver.wait(until.elementIsEnabled(button), 10000)\nawait button.click()\n\nconst toast = driver.findElement(By.css('.toast'))\nawait driver.wait(until.elementIsVisible(toast), 10000)\nassert.strictEqual(await toast.getText(), 'Saved!')"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('#myButton').click()\ncy.get('[data-testid=\"toast\"]').should('have.text', 'Saved!')"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('#myButton').click()\ncy.get('[data-testid=\"toast\"]').should('have.text', 'Saved!')"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "When you genuinely need to wait for a specific network call, alias it with `cy.intercept()` and `cy.wait('@alias')`, a deterministic wait on the request rather than an arbitrary timeout. See "
          },
          {
            "type": "link",
            "title": null,
            "url": "#Network-spying-and-stubbing",
            "children": [
              {
                "type": "text",
                "value": "Network stubbing"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Choosing a selector strategy"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium locates elements with `By` strategies: `By.id`, `By.name`, `By.className`, `By.css`, `By.linkText`, and `By.xpath`. Decide how these map to Cypress before translating tests, because the choice affects nearly every line."
          }
        ]
      },
      {
        "type": "table",
        "align": [
          null,
          null
        ],
        "children": [
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Selenium `By`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`By.id('email')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get('#email')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`By.name('email')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get('[name=\"email\"]')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`By.className('btn')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get('.btn')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`By.css('...')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get('...')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`By.linkText('Sign in')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.contains('a', 'Sign in')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`By.partialLinkText('Sign')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.contains('a', 'Sign')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`By.css('button')` (by tag)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get('button')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`By.xpath(\"//button[text()='OK']\")`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.contains('button', 'OK')` (rewrite, see below)"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "XPath needs special attention. Cypress has no first-class XPath support. Most XPath locators fall into one of two buckets:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Text-based XPath (`//button[text()='Submit']`, `//a[contains(., 'Next')]`) → rewrite with "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/api/commands/contains.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "`cy.contains()`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": ", which is usually clearer."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Structural XPath (`//div[@class='card']//span`) → rewrite as a CSS selector (`.card span`), optionally using "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/api/commands/find.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "`.find()`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": ", "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/api/commands/within.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "`.within()`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": ", or "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/api/commands/parent.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "`.parent()`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": "/"
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/api/commands/children.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "`.children()`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " for traversal."
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Treat an XPath-heavy suite as an opportunity to move to more robust selectors."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "For the most resilient long-term strategy, follow Cypress "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/core-concepts/best-practices.md#Selecting-Elements",
            "children": [
              {
                "type": "text",
                "value": "Best Practices"
              }
            ]
          },
          {
            "type": "text",
            "value": " and add dedicated `data-cy` (or `data-testid`) attributes to your application, then select with `cy.get('[data-cy=\"submit\"]')`. If you want role/label ergonomics without editing markup, install "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/testing-library/cypress-testing-library",
            "children": [
              {
                "type": "text",
                "value": "`@testing-library/cypress`"
              }
            ]
          },
          {
            "type": "text",
            "value": " and use `cy.findByRole('button', { name: 'Submit' })`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The examples in this guide use `data-testid` for brevity."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Finding multiple elements"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "`driver.findElements(...)` returns a collection you iterate. `cy.get()` already yields all matching elements; use "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/each.md",
            "children": [
              {
                "type": "text",
                "value": "`.each()`"
              }
            ]
          },
          {
            "type": "text",
            "value": ", "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/eq.md",
            "children": [
              {
                "type": "text",
                "value": "`.eq()`"
              }
            ]
          },
          {
            "type": "text",
            "value": ", "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/first.md",
            "children": [
              {
                "type": "text",
                "value": "`.first()`"
              }
            ]
          },
          {
            "type": "text",
            "value": ", and "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/last.md",
            "children": [
              {
                "type": "text",
                "value": "`.last()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " to work with them."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const rows = await driver.findElements(By.css('table tr'))\nassert.strictEqual(rows.length, 5)"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('table tr').should('have.length', 5)"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('table tr').should('have.length', 5)"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Interactions"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Click, type, and clear"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium's `sendKeys` appends text; to replace a value you must `clear()` first. `.type()` behaves the same way, so clear before typing when a field may already contain text."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "await driver.findElement(By.id('username')).sendKeys('jane')\nawait driver.findElement(By.id('password')).sendKeys('secret')\nawait driver.findElement(By.css('button[type=submit]')).click()"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('#username').clear()\ncy.get('#username').type('jane')\ncy.get('#password').clear()\ncy.get('#password').type('secret')\ncy.get('button[type=submit]').click()"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('#username').clear()\ncy.get('#username').type('jane')\ncy.get('#password').clear()\ncy.get('#password').type('secret')\ncy.get('button[type=submit]').click()"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Dropdowns, checkboxes, and radios"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium wraps `<select>` elements in a `Select` helper. Cypress has a dedicated "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/select.md",
            "children": [
              {
                "type": "text",
                "value": "`.select()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " command, plus "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/check.md",
            "children": [
              {
                "type": "text",
                "value": "`.check()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " and "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/uncheck.md",
            "children": [
              {
                "type": "text",
                "value": "`.uncheck()`"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { Select } = require('selenium-webdriver/lib/select')\n\nawait new Select(driver.findElement(By.id('country'))).selectByVisibleText(\n  'United States'\n)\nawait driver.findElement(By.id('subscribe')).click() // checkbox"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('#country').select('United States')\ncy.get('#subscribe').check()"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('#country').select('United States')\ncy.get('#subscribe').check()"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Hover, right-click, double-click, and keyboard"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium performs these through the `Actions` builder. Cypress has direct commands for most, and uses "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/trigger.md",
            "children": [
              {
                "type": "text",
                "value": "`.trigger()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " for hover."
          }
        ]
      },
      {
        "type": "table",
        "align": [
          null,
          null
        ],
        "children": [
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Selenium `Actions`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.actions().move({ origin: el }).perform()` (hover)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).trigger('mouseover')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.actions().contextClick(el).perform()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).rightclick()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.actions().doubleClick(el).perform()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).dblclick()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`el.sendKeys(Key.ENTER)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).type('{enter}')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.actions().keyDown(Key.SHIFT).click(el)...`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).click({ shiftKey: true })`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.actions().sendKeys(Key.TAB).perform()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.press(Cypress.Keyboard.Keys.TAB)`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.actions().dragAndDrop(source, target).perform()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`.trigger('mousedown')` → `.trigger('mousemove')` → `.trigger('mouseup')`, or a drag-and-drop plugin"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "See "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/type.md",
            "children": [
              {
                "type": "text",
                "value": "`.type()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " for the full list of special-character sequences (`{enter}`, `{esc}`, `{selectall}`, etc.)."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Scrolling and viewport"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium often scrolls via `driver.executeScript()`. Cypress automatically scrolls elements into view before acting on them, and offers "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/scrollintoview.md",
            "children": [
              {
                "type": "text",
                "value": "`.scrollIntoView()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " and "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/scrollto.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.scrollTo()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " when you need explicit control. Resize the window with "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/viewport.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.viewport()`"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "await driver.executeScript(\n  'arguments[0].scrollIntoView(true);',\n  driver.findElement(By.id('footer'))\n)\nawait driver.manage().window().setRect({ width: 375, height: 812 })"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('#footer').scrollIntoView()\ncy.viewport(375, 812)"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('#footer').scrollIntoView()\ncy.viewport(375, 812)"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Assertions"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium has no assertions of its own. With the JavaScript bindings you use Node's built-in `assert` module (or a library like Chai). Cypress bundles "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/references/assertions.md",
            "children": [
              {
                "type": "text",
                "value": "Chai"
              }
            ]
          },
          {
            "type": "text",
            "value": ", exposed through the retrying "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/should.md",
            "children": [
              {
                "type": "text",
                "value": "`.should()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " command and the one-off `expect()`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Because `.should()` retries, you rarely need an explicit wait before an assertion; the wait and the assertion are the same call."
          }
        ]
      },
      {
        "type": "table",
        "align": [
          null,
          null
        ],
        "children": [
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Selenium (Node `assert`)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`assert(await el.isDisplayed())`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('be.visible')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`assert(!(await el.isDisplayed()))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('not.be.visible')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`assert.strictEqual(await el.getText(), 'Saved!')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('have.text', 'Saved!')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`assert((await el.getText()).includes('Saved'))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('contain', 'Saved')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`assert.strictEqual(await el.getAttribute('value'), 'v')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('have.value', 'v')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`assert.strictEqual(await el.getAttribute('href'), '/x')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('have.attr', 'href', '/x')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`assert(await el.isEnabled())`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('be.enabled')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`assert(!(await el.isEnabled()))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('be.disabled')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`assert(await el.isSelected())`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('be.checked')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`assert.strictEqual(els.length, 5)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('have.length', 5)`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`assert((await driver.getCurrentUrl()).includes('/x'))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.url().should('include', '/x')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`assert.strictEqual(await driver.getTitle(), 'Title')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.title().should('eq', 'Title')`"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const toast = driver.findElement(By.css('.toast'))\nassert(await toast.isDisplayed())\nassert.strictEqual(await toast.getText(), 'Saved!')"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('[data-testid=\"toast\"]').should('be.visible').and('have.text', 'Saved!')"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('[data-testid=\"toast\"]').should('be.visible').and('have.text', 'Saved!')"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Network spying and stubbing"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium has no built-in way to observe or stub network traffic, so teams reach for an external proxy (BrowserMob) or poll the UI until the backend catches up. Cypress has "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/intercept.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.intercept()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " built in, which removes an entire class of flaky, timing-based Selenium code."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Wait for a request deterministically"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Instead of an explicit wait hoping the response arrived, wait on the request itself."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "await driver.findElement(By.id('load-users')).click()\n// Hope the request finished within 10s\nawait driver.wait(until.elementLocated(By.css('.user-row')), 10000)"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.intercept('GET', '/api/users').as('users')\ncy.get('#load-users').click()\ncy.wait('@users').its('response.statusCode').should('eq', 200)\ncy.get('[data-testid=\"user-row\"]').should('have.length.greaterThan', 0)"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.intercept('GET', '/api/users').as('users')\ncy.get('#load-users').click()\ncy.wait('@users').its('response.statusCode').should('eq', 200)\ncy.get('[data-testid=\"user-row\"]').should('have.length.greaterThan', 0)"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Stub a response"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Return canned data without hitting the backend, which is impossible in plain Selenium."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.intercept('GET', '/api/projects', {\n  statusCode: 200,\n  body: [{ id: '1' }, { id: '2' }],\n}).as('projects')"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.intercept('GET', '/api/projects', {\n  statusCode: 200,\n  body: [{ id: '1' }, { id: '2' }],\n}).as('projects')"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "See "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/guides/network-requests.md",
            "children": [
              {
                "type": "text",
                "value": "Network Requests"
              }
            ]
          },
          {
            "type": "text",
            "value": " and "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/intercept.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.intercept()`"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Authentication"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium suites usually re-run the full login UI in a `beforeEach`, or manually persist cookies. In Cypress, wrap login in "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/session.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.session()`"
              }
            ]
          },
          {
            "type": "text",
            "value": ", which caches cookies, `localStorage`, and `sessionStorage` and restores them across tests, so you log in once instead of on every test."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "beforeEach(async function () {\n  await driver.get('http://localhost:3000/login')\n  await driver.findElement(By.id('username')).sendKeys('jane')\n  await driver.findElement(By.id('password')).sendKeys('secret')\n  await driver.findElement(By.css('button[type=submit]')).click()\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "cypress/support/e2e.js"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const login = () => {\n  cy.visit('/login')\n  cy.get('#username').type('jane')\n  cy.get('#password').type('secret')\n  cy.get('button[type=submit]').click()\n  cy.url().should('include', '/dashboard')\n}\n\nbeforeEach(() => {\n  cy.session('jane', login)\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "cypress/support/e2e.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const login = () => {\n  cy.visit('/login')\n  cy.get('#username').type('jane')\n  cy.get('#password').type('secret')\n  cy.get('button[type=submit]').click()\n  cy.url().should('include', '/dashboard')\n}\n\nbeforeEach(() => {\n  cy.session('jane', login)\n})"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Alerts, confirms, and prompts"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium switches into a native dialog with `driver.switchTo().alert()`. Cypress runs inside the browser and handles JavaScript dialogs through events. By default Cypress auto-accepts `alert()` and `confirm()`."
          }
        ]
      },
      {
        "type": "table",
        "align": [
          null,
          null
        ],
        "children": [
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Selenium"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.switchTo().alert().accept()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "auto-accepted; listen with `cy.on('window:alert', ...)`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.switchTo().alert().dismiss()` (confirm)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.on('window:confirm', () => false)`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.switchTo().alert().getText()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "assert on the message inside the event handler"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.switchTo().alert().sendKeys(text)` (prompt)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "stub `window.prompt` in `cy.visit`'s `onBeforeLoad`"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "await driver.findElement(By.id('delete')).click()\nconst alert = await driver.switchTo().alert()\nassert.strictEqual(await alert.getText(), 'Are you sure?')\nawait alert.accept()"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.on('window:confirm', (message) => {\n  expect(message).to.eq('Are you sure?')\n  // return nothing / true to accept, return false to dismiss\n})\ncy.get('#delete').click()"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.on('window:confirm', (message) => {\n  expect(message).to.eq('Are you sure?')\n  // return nothing / true to accept, return false to dismiss\n})\ncy.get('#delete').click()"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "For `prompt()`, stub the return value before the page loads:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.visit('/', {\n  onBeforeLoad(win) {\n    cy.stub(win, 'prompt').returns('Ada Lovelace')\n  },\n})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.visit('/', {\n  onBeforeLoad(win) {\n    cy.stub(win, 'prompt').returns('Ada Lovelace')\n  },\n})"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Frames and iframes"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium switches context with `driver.switchTo().frame(...)` and `switchTo().defaultContent()`. Cypress does not switch context; instead you get the iframe's body and scope commands to it with "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/within.md",
            "children": [
              {
                "type": "text",
                "value": "`.within()`"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "await driver.switchTo().frame(driver.findElement(By.id('payment-frame')))\nawait driver.findElement(By.id('card-number')).sendKeys('4242424242424242')\nawait driver.switchTo().defaultContent()"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('#payment-frame')\n  .its('0.contentDocument.body')\n  .should('not.be.empty')\n  .then(cy.wrap)\n  .within(() => {\n    cy.get('#card-number').type('4242424242424242')\n  })"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('#payment-frame')\n  .its('0.contentDocument.body')\n  .should('not.be.empty')\n  .then(cy.wrap)\n  .within(() => {\n    cy.get('#card-number').type('4242424242424242')\n  })"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The `.should('not.be.empty')` step makes Cypress wait for the frame document to load. See "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/faq.md#How-do-I-test-elements-inside-an-iframe",
            "children": [
              {
                "type": "text",
                "value": "How do I test elements inside an iframe?"
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Multiple tabs and windows"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium manages tabs with `driver.getAllWindowHandles()` and `driver.switchTo().window(handle)`. Cypress runs in a single browser tab by design. There are two common approaches:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Prefer testing the behavior, not the tab. If a link opens a new tab via `target=\"_blank\"`, assert it has the right `href` rather than following it, or "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/api/commands/request.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "`cy.request()`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " the URL directly."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "When you must drive a second tab, use the "
                  },
                  {
                    "type": "link",
                    "title": null,
                    "url": "https://www.npmjs.com/package/@cypress/puppeteer",
                    "children": [
                      {
                        "type": "text",
                        "value": "`@cypress/puppeteer`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " plugin, which gives Cypress access to the underlying browser via Puppeteer."
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const original = await driver.getWindowHandle()\nawait driver.findElement(By.linkText('Open report')).click()\nconst handles = await driver.getAllWindowHandles()\nfor (const handle of handles) {\n  if (handle !== original) await driver.switchTo().window(handle)\n}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress (assert the href instead)"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.contains('a', 'Open report')\n  .should('have.attr', 'target', '_blank')\n  .and('have.attr', 'href', '/report')"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.contains('a', 'Open report')\n  .should('have.attr', 'target', '_blank')\n  .and('have.attr', 'href', '/report')"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "File uploads and downloads"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Upload"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium uploads by sending the file path to the `<input type=\"file\">`. Cypress has a dedicated "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/selectfile.md",
            "children": [
              {
                "type": "text",
                "value": "`.selectFile()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " command that also supports multiple files and drag-and-drop."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "await driver\n  .findElement(By.css('input[type=file]'))\n  .sendKeys('/path/to/avatar.png')"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('input[type=file]').selectFile('cypress/fixtures/avatar.png')"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('input[type=file]').selectFile('cypress/fixtures/avatar.png')"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Download"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Trigger the download, then assert the file landed in the configured downloads folder with "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/readfile.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.readFile()`"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.contains('button', 'Export CSV').click()\ncy.readFile('cypress/downloads/export.csv')"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.contains('button', 'Export CSV').click()\ncy.readFile('cypress/downloads/export.csv')"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Screenshots"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium's `driver.takeScreenshot()` maps to "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/screenshot.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.screenshot()`"
              }
            ]
          },
          {
            "type": "text",
            "value": ", which can capture the full page or a single element. Cypress also captures a screenshot automatically on test failure during `cypress run`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const fs = require('fs')\n\nconst image = await driver.takeScreenshot()\nfs.writeFileSync('screenshot.png', image, 'base64')"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.screenshot('after-signup')\ncy.get('[data-testid=\"toast\"]').screenshot('toast')"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.screenshot('after-signup')\ncy.get('[data-testid=\"toast\"]').screenshot('toast')"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "See "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/guides/screenshots-and-videos.md",
            "children": [
              {
                "type": "text",
                "value": "Screenshots and Videos"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "API testing"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium suites often add a separate HTTP client (`axios`, `node-fetch`) for API setup or assertions. Cypress has "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/request.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.request()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " built in for making real HTTP calls (no `cy.intercept` stubbing involved)."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.request('/api/health').its('status').should('eq', 200)\n\n// Seed state via the API before driving the UI\ncy.request('POST', '/api/users', { name: 'Jane' }).its('body.id').as('userId')"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.request('/api/health').its('status').should('eq', 200)\n\n// Seed state via the API before driving the UI\ncy.request('POST', '/api/users', { name: 'Jane' }).its('body.id').as('userId')"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "See "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/request.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.request()`"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Reusable code patterns"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Page Object Model"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If your Selenium suite uses the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://www.selenium.dev/documentation/test_practices/encouraged/page_object_models/",
            "children": [
              {
                "type": "text",
                "value": "Page Object Model"
              }
            ]
          },
          {
            "type": "text",
            "value": ", the pattern ports directly. The class stays; only the body changes from WebDriver calls to Cypress commands. Because Cypress commands are globally available on `cy`, page objects no longer need a `driver` passed into their constructor."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Before: Selenium"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { By } = require('selenium-webdriver')\n\nclass LoginPage {\n  constructor(driver) {\n    this.driver = driver\n  }\n\n  async login(username, password) {\n    await this.driver.findElement(By.id('username')).sendKeys(username)\n    await this.driver.findElement(By.id('password')).sendKeys(password)\n    await this.driver.findElement(By.css('button[type=submit]')).click()\n  }\n}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After: Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "loginPage.js"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "export class LoginPage {\n  login(username, password) {\n    cy.get('[data-testid=\"username\"]').type(username)\n    cy.get('[data-testid=\"password\"]').type(password)\n    cy.contains('button', 'Login').click()\n  }\n}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "loginPage.ts"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "export class LoginPage {\n  login(username: string, password: string) {\n    cy.get('[data-testid=\"username\"]').type(username)\n    cy.get('[data-testid=\"password\"]').type(password)\n    cy.contains('button', 'Login').click()\n  }\n}"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "As you migrate, consider whether frequently repeated flows (like login) are better expressed as "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/cypress-api/custom-commands.md",
            "children": [
              {
                "type": "text",
                "value": "custom commands"
              }
            ]
          },
          {
            "type": "text",
            "value": " than page-object methods."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Data-driven tests"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium data-driven tests typically loop over an array to generate cases (or use a runner feature such as Mocha's dynamic tests). In Cypress the pattern is the same: iterate a plain array with `.forEach()` and generate one `it` per entry."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Cypress"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const people = [\n  { name: 'Maya', expected: 'Hello, Maya!' },\n  { name: 'Theo', expected: 'Hello, Theo!' },\n]\n\npeople.forEach(({ name, expected }) => {\n  it(`greets ${name}`, () => {\n    cy.visit(`/greet?name=${name}`)\n    cy.get('h1').should('have.text', expected)\n  })\n})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const people = [\n  { name: 'Maya', expected: 'Hello, Maya!' },\n  { name: 'Theo', expected: 'Hello, Theo!' },\n]\n\npeople.forEach(({ name, expected }) => {\n  it(`greets ${name}`, () => {\n    cy.visit(`/greet?name=${name}`)\n    cy.get('h1').should('have.text', expected)\n  })\n})"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Migrating a Cucumber suite"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If you drive Selenium through Cucumber (`.feature` files with step definitions), the "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/badeball/cypress-cucumber-preprocessor",
            "children": [
              {
                "type": "text",
                "value": "`@badeball/cypress-cucumber-preprocessor`"
              }
            ]
          },
          {
            "type": "text",
            "value": " community plugin lets you keep your Gherkin and reuse most scenarios. Your `.feature` files stay largely as-is; only the step definitions change, with the WebDriver calls in each step becoming Cypress commands."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "JavaScript"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "TypeScript"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const { When, Then } = require('@badeball/cypress-cucumber-preprocessor')\n\nWhen('I visit the homepage', () => {\n  cy.visit('/')\n})\n\nThen('I should see a search bar', () => {\n  cy.get('input[type=\"search\"]').should('be.visible')\n})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "import { When, Then } from '@badeball/cypress-cucumber-preprocessor'\n\nWhen('I visit the homepage', () => {\n  cy.visit('/')\n})\n\nThen('I should see a search bar', () => {\n  cy.get('input[type=\"search\"]').should('be.visible')\n})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The scenario logic is unchanged. The difference is the framework wiring and that the step bodies now use `cy` instead of a `driver`."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Replacing Selenium Grid"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium Grid distributes tests across machines by running a hub and nodes that you provision, configure, and maintain. Cypress replaces this with "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/cloud/get-started/introduction.md",
            "children": [
              {
                "type": "text",
                "value": "Cypress Cloud"
              }
            ]
          },
          {
            "type": "text",
            "value": " parallelization: your CI runs Cypress on several machines in parallel and Cypress Cloud coordinates how specs are split across them, so there is no hub to operate. Like Selenium Grid, this runs in CI, not on your local machine."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "npm"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Yarn"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "pnpm"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Bun"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "npx cypress run --record --parallel"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "yarn cypress run --record --parallel"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "pnpm cypress run --record --parallel"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "bunx cypress run --record --parallel"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Cypress Cloud assigns each spec file to an available machine using a "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/cloud/features/smart-orchestration/load-balancing.md#Balance-strategy",
            "children": [
              {
                "type": "text",
                "value": "balance strategy"
              }
            ]
          },
          {
            "type": "text",
            "value": " based on historical run durations, so run time is minimized automatically and you never configure shards by hand."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Smart Orchestration"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Recording to Cypress Cloud unlocks "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/cloud/features/smart-orchestration/overview.md",
            "children": [
              {
                "type": "text",
                "value": "Smart Orchestration"
              }
            ]
          },
          {
            "type": "text",
            "value": " beyond plain parallelization:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/cloud/features/smart-orchestration/load-balancing.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Load Balancing"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": ": distributes specs by previous run durations."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/cloud/features/smart-orchestration/spec-prioritization.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Spec Prioritization"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": ": runs previously failed specs first for faster feedback."
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/cloud/features/smart-orchestration/run-cancellation.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Auto Cancellation"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": ": stops a run after a threshold of failures."
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Debugging CI with Test Replay"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "A major pain point with Grid runs is reproducing a CI failure locally. "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/cloud/features/test-replay.md",
            "children": [
              {
                "type": "text",
                "value": "Test Replay"
              }
            ]
          },
          {
            "type": "text",
            "value": " records a full, interactive replay of every test run (DOM, network requests, and console logs exactly as they ran in CI) so you debug from the replay instead of re-running the suite. Test Replay is available on all Cypress Cloud plans at no additional cost."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "npm"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Yarn"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "pnpm"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Bun"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "npx cypress run --record --key <record_key>"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "yarn cypress run --record --key <record_key>"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "pnpm cypress run --record --key <record_key>"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "bunx cypress run --record --key <record_key>"
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Integration with your CI/CD pipeline"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Learn more about "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/continuous-integration/overview.md",
            "children": [
              {
                "type": "text",
                "value": "running Cypress tests in Continuous Integration"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Cheat sheet"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Selenium calls below use the JavaScript bindings, with `await` omitted for brevity. The Java, Python, C#, and Ruby bindings map the same way."
          }
        ]
      },
      {
        "type": "table",
        "align": [
          null,
          null
        ],
        "children": [
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Selenium"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`new Builder().forBrowser('chrome').build()` / `driver.quit()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "(removed; managed by Cypress)"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.get('/path')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.visit('/path')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.navigate().to(url)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.visit(url)`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.navigate().back()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.go('back')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.navigate().forward()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.go('forward')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.navigate().refresh()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.reload()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.getCurrentUrl()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.url()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.getTitle()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.title()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.findElement(By.id('x'))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get('#x')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.findElement(By.css('.x'))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get('.x')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.findElement(By.linkText('Next'))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.contains('a', 'Next')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.findElement(By.xpath(\"//b[text()='X']\"))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.contains('b', 'X')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.findElements(By.css('.x'))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get('.x')` (yields all)"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`el.click()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).click()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`el.sendKeys('text')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).type('text')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`el.clear()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).clear()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`el.getText()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).invoke('text')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`el.getAttribute('href')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).invoke('attr', 'href')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`el.isDisplayed()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('be.visible')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`el.isEnabled()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('be.enabled')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`el.isSelected()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('be.checked')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`new Select(el).selectByVisibleText('US')`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).select('US')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.actions().move({ origin: el })` (hover)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).trigger('mouseover')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.actions().contextClick(el)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).rightclick()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.actions().doubleClick(el)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).dblclick()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`el.sendKeys(Key.ENTER)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).type('{enter}')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.wait(until.elementIsVisible(el))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).should('be.visible')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.wait(until.elementIsEnabled(el))`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).click()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.sleep(ms)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "(remove; assert on the resulting state)"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`manage().setTimeouts({ implicit: ms })`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`defaultCommandTimeout` in config"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`el.sendKeys('/path/file.png')` (upload)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get(sel).selectFile('path/file.png')`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.switchTo().frame(el)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get('#f').its('0.contentDocument.body')...`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.switchTo().alert().accept()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "auto-accepted; `cy.on('window:alert', ...)`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.switchTo().alert().dismiss()` (confirm)"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.on('window:confirm', () => false)`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.switchTo().window(handle)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "https://www.npmjs.com/package/@cypress/puppeteer",
                    "children": [
                      {
                        "type": "text",
                        "value": "`@cypress/puppeteer`"
                      }
                    ]
                  },
                  {
                    "type": "text",
                    "value": " or assert the `href`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.manage().getCookies()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.getCookies()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.manage().addCookie(cookie)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.setCookie(name, value)`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.manage().deleteAllCookies()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.clearCookies()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.takeScreenshot()`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.screenshot()`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`driver.executeScript(js)`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.window().then(win => ...)` / `cy.invoke(...)`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`fetch(url)` / an HTTP client"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.request(url)`"
                  }
                ]
              }
            ]
          },
          {
            "type": "tableRow",
            "children": [
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "Selenium Grid / `RemoteWebDriver`"
                  }
                ]
              },
              {
                "type": "tableCell",
                "children": [
                  {
                    "type": "text",
                    "value": "`cypress run --record --parallel` (Cypress Cloud)"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Conclusion"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Migrating from Selenium to Cypress is less about translating syntax and more about removing machinery: the WebDriver lifecycle, explicit and implicit waits, and Grid infrastructure all give way to Cypress's in-browser execution and built-in retry-ability. The main planning work is choosing your target language (JavaScript or TypeScript), deciding a selector strategy to replace `By` and XPath locators, and reimplementing any shared framework code in JS/TS."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Approach it incrementally: run Cypress and Selenium side by side, migrate one class or spec at a time, and lean on "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/cypress-io/eslint-plugin-cypress",
            "children": [
              {
                "type": "text",
                "value": "`eslint-plugin-cypress`"
              }
            ]
          },
          {
            "type": "text",
            "value": " to keep the new tests idiomatic."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "See also"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/get-started/why-cypress.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Why Cypress?"
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/core-concepts/retry-ability.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Retry-ability"
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/core-concepts/best-practices.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Best Practices"
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/core-concepts/writing-and-organizing-tests.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Writing and Organizing Tests"
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/guides/network-requests.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Network Requests"
                      }
                    ]
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "link",
                    "title": null,
                    "url": "/llm/markdown/app/references/command-line.md",
                    "children": [
                      {
                        "type": "text",
                        "value": "Command Line"
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  "token_estimate": 6788
}