惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News - Newest:
Hacker News - Newest: "LLM"
Webroot Blog
Webroot Blog
S
Security @ Cisco Blogs
H
Heimdal Security Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
www.infosecurity-magazine.com
www.infosecurity-magazine.com
N
News and Events Feed by Topic
H
Hacker News: Front Page
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
SecWiki News
SecWiki News
N
News | PayPal Newsroom
T
Tor Project blog
W
WeLiveSecurity
A
Arctic Wolf
Security Archives - TechRepublic
Security Archives - TechRepublic
S
Secure Thoughts
月光博客
月光博客
AWS News Blog
AWS News Blog
D
Docker
C
CERT Recently Published Vulnerability Notes
MyScale Blog
MyScale Blog
Google Online Security Blog
Google Online Security Blog
大猫的无限游戏
大猫的无限游戏
T
The Blog of Author Tim Ferriss
I
InfoQ
人人都是产品经理
人人都是产品经理
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
Hacker News: Ask HN
Hacker News: Ask HN
Blog — PlanetScale
Blog — PlanetScale
博客园 - 【当耐特】
Engineering at Meta
Engineering at Meta
Stack Overflow Blog
Stack Overflow Blog
Recorded Future
Recorded Future
罗磊的独立博客
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
The Exploit Database - CXSecurity.com
D
DataBreaches.Net
S
Security Affairs
WordPress大学
WordPress大学
T
Threatpost
Microsoft Security Blog
Microsoft Security Blog
V
Vulnerabilities – Threatpost
The Hacker News
The Hacker News
S
SegmentFault 最新的问题
B
Blog RSS Feed
Project Zero
Project Zero
P
Proofpoint News Feed

Chip Cullen

The need for importance, and AI: Chip Cullen An updated Colorosetta: Chip Cullen The Return of the Font Combinator!: Chip Cullen Changing the number of an item in an ordered list: Chip Cullen My pizza dough recipe as of May 2025: Chip Cullen Gonna try to be a bit more personal: Chip Cullen How I built dynamic social media images in Eleventy using Cloudinary: Chip Cullen My current approach to AI : Chip Cullen Lessons Learned Surviving a Major Product Launch: Chip Cullen How to Build a Drop Down Menu with Modern CSS: Chip Cullen How to stop page scrolling when you have an open dialog element: Chip Cullen Distraction Driven Development: Chip Cullen How I learned to code: the art of letting go: Chip Cullen In praise of the switch statement: Chip Cullen Project stuck? Think about how you’re breaking it down & question everything: Chip Cullen So how did the onboarding experiment go?: Chip Cullen Ideas for an Onboarding Checklist: Chip Cullen I really like Post Mortems: Chip Cullen Raise Red Flags Early: Chip Cullen How to mock fetch requests in React Testing Librarty tests: Chip Cullen Running a Structured Meeting: Chip Cullen Adding the View Transitions API to my personal site: Chip Cullen A Lightweight Way to Read GraphQL Data: Chip Cullen How to make a color changing favicon: Chip Cullen Using a Pros/Cons list to help navigate technical discussions: Chip Cullen How to use variable fonts from Google Fonts: Chip Cullen A new website: now on Eleventy!: Chip Cullen How to Truncate Type at More Than One Line with Just CSS: Chip Cullen Colorosetta: the VS Code Extension!: Chip Cullen Using CSS Custom Properties and Logical Properties Together: Chip Cullen Browser Dev Tools: Element Inspector Popover: Chip Cullen The Link with rel=preload is a Seperate Thing: Chip Cullen How to have Dark & Light Mode Images that also works with User Choice: Chip Cullen Don’t use Viewport Units for Font Size on their own: Chip Cullen A little known Media Query: Aspect Ratio: Chip Cullen Meta thinking: Managing Decisions: Chip Cullen Give Your To-Do's Context: Chip Cullen Say What the Impact is when Reporting Issues: Chip Cullen Firefighting 101: How to Manage Breakages: Chip Cullen How to Deal With Large Pieces of Technical Debt: Chip Cullen Make Your Request Clear: Chip Cullen Analytics events, HTML classes, and protecting against refactoring: Chip Cullen How We Removed jQuery from a large app: Chip Cullen New tool: ColoRosetta: Chip Cullen What width and height attributes should you use with responsive images?: Chip Cullen Django 3.1 gotcha: Referrer Policy has a new default, and it might break iframes and links: Chip Cullen A Javascript Component Pattern: Chip Cullen CSS min(), max() and clamp() Functions: Chip Cullen Pointer Events and Inline Elements in Chrome: Chip Cullen Resolving a github repo and a new Create React App: Chip Cullen How to POST *Data* with the Fetch API: Chip Cullen The Contrast Triangle: Chip Cullen Advice on interviewing for Junior Developers: Chip Cullen Life Lessons Learned From Running a Marathon: How to do something really hard: Chip Cullen A (Brief) intro to Search Engine Structured Data: Chip Cullen Javascript Fallback Values on Variables and Booleans - a hard lesson: Chip Cullen Alfred Tip: Quickly Access Common URLs: Chip Cullen Responsive Images in Hugo - by Laura Kalbag: Chip Cullen Making a Gatsby Site with Multiple Content Types: Chip Cullen Fixing the 'Bad Interpreter' Error from AWS and Python 3.7: Chip Cullen Creating a Canonical Tag in a Django Template: Chip Cullen Responsive spacing with viewport and ch units: Chip Cullen Welcome to my New Design - 2019: Chip Cullen Django Templates: Block and If statements don’t work like you might expect: Chip Cullen Books I Read in 2018: Chip Cullen Lifehack: 4 ways to help tame common email noise: Chip Cullen How to make better Pull Requests: Adding Steps to Test: Chip Cullen The unsung develpment tool: Spreadsheets: Chip Cullen Troubleshooting Adding and Removing EventListeners: with Arguments, Debounced, and in a React Class: Chip Cullen How to Fake the Window Object in Jest and Enzyme: Chip Cullen Migrating From Wordpress to Hugo: Chip Cullen Background Repeat and its Possibilities: Chip Cullen Getting Started With Front End Tests: a Mindset: Chip Cullen Migrating a Blog - An Opportunity for a Content Inventory: Chip Cullen Moving to Hugo: Chip Cullen JavaScript events: .target vs .currentTarget: Chip Cullen Things I wish I knew when starting with Python: Chip Cullen Leading Ampersands for modifiers in Sass: An anti-pattern: Chip Cullen How to get rid of the "You have mail" message in your terminal: Chip Cullen Why three typefaces rule the web, and what you can do about it: Chip Cullen You shouldn't worry about Section 508 - it's Section 504: Chip Cullen Looping Video Backgrounds: pointers and pitfalls: Chip Cullen How to “preview” a click event tag in the Google Tag Manager console: Chip Cullen Moving on from a technology, or: life after Drupal: Chip Cullen Don’t be a dumb developer: Chip Cullen Two level breadcrumbs with CSS :only-child: Chip Cullen Simplicity comes with experience: Chip Cullen Do the least amount possible: Chip Cullen SVGs vs. Icon Fonts: Two points in favor of Icon Fonts: Chip Cullen Accessible links without underlines: Chip Cullen The Strategic Job Hunt: Chip Cullen Surviving Getting Laid Off: Chip Cullen How to structure your typography in Sass: Chip Cullen Layer Cake: A Responsive Design Layout Pattern: Chip Cullen Creativity is yet to come in Web Design: Chip Cullen Front End Testing with Wraith: A Step by Step Recipe: Chip Cullen Where to begin? How I start a visual design for the web: Chip Cullen If you could only have five Google Fonts: Chip Cullen Why SVG is so cool (or: what happens when you're late to the party on something): Chip Cullen How to apply classes to elements with CKEditor 4, in Drupal 7: Chip Cullen
How to Create and Use Fixtures in Cypress Tests: Chip Cullen
2019-03-28 · via Chip Cullen

I don't write a lot of end to end (e2e) tests. However, for one project at work, we have a handful of them, and we write them using Cypress. Cypress is a great e2e test framework that is very intuitive for people coming from a JavaScript background.

In particular, I was writing an e2e test for an interaction that required an ajax call / response, and found the existing Cypress documentation … lacking. It is full of unspoken assumptions and one glaring omission.

I'm writing this post mostly as notes to myself in the future, but I hope this walk through helps someone else out there.

What are fixtures? Why should I care?

Fixtures are blobs of hard coded data, usually recorded from an actual network response. (You could write your own by hand, but I imagine it'd be quite painful.)

If you are trying to test functionality that relies on a network request, test frameworks can artificially insert this fixture data while running the test. The insertion of fake data like this is referred to as stubbing. This has many advantages for tests:

  • They remove the reliance on a functioning network to make the test work
  • You can write tests knowing that the data won't change
  • It speeds up tests, since you're not actually waiting for a network response

What place do fixtures have in Cypress?

Fixtures will only be useful in something like Cypress if you are stubbing in front end network requests (read: xhr / ajax). Cypress runs a browser instance and then tests what happens in that browser.

You cannot stub server backend network requests. (You can do this in separate backend integration tests, but then you are not testing browser behavior.)

In other words — if you have a server side rendered site, this won't help you much.

Okay, I want to test a front end interaction with an AJAX call. Now what?

So you've identified a piece of functionality that you want to test, and it depends on an AJAX / XHR call in order to work. Here is roughly the steps you will go through:

  1. Identify which XHR requests is being made with this interaction
  2. Intercept the response from that request and write it to a fixture
  3. Configure your test so that it knows to insert this fixture when a particular XHR call is being made as part of the test

(This is what I found so frustrating about the Cypress docs on this. In that whole page, it basically covers step 3 above. At no point do they explain how to generate a fixture, they just explain how to use it.)

Step 1 - Identify which XHR requests is being made with this interaction

The easiest way to figure out exactly which XHR call to record is to use your browser's developer tools Network tab. The screenshot below will be from Chrome, but other browsers have very similar functionality. So, with that tab open:

Chrome network tab filtered to XHR requests

  1. Filter to only XHR network requests
  2. Clear all recorded requests that have already loaded
  3. Perform the interaction that you're looking to test (clicking on the button, changing a select, etc)
  4. You should see a new XHR request in the network tab, click on it
  5. Note the full Request URL - we will need that in a second, so, copy it

Step 2 - Intercept the response from that request and write it to a fixture

This is the glaring omission made in the Cypress docs. I literally found out how to do this from some Github issue comments. Apparently, this steps seems obvious to a lot of people — well, I can tell you, it is not obvious.

I'm going to assume that you already have Cypress installed in your project. Let's create a test for, say, a widget component (the actual kind of component isn't important).

We'll create a test file in the cypress/integration integration directory. Call it, say, widget_spec.js. You will need to start off with a basic test like this:

// cypress/integration/widget_spec.js

describe("Testing the widget", function() {
  it("Widget does something with AJAX / XHR", function() {
    // stuff will go here
  });
});

This is the magic part. At this point you can write a temporary function that will make the network call in question, and then write that response to a fixture file.

// cypress/integration/widget_spec.js

describe("Testing the widget", function() {
  it("Widget does something with AJAX / XHR", function() {
    // this function will be temporary
    // using cy.request, we will ping the
    // Request URL that we copied earlier
    cy.request("https://request-url-from-step-1-above/example/").then(
      response => {
        // then use the response.body to write a fixture.
        cy.writeFile("cypress/fixtures/widget.json", response.body);
      }
    );
  });
});

You can organize fixtures however you want, but they should live in the cypress/fixtures directory.

Now, actually run Cypress and run the current spec file's tests. Cypress will now create a fixture file (in this example, cypress/fixtures/widget.json). That is the fixture we will now use in our test.

You can look at it — it's just a JSON file. For this example, let's say it looks like this:

// cypress/fixtures/widget.js
{
  "title": "The title of the widget based on the XHR fixture data"
}

Step 3 - Configure your test so that it knows to insert this fixture when a particular XHR call is being made as part of the test

Now that we have a fixture file in hand, we can write a test that stubs that response in when an XHR call is made.

First, delete the function that we wrote before.

Now, writing a test to use the fixture looks like this:

// cypress/integration/widget_spec.js

describe("Testing the widget", function() {
  it("Widget does something with AJAX / XHR", function() {
    // sets up cy.server, so cypress knows to
    // prepare network responses
    cy.server();
    // this is where we tell cypress to intercept
    // certain XHR calls,
    // and to stub in our fixture instead
    cy.route({
      // our example is a GET call, but you could also
      // have a POST, if you're pushing data up
      method: "GET",
      // more on the URL below
      url: `https://request-url-from-step-1-above/example/`,
      // the fixture: shortcut will know to
      // look in cypress/fixtures,
      // unless you configure cypress to
      // put it somewhere else
      response: "fixture:widget.json"
    });
    // all this does is load the path where our widget is,
    // but it has to come after cy.server and cy.route
    cy.visit("/path-to-page-where-widget-appears");
    // using a CSS selector, in this case a class name,
    // make sure there is at least one widget
    cy.get(".widget-selector").should("have.length", 1);
    // from here on out, you can write your test as needed
    // in this example clicking the widget button
    // kicks off the XHR request
    cy.get(".widget-button").click();
    // our fixture data will come back,
    // so we can write tests to make sure
    // data is getting displayed in some
    // manner that we expect
    cy.get(".widget-title").contains(
      "The title of the widget based on the XHR fixture data"
    );
  });
});

Configuring cy.route and the URL

In our example above, I had this configuration:

cy.route({
  method: "GET",
  url: `https://request-url-from-step-1-above/example/`,
  response: "fixture:widget.json"
});

First https://request-url-from-step-1-above/example/ is an absolute URL. You will need this if your XHR call is to outside site, but, if it's an internal AJAX call, you can start with /, like so:

url: `/example/`,

This is okay, if the URL is only ever one path, and it never changes. Thankfully, we can use wildcards.

url: `/example/*`,

This was one of the tricker things that I ran into. Depending on the depth of the path, you may need to experiment with which pieces of it you can or cannot wildcard in order to get stubbing to work.

Let's say it's more complicated, like

url: `/users/123/profile/emailprefs`,

Using a blanket wildcard like this may not work:

// does not work
url: `/users/*`,

But with some trial and error you may find that something like this works:

url: `/users/*/profile/*`,

I wasted a lot of time trying to get stubbing to work, only to find that my url wildcard needed to be more specific.

Conclusion

I hope this helps you write some fixture driven e2e tests in Cypress!