Explain It Like I'm 5: Cypress Fixtures

Doing research on Cypress Fixtures makes me feel like this:

Files Filing Cabinet GIF

Google “Cypress Fixtures,” and there are so many tutorials and videos on the topic. It’s hard to know where to begin.

Having zero knowledge of Fixtures, what’s helpful for me is dialing down to the very basics of fixtures, what they are for, how they are created, and how to use them in tests.

Here’s my first installment of Explain It Like I’m 5: Cypress Fixtures edition.

Assumptions I’m making:

You…

  • already have some working knowledge of Cypress

  • know little to zero when it comes to fixtures (no worries, me too 🙋🏻)

  • have a decent understanding between Typescript and JavaScript. I’m working with Typescript, so if your project does not use TS, expect the syntax to look slightly different than mine.

So, what are fixtures for?

According to the docs, Cypress Fixtures “Load a fixed set of data located in a file.” Okay. That’s what they do, but I need to understand what they are for. Here’s what helped me.

TL;DR: Fixtures are sets of reusable test data that can be created and used in any environment that returns reliable test results when the tests are run.

Think about it this way. Our tests need stability. Flaky test results cause mistrust within the team. What causes flakiness? Lots of things, but not having reliable test data is one of them. We need the same test data that the tests can run against over and over and reliably report correct results (pass or fail). Fixtures are static data that can be transferred to any environment. Remember, we aren’t testing the data - we’re testing functionality. So, as long as the data is the same, we can use our tests in any environment and get reliable results that maintain trust in the tests and each other.

Nice! So, how do I create a fixture?

This is where I found a decent majority of the internet tutorials lacking. They would start with tests that just worked with pre-existing feature files. It all worked, everything worked, yay 🎉 Except, when following the tutorials, the steps weren’t working for me, and I didn’t know how to troubleshoot. This is where learning how to create a fixture helped me the most.

Chip Cullen’s explanation on “How to Create and Use Fixtures in Cypress Tests” brought it home for me. While I won’t go through each step outlined there, here are updated steps that can be used at the time of this writing:

  1. After identifying which XHR request you need to use for your tests, follow Step 1 outlined in his article:

  1. Create a test that will write the XHR response to your fixtures folder. For this example, we’ll use a login request:

    // cypress/e2e/fixtureSpec.cy.ts
    it("writes the fixtures file and stores the response in the fixtures folder", () => {
      cy.request("POST", "/auth/login", {
        email: "[email protected]",
        password: "PasswordExample"
      }).then((response) => {
        cy.writeFile("cypress/fixtures/login.json", response.body)
      })
    })
  2. Run Cypress

  3. 💥 You now have a login.json fixture file in your fixtures folder! This is the file we’ll use to stub the login response. Continuing on to…

  4. Use cy.intercept() to stub and use the response:

cy.intercept("POST", "auth/login"), "fixtures:login.json");

For example, I needed to use this stubbed response to simulate logins and access different parts of the application. Here’s what it looks like in a command.

// cypress/support/commands.ts

Cypress.Commands.add("loginStub", (email, password) => {  cy.intercept("POST", "auth/login"), "fixtures:login.json");  cy.login(email, password)});

Now, when I need to log in, but don’t want to repeat the login action, I pass cy.loginStub(email, password) in a beforeEach!

Okay, that’s cool. How do I access the values in my fixtures file?

Let’s say you have a fixture file that contains your users:

// cypress/fixtures/users.json
{
  "users": {
    "email": "[email protected]",
    "password": "PasswordExample"
  }
}

Back in our spec file, you can do the bare minimum, just to make sure it’s working and you understand the concepts:

// cypress/e2e/spec.cy.ts
import { users } from "cypress/supposrt/fixtures/users.json"

describe("fixture test", () => {
it("loads the user from the fixture file", () => {
  cy.get("[aria-label='example text field']").type(users.name)
  })
})

Run the test and 😱 it works!

I put this question to the Cypress community. “Can someone explain to me why I need to use cy.fixture over an import that doesn’t require it at all? And, would something like the above be appropriate for using?”

Here’s one user’s response:

Loading a fixture file with an import at the beginning of your spec file, as your example, is simply one of the ways to do it.

Using cy.fixture() within your test methods is another way of loading a fixture file, but be aware that in that case you will need to run cy.fixture() within an .it() or a hook like beforeEach().

With the import, you are storing the content of the file in a global variable as a regular javascript object. With the cy.fixture() you usually store what you  load in a Cypress alias.

How you reference/access that content is what is different (simple js variable VS alias). Note that a Cypress alias is a chainable.

They then recommended Gleb Bahmutov’s excellent post: “Import Cypress Fixtures

My favorite part, though, was this:

“simply one of the ways to do it.”

Often, we get tied up in thinking there is only one way to accomplish something. Sometimes, if we take a step back and approach the problem from a different angle, we will see what we need to see and make decisions from that vantage point.

Now, go forth and import those fixtures!

Till next time…

Bruce Almighty I Got The Power GIF by Jim Carrey

All my posts are free to read and clicking subscribe will bring each post to your inbox. If my work brings you joy, and you’d like to support it, you can become a paid subscriber by clicking the button above. If a paid subscription is not your thing, you can support my caffeine addiction writing by clicking the button below! Thanks!

Sources discussed in this article:

Reply

or to participate.