{
  "doc": {
    "id": "app/core-concepts/variables-and-aliases",
    "title": "Variables and Aliases",
    "description": "Learn how to handle asynchronous code in Cypress, when to assign variables, how to use aliases to share objects between hooks and tests, and how to alias DOM elements, intercepts, and requests.",
    "section": "app",
    "source_path": "/llm/markdown/app/core-concepts/variables-and-aliases.md",
    "version": "fa8f60eba6ec9a949b75fe9f9f5f6591719cd01f",
    "updated_at": "2026-05-05T21:21:10.048Z",
    "headings": [
      {
        "id": "app/core-concepts/variables-and-aliases#variables-and-aliases",
        "text": "Variables and Aliases",
        "level": 1
      },
      {
        "id": "app/core-concepts/variables-and-aliases#what-youll-learn",
        "text": "What you'll learn",
        "level": 5
      },
      {
        "id": "app/core-concepts/variables-and-aliases#closures",
        "text": "Closures",
        "level": 3
      },
      {
        "id": "app/core-concepts/variables-and-aliases#debugging",
        "text": "Debugging",
        "level": 3
      },
      {
        "id": "app/core-concepts/variables-and-aliases#variables",
        "text": "Variables",
        "level": 3
      },
      {
        "id": "app/core-concepts/variables-and-aliases#aliases",
        "text": "Aliases",
        "level": 2
      },
      {
        "id": "app/core-concepts/variables-and-aliases#sharing-context",
        "text": "Sharing Context",
        "level": 3
      },
      {
        "id": "app/core-concepts/variables-and-aliases#accessing-fixtures",
        "text": "Accessing Fixtures:",
        "level": 4
      },
      {
        "id": "app/core-concepts/variables-and-aliases#avoiding-the-use-of-this",
        "text": "Avoiding the use of this",
        "level": 4
      },
      {
        "id": "app/core-concepts/variables-and-aliases#elements",
        "text": "Elements",
        "level": 3
      },
      {
        "id": "app/core-concepts/variables-and-aliases#stale-elements",
        "text": "Stale Elements:",
        "level": 4
      },
      {
        "id": "app/core-concepts/variables-and-aliases#intercepts",
        "text": "Intercepts",
        "level": 3
      },
      {
        "id": "app/core-concepts/variables-and-aliases#requests",
        "text": "Requests",
        "level": 3
      },
      {
        "id": "app/core-concepts/variables-and-aliases#aliases-are-reset-before-each-test",
        "text": "Aliases are reset before each test",
        "level": 3
      }
    ]
  },
  "content": {
    "type": "root",
    "children": [
      {
        "type": "heading",
        "depth": 1,
        "children": [
          {
            "type": "text",
            "value": "Variables and Aliases"
          }
        ]
      },
      {
        "type": "heading",
        "depth": 5,
        "children": [
          {
            "type": "text",
            "value": "What you'll learn"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Common patterns for handling asynchronous code in Cypress"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "When to assign variables and when not to"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to use aliases to share objects between hooks and tests"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "Pitfalls with using `this` and how to avoid them"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "How to alias DOM elements, intercepts, and requests"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "New users to Cypress may initially find it challenging to work with the asynchronous nature of our APIs. There are many ways to reference, compare and utilize the objects that Cypress commands yield you. Once you get the hang of async code you'll realize you can do everything you could do synchronously, without your code doing any backflips."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This guide explores many common patterns for writing good Cypress code that can handle even the most complex situations."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Asynchronous APIs are here to stay in JavaScript. They are found everywhere in modern code. In fact, most new browser APIs are asynchronous and many core Node modules are asynchronous as well."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The patterns we'll explore below are useful in and outside of Cypress. The first and most important concept you should recognize is..."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "You cannot assign or work with the return values of any Cypress command. Commands are enqueued and run asynchronously."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// this won't work the way you think it doesconst button = cy.get('button')const form = cy.get('form')button.click()"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Closures"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "To access what each Cypress command yields you use "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/then.md",
            "children": [
              {
                "type": "text",
                "value": "`.then()`"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('button').then(($btn) => {  // $btn is the object that the previous  // command yielded us})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "If you're familiar with "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises",
            "children": [
              {
                "type": "text",
                "value": "native Promises"
              }
            ]
          },
          {
            "type": "text",
            "value": " the Cypress `.then()` works similarly. You can continue to nest more Cypress commands inside of the `.then()`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Each nested command has access to the work done in previous commands. This ends up reading very nicely."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('button').then(($btn) => {  // store the button's text  const txt = $btn.text()  // submit a form  cy.get('form').submit()  // compare the two buttons' text  // and make sure they are different  cy.get('button').should(($btn2) => {    expect($btn2.text()).not.to.eq(txt)  })})// these commands run after all of the// other previous commands have finishedcy.get(...).find(...).should(...)"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The commands outside of the `.then()` will not run until all of the nested commands finish."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "By using callback functions we've created a "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures",
            "children": [
              {
                "type": "text",
                "value": "closure"
              }
            ]
          },
          {
            "type": "text",
            "value": ". Closures enable us to keep references around to refer to work done in previous commands."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Debugging"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Using `.then()` functions is an excellent opportunity to use "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger",
            "children": [
              {
                "type": "text",
                "value": "`debugger`"
              }
            ]
          },
          {
            "type": "text",
            "value": ". This can help you understand the order in which commands are run. This also enables you to inspect the objects that Cypress yields you in each command."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('button').then(($btn) => {  // inspect $btn <object>  debugger  cy.get('[data-testid=\"countries\"]')    .select('USA')    .then(($select) => {      // inspect $select <object>      debugger      cy.clock().then(($clock) => {        // inspect $clock <object>        debugger        $btn // is still available        $select // is still available too      })    })})"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Variables"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Typically in Cypress you hardly need to ever use `const`, `let`, or `var`. When using closures you'll always have access to the objects that were yielded to you without assigning them."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The one exception to this rule is when you are dealing with mutable objects (that change state). When things change state you often want to compare an object's previous value to the next value."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Here's a great use case for a `const`."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "<button>increment</button>you clicked button <span data-testid=\"num\">0</span> times"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// app codelet count = 0$('button').on('click', () => {  $('[data-testid=\"num\"]').text((count += 1))})"
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// cypress test codecy.get('[data-testid=\"num\"]').then(($span) => {  // capture what num is right now  const num1 = parseFloat($span.text())  cy.get('button')    .click()    .then(() => {      // now capture it again      const num2 = parseFloat($span.text())      // make sure it's what we expected      expect(num2).to.eq(num1 + 1)    })})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The reason for using `const` is because the `$span` object is mutable. Whenever you have mutable objects and you're trying to compare them, you'll need to store their values. Using `const` is a perfect way to do that."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 2,
        "children": [
          {
            "type": "text",
            "value": "Aliases"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Using `.then()` callback functions to access the previous command values is great—but what happens when you're running code in hooks like `before` or `beforeEach`?"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "beforeEach(() => {  cy.get('button').then(($btn) => {    const text = $btn.text()  })})it('does not have access to text', () => {  // how do we get access to text ?!?!})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "How will we get access to `text`?"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "We could make our code do some ugly backflips using `let` to get access to it."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Do not do this"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This code below is just for demonstration."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "describe('a suite', () => {  // this creates a closure around  // 'text' so we can access it  let text  beforeEach(() => {    cy.get('button').then(($btn) => {      // redefine text reference      text = $btn.text()    })  })  it('does have access to text', () => {    // now text is available to us    // but this is not a great solution :(    text  })})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Fortunately, you don't have to make your code do backflips. With Cypress, we can better handle these situations."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Introducing Aliases"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Aliases are a powerful construct in Cypress that have many uses. We'll explore each of their capabilities below."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "At first, we'll use them to share objects between your hooks and your tests."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Sharing Context"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Sharing context is the simplest way to use aliases."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "To alias something you'd like to share use the "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/as.md",
            "children": [
              {
                "type": "text",
                "value": "`.as()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " command."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Let's look at our previous example with aliases."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "beforeEach(() => {  // alias the $btn.text() as 'text'  cy.get('button').invoke('text').as('text')})it('has access to text', function () {  this.text // is now available})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Under the hood, aliasing basic objects and primitives utilizes Mocha's shared "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://github.com/mochajs/mocha/wiki/Shared-Behaviours",
            "children": [
              {
                "type": "text",
                "value": "`context`"
              }
            ]
          },
          {
            "type": "text",
            "value": " object: that is, aliases are available as `this.*`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Mocha automatically shares contexts for us across all applicable hooks for each test. Additionally these aliases and properties are automatically cleaned up after each test."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "describe('parent', () => {  beforeEach(() => {    cy.wrap('one').as('a')  })  context('child', () => {    beforeEach(() => {      cy.wrap('two').as('b')    })    describe('grandchild', () => {      beforeEach(() => {        cy.wrap('three').as('c')      })      it('can access all aliases as properties', function () {        expect(this.a).to.eq('one') // true        expect(this.b).to.eq('two') // true        expect(this.c).to.eq('three') // true      })    })  })})"
      },
      {
        "type": "heading",
        "depth": 4,
        "children": [
          {
            "type": "text",
            "value": "Accessing Fixtures:"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The most common use case for sharing context is when dealing with "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/fixture.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.fixture()`"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Often times you may load a fixture in a `beforeEach` hook but want to utilize the values in your tests."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "beforeEach(() => {  // alias the users fixtures  cy.fixture('users.json').as('users')})it('utilize users in some way', function () {  // access the users property  const user = this.users[0]  // make sure the header contains the first  // user's name  cy.get('header').should('contain', user.name)})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Watch out for async commands"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Do not forget that Cypress commands are async!"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "You cannot use a `this.*` reference until the `.as()` command runs."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "it('is not using aliases correctly', function () {  cy.fixture('users.json').as('users')  // nope this won't work  //  // this.users is not defined  // because the 'as' command has only  // been enqueued - it has not run yet  const user = this.users[0]})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The same principles we introduced before apply to this situation. If you want to access what a command yields you have to do it in a closure using a "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/then.md",
            "children": [
              {
                "type": "text",
                "value": "`.then()`"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// yup all goodcy.fixture('users.json').then((users) => {  // now we can avoid the alias altogether  // and use a callback function  const user = users[0]  // passes  cy.get('header').should('contain', user.name)})"
      },
      {
        "type": "heading",
        "depth": 4,
        "children": [
          {
            "type": "text",
            "value": "Avoiding the use of `this`"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Arrow Functions"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Accessing aliases as properties with `this.*` will not work if you use "
          },
          {
            "type": "link",
            "title": null,
            "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions",
            "children": [
              {
                "type": "text",
                "value": "arrow functions"
              }
            ]
          },
          {
            "type": "text",
            "value": " for your tests or hooks."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "This is why all of our examples use the regular `function () {}` syntax as opposed to the lambda \"fat arrow\" syntax `() => {}`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Instead of using the `this.*` syntax, there is another way to access aliases."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/get.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.get()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " command is capable of accessing aliases with a special syntax using the `@` character:"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "beforeEach(() => {  // alias the users fixtures  cy.fixture('users.json').as('users')})it('utilize users in some way', function () {  // use the special '@' syntax to access aliases  // which avoids the use of 'this'  cy.get('@users').then((users) => {    // access the users argument    const user = users[0]    // make sure the header contains the first    // user's name    cy.get('header').should('contain', user.name)  })})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "By using "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/get.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.get()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " we avoid the use of `this`."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Keep in mind that there are use cases for both approaches because they have one major difference."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "When using `this.users`, it is stored on the context when it is first evaluated. But when using `cy.get('@users')`, any queries are re-evaluated every time the alias is accessed."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "const favorites = { color: 'blue' }cy.wrap(favorites).its('color').as('favoriteColor')cy.then(function () {  favorites.color = 'red'})cy.get('@favoriteColor').then(function (aliasValue) {  expect(aliasValue).to.eql('red')  expect(this.favoriteColor).to.eql('blue')})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "In the second `.then()` block, `cy.get('@favoriteColor')` runs `cy.wrap(favorites).its('color')` fresh each time, but `this.favoriteColor` was set when the alias was first stored, back when our favorite color was blue."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Elements"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Aliases have other special characteristics when being used with DOM elements."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "After you alias DOM elements, you can then later access them for reuse."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// alias all of the tr's found in the table as 'rows'cy.get('table').find('tr').as('rows')"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Internally, Cypress has made a reference to the `<tr>` collection returned as the alias \"rows\". To reference these same \"rows\" later, you can use the "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/get.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.get()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " command."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// Cypress returns the reference to the <tr>'s// which allows us to continue to chain commands// finding the 1st row.cy.get('@rows').first().click()"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Because we've used the `@` character in "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/get.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.get()`"
              }
            ]
          },
          {
            "type": "text",
            "value": ", instead of querying the DOM for elements, "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/get.md",
            "children": [
              {
                "type": "text",
                "value": "`cy.get()`"
              }
            ]
          },
          {
            "type": "text",
            "value": " looks for an existing alias called `rows` and returns the reference (if it finds it)."
          }
        ]
      },
      {
        "type": "heading",
        "depth": 4,
        "children": [
          {
            "type": "text",
            "value": "Stale Elements:"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "In many single-page applications, the JavaScript re-renders parts of the DOM constantly. This is why we always re-run queries when you fetch an alias, so you never end up with stale elements."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "<ul id=\"todos\">  <li>    Walk the dog    <button class=\"edit\">edit</button>  </li>  <li>    Feed the cat    <button class=\"edit\">edit</button>  </li></ul>"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Let's imagine when we click the `.edit` button that our `<li>` is re-rendered in the DOM. Instead of displaying the edit button it instead displays an `<input />` text field allowing you to edit the todo. The previous `<li>` has been completely removed from the DOM and a new `<li>` is rendered in its place."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.get('[data-testid=\"todos\"] li').first().as('firstTodo')cy.get('@firstTodo').find('.edit').click()cy.get('@firstTodo')  .should('have.class', 'editing')  .find('input')  .type('Clean the kitchen')"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Every time we reference `@firstTodo`, Cypress re-runs the queries leading up to the alias definition."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "In our case it would re-query the DOM using: `cy.get('#todos li').first()`. Everything works because the new `<li>` is found."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Usually, replaying previous commands will return what you expect, but not always. It is recommended that you alias elements before running commands."
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get('nav').find('header').find('[data-testid=\"user\"]').as('user').click()` (good)"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "`cy.get('nav').find('header').find('[data-testid=\"user\"]').click().as('user')` (bad)"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Intercepts"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Aliases can also be used with "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/intercept.md",
            "children": [
              {
                "type": "text",
                "value": "cy.intercept()"
              }
            ]
          },
          {
            "type": "text",
            "value": ". Aliasing your intercepted routes enables you to:"
          }
        ]
      },
      {
        "type": "list",
        "ordered": false,
        "start": null,
        "spread": false,
        "children": [
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "ensure your application makes the intended requests"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "wait for your server to send the response"
                  }
                ]
              }
            ]
          },
          {
            "type": "listItem",
            "spread": false,
            "checked": null,
            "children": [
              {
                "type": "paragraph",
                "children": [
                  {
                    "type": "text",
                    "value": "access the actual request object for assertions"
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Here's an example of aliasing an intercepted route and waiting on it to complete."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.intercept('POST', '/users', { id: 123 }).as('postUser')cy.get('form').submit()cy.wait('@postUser').then(({ request }) => {  expect(request.body).to.have.property('name', 'Brian')})cy.contains('Successfully created user: Brian')"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "New to Cypress?"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/app/guides/network-requests.md",
            "children": [
              {
                "type": "text",
                "value": "We have a much more detailed and comprehensive guide on routing Network Requests."
              }
            ]
          }
        ]
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Requests"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Aliases can also be used with "
          },
          {
            "type": "link",
            "title": null,
            "url": "/llm/markdown/api/commands/request.md",
            "children": [
              {
                "type": "text",
                "value": "requests"
              }
            ]
          },
          {
            "type": "text",
            "value": "."
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Here's an example of aliasing a request and accessing its properties later."
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "cy.request('https://jsonplaceholder.cypress.io/comments').as('comments')// other test code herecy.get('@comments').should((response) => {  if (response.status === 200) {      expect(response).to.have.property('duration')    } else {      // whatever you want to check here    }  })})"
      },
      {
        "type": "heading",
        "depth": 3,
        "children": [
          {
            "type": "text",
            "value": "Aliases are reset before each test"
          }
        ]
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "Note: all aliases are reset before each test. A common user mistake is to create aliases using the `before` hook. Such aliases work in the first test only!"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// 🚨 THIS EXAMPLE DOES NOT WORKbefore(() => {  // notice this alias is created just once using \"before\" hook  cy.wrap('some value').as('exampleValue')})it('works in the first test', () => {  cy.get('@exampleValue').should('equal', 'some value')})// NOTE the second test is failing because the alias is resetit('does not exist in the second test', () => {  // there is not alias because it is created once before  // the first test, and is reset before the second test  cy.get('@exampleValue').should('equal', 'some value')})"
      },
      {
        "type": "paragraph",
        "children": [
          {
            "type": "text",
            "value": "The solution is to create the aliases before each test using the `beforeEach` hook"
          }
        ]
      },
      {
        "type": "code",
        "lang": null,
        "meta": null,
        "value": "// ✅ THE CORRECT EXAMPLEbeforeEach(() => {  // we will create a new alias before each test  cy.wrap('some value').as('exampleValue')})it('works in the first test', () => {  cy.get('@exampleValue').should('equal', 'some value')})it('works in the second test', () => {  cy.get('@exampleValue').should('equal', 'some value')})"
      }
    ]
  },
  "token_estimate": 2725
}