{"__v":0,"_id":"56954a97fe18811700c9c022","category":{"__v":16,"_id":"56954a95fe18811700c9bfdf","pages":["56954a97fe18811700c9c01d","56954a97fe18811700c9c01e","56954a97fe18811700c9c01f","56954a97fe18811700c9c020","56954a97fe18811700c9c021","56954a97fe18811700c9c022","56954a97fe18811700c9c023","56954a97fe18811700c9c024","56954a97fe18811700c9c025","56954a97fe18811700c9c026","56954a97fe18811700c9c027","56954a97fe18811700c9c028","56954a97fe18811700c9c029","5696cda524490c3700170a05","5697efe61c4dc8230054268e","5697efe72cf4060d004eaa75","56993ff47465970d00650b8f","56a7a155dfdabc0d000ae910","56a7a155b5d0920d0051cd81","56a7a1a6cf6d771700baeee3","56a7a1a63d33bc2100793d5d","56a7a23097e8b00d0096d209","56a7a230ea3e3417000df4b1","56a7a25acf6d771700baeee6","56a7a25a03f28c0d00a545bf","56a7a2b83d33bc2100793d60","56a7a2b8b5d0920d0051cd82","56b27fe42db51f0d0044e566"],"project":"568fde81b700ce0d002f4b43","version":"56954a94fe18811700c9bfda","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-01-09T16:40:53.584Z","from_sync":false,"order":4,"slug":"guides","title":"Guides"},"parentDoc":null,"project":"568fde81b700ce0d002f4b43","user":"568fffce769f210d0013258f","version":{"__v":6,"_id":"56954a94fe18811700c9bfda","project":"568fde81b700ce0d002f4b43","createdAt":"2016-01-12T18:48:52.007Z","releaseDate":"2016-01-12T18:48:52.007Z","categories":["56954a95fe18811700c9bfdb","56954a95fe18811700c9bfdc","56954a95fe18811700c9bfdd","56954a95fe18811700c9bfde","56954a95fe18811700c9bfdf","56954a95fe18811700c9bfe0","56954a95fe18811700c9bfe1","56954a95fe18811700c9bfe2","56954a95fe18811700c9bfe3","56954a95fe18811700c9bfe4","5695649fdcaf0d1700cb8721","5696c1168560a60d00e2c1d6","56a7a32e79395317007c1ad6","5898fc3eec49fb0f004c2663","589cc675ea37da23004e05e1"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"foo","version_clean":"0.0.0","version":"0.0"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-01-09T16:42:07.209Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":4,"body":"# Contents\n\n- :fa-angle-right: [Strategy](#section-strategy)\n  - [1: Don't Stub Responses](#section-1-don-1-stub-responses)\n  - [2: Stub Responses](#section-2-stub-responses)\n- :fa-angle-right: [How to Stub Responses](#section-how-to-stub-responses)\n- :fa-angle-right: [Requests](#section-requests)\n- :fa-angle-right: [Server + Routing Table](#section-server-routing-table)\n- :fa-angle-right: [Fixtures](#section-fixtures)\n- :fa-angle-right: [Waiting](#section-waiting)\n  - [Removing Flake](#section-removing-flake)\n  - [Clear Source of Failure](#section-clear-source-of-failure)\n  - [Asserting about the XHR Object](#section-asserting-about-the-xhr-object)\n\n***\n\n# Strategy\n\nCypress makes it easy to manage the entire lifecyle of AJAX / XHR requests within your application. Cypress provides you direct access to the XHR objects, enabling you to make assertions about its properties. Additionally you can even stub and mock a request's response.\n\n**Common testing scenarios:**\n\n- Asserting on a request's body\n- Asserting on a request's url\n- Asserting on a request's headers\n- Stubbing a response's body\n- Stubbing a response's status code\n- Stubbing a response's headers\n- Delaying a response\n- Waiting for a response to happen\n\nWithin Cypress, you have the ability to choose whether to stub responses or allow them to actually hit your server. You can also mix and match within the same test by choosing to stub certain requests, while allowing others to hit your server.\n\nLet's investigate both strategies, why you would use one versus the other, and why you should regularly use both.\n\n***\n\n## 1: Don't Stub Responses\n\nRequests that aren't stubbed will actually reach your server. By *not* stubbing your responses, you are writing true **end to end** tests. This means you are driving your application the same way a real user would.\n\n> When requests are not stubbed, this gaurantees the *contract* between your client and server is working correctly.\n\nIn other words, you can have confidence your server is sending the correct data in the correct structure for your client to consume. It is a good idea to have **end to end** tests around your application's *critical paths*. These typically include user login, signup, and other critical paths such as billing.\n\n**There are downsides to not stubbing responses you should be aware of:**\n\n- Since no responses are stubbed, that means your server has to *actually send real responses*. This can be problematic because you may have to *seed a database* before every test to generate state. For instance, if you were testing **pagination**, you'd have to seed the database with every object that it takes to replicate this feature in your application.\n- Since real responses go through every single layer of your server (controllers / models / views) the tests are often *much* slower than stubbed responses.\n\nIf you are writing a traditional server-side application where most of the responses are `HTML` you will likely have few stubbed responses. However, most modern applications that serve `JSON` can take advantage of stubbing.\n\n[block:callout]\n{\n  \"type\": \"success\",\n  \"body\": \"- Guaranteed to work in production\\n- Test coverage around server endpoints\\n- Great for traditional server-side HTML rendering\",\n  \"title\": \"Benefits\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"danger\",\n  \"body\": \"- Requires seeding\\n- Much slower\\n- Hard to test edge cases\",\n  \"title\": \"Downsides\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"- Use sparingly\\n- Great for the *critical paths* of your application\\n- Helpful to have one test around the *happy path* of a feature\",\n  \"title\": \"Suggestions\"\n}\n[/block]\n\n***\n\n## 2: Stub Responses\n\nStubbing responses enables you to control every aspect of the response, including the response body, the status, headers, and even network delay. Stubbing is extremely fast, most responses will be returned in less than 20ms.\n\n> Stubbing responses is a great way to control the data that is returned to your client.\n\nYou don't have to do any work on the server. Your application will have no idea it's requests are being stubbed, so there are **no code changes** needed. In fact, stubbed requests will show up in the Network tab of your Developer Tools, and your application will continue to work after the test is finished.\n\n[block:callout]\n{\n  \"type\": \"success\",\n  \"body\": \"- Easy control of response bodies, status, and headers\\n- Force responses to take longer to simulate network delay\\n- No code changes to your server or client code\\n- Fast, < 20ms response times\\n- Perfect for JSON API's\",\n  \"title\": \"Benefits\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"danger\",\n  \"body\": \"- No guarantee your stubbed responses match the actual data your server sends\\n- No test coverage on some server endpoints\\n- Not as useful if you're using traditional server side HTML rendering\",\n  \"title\": \"Downsides\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"- Use for the vast majority of your testing\\n- Mix and match, typically have one true end to end test, and then stub the rest\",\n  \"title\": \"Suggestions\"\n}\n[/block]\n\n***\n\n# How to stub responses\n\nCypress makes it easy to stub a response and control the `body`, `status`, `headers`, or even delay.\n\nTo begin stubbing responses you have to do two things.\n\n1. Start a [`cy.server`](https://on.cypress.io/api/server)\n2. Provide a [`cy.route`](https://on.cypress.io/api/route)\n\nThese two commands work together to control the behavior of your responses within the command's options. See [`cy.server` options](https://on.cypress.io/api/server#section-options) and [`cy.route` options](https://on.cypress.io/api/route#section-options) for instructions on how to stub responses.\n\n[`cy.server`](https://on.cypress.io/api/server) enables stubbing, while [`cy.route`](https://on.cypress.io/api/route) provides a routing table so Cypress understands which response should go with which request.\n\n***\n\n# Requests\n\nCypress will automatically indicate when an XHR request happens in your application. These are logged in the Command Log regardless of whether or not you are using stubbing. This provides you a visual indicator when a request has started and when it is finished. Additionally, Cypress will take a snapshot of the DOM when the request is made and another snapshot when the response comes back.\n\nBy default, Cypress is configured to *ignore* requests that are used to fetch static content like `.js` or `.html` files. This keeps the Command Log less noisy. This option can be changed in the [configuration](https://on.cypress.io/guides/configuration).\n\nCypress automatically collects the request `headers` and the request `body` and will make this available to you.\n\n***\n\n# Server + Routing Table\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  // enable response stubbing\\n  .server()\\n\\n  // Route all GET requests that have a\\n  // URL that matches the RegExp /users/\\n  // and force the response to be: []\\n  .route({\\n    method: \\\"GET\\\",\\n    url: /users/,\\n    response: []\\n  })\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\nEach [`cy.route`](https://on.cypress.io/api/route) you provide will automatically route those requests to specific responses and control their body, response headers, or even force additional network delay.\n\nWhen you start a server and provide a routing table, Cypress will display this under \"Routes\" in the Command Log.\n\n![Routing Table](https://cloud.githubusercontent.com/assets/1268976/10780221/91743ab8-7d11-11e5-9fe1-8bcbdf5e344c.png)\n\nOnce you start a server with [`cy.server`](https://on.cypress.io/api/server), all requests will be controllable for the remainder of the test. When a new test runs, Cypress will restore the default behavior and remove all routing and stubbing. For a complete reference of the API and options, refer to the documentation for each command.\n\n- [`cy.server`](https://on.cypress.io/api/server)\n- [`cy.route`](https://on.cypress.io/api/route)\n\n***\n\n# Fixtures\n\nWhen stubbing a response, you typically need to manage potentially large and complex JSON objects. Cypress has support for [fixtures](https://on.cypress.io/guides/creating-fixtures), and even allows you to integrate fixture syntax directly into responses.\n\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .server()\\n\\n   // we set the response to be the activites.json fixture\\n  .route(\\\"GET\\\", /activities/, \\\"fixture:activities.json\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\nYou can additionally reference [aliases](https://on.cypress.io/guides/using-aliases) within responses. These aliases do not have to point to fixtures, but that is a common use case. Separating out a fixture enables you to work and mutate that object prior to handing it off to a response.\n\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .server()\\n\\n  .fixture(\\\"activities.json\\\").as(\\\"activitiesJSON\\\")\\n  .route(\\\"GET\\\", /activities/, \\\":::at:::activitiesJSON\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n***\n\n# Waiting\n\nWhether or not you choose to stub responses, Cypress enables you to declaratively [`cy.wait`](https://on.cypress.io/api/wait) for requests and their responses.\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .server()\\n  .route(/activities/, \\\"fixture:activities\\\").as(\\\"getActivities\\\")\\n  .route(/messages/, \\\"fixture:messages\\\").as(\\\"getMessages\\\")\\n\\n  // visit the dashboard, which should make requests that match\\n  // the two routes above\\n  .visit(\\\"http://localhost:8888/dashboard\\\")\\n\\n  // pass an array of Route Aliases which forces Cypress to wait\\n  // until it sees a response for each request that matches\\n  // each of these aliases\\n  .wait([\\\"@getActivities\\\", \\\"@getMessages\\\"])\\n\\n  // these commands will not run until the wait command resolves above\\n  .get(\\\"h1\\\").should(\\\"contain\\\", \\\"Dashboard\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\nDeclaratively waiting for responses has many advantages:\n- You descrease test flake\n- Source of failure is clearer\n- You can make assertions about the XHR objects\n\n***\n\n## Removing Flake\n\nOne advantage of declaratively waiting for requests is that it decreases test flake. You can think of [`cy.wait`](https://on.cypress.io/api/wait) as a guard that indicates to Cypress when you expect a request to be made that matches a specific routing alias. This prevents commands from running until responses come back and it guards against situations where your requests are initially delayed.\n\n**Auto-complete Example:**\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .server()\\n  .route(/search/, [{item: \\\"Book 1\\\"}, {item: \\\"Book 2\\\"}]).as(\\\"getSearch\\\")\\n\\n  // our autocomplete field is throttled\\n  // meaning it only makes a request after\\n  // 500ms from the last keyPress\\n  .get(\\\"#autocomplete\\\").type(\\\"Book\\\")\\n\\n  // wait for the request + response\\n  // thus insulating us from the\\n  // throttled request\\n  .wait(\\\"@getSearch\\\")\\n\\n  .get(\\\"#results\\\")\\n    .should(\\\"contain\\\", \\\"Book 1\\\")\\n    .and(\\\"contain\\\", \\\"Book 2\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\nWhat makes this example above so powerful is that Cypress will automatically wait for a request that matches the `getSearch` alias. Instead of forcing Cypress to test the *side effect* of a successful request (the display of the Book results), you can test the actual *cause* of the results.\n\n***\n\n## Clear Source of Failure\n\nIn our example above, we added an assertion to the display of the search results.\n\n**The search results working are coupled to a few things in our application:**\n\n1. Our application making a request to the correct URL.\n2. Our application correctly processing the response.\n3. Our application inserting the results into the DOM.\n\nIn this example, there are many possible sources of failure. In most testing tools, if our request failed to ever go out, we would normally only ever get an error once we attempt to find the results in the DOM and see that there is no matching element. This is problematic because it's unknown *why* the results failed to be displayed. Was there a problem with our rendering code? Did we modify or change an attribute such as an `id` or `class` on an element? Perhaps our server sent us different Book items.\n\nWith Cypress, by adding a [`cy.wait`](https://on.cypress.io/api/wait) guard, you can more easily pinpoint your specific problem. If the request never went out, you'll receive errors like this.\n\n![wait failure](https://cloud.githubusercontent.com/assets/1268976/10780062/a9c3245a-7d0f-11e5-9984-67d84650b0a0.png)\n\nNow we know exactly why our test failed. It had nothing to do with the DOM. Instead we can see that either our request never went out or a request went out to the wrong URL.\n\n***\n\n## Asserting about the XHR Object\n\nAnother benefit of using [`cy.wait`](https://on.cypress.io/api/wait) on requests is that it allows you to access the actual `XHR` object. This is useful when you want to make assertions about this object.\n\nIn our example above we can assert about the request object to verify that it sent data as a query string in the URL. Although we're mocking the response, we can still verify that our application sends the correct request.\n\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .server()\\n  .route(/search/, [{item: \\\"Book 1\\\"}, {item: \\\"Book 2\\\"}]).as(\\\"getSearch\\\")\\n\\n  .get(\\\"#autocomplete\\\").type(\\\"Book\\\")\\n\\n  // this yields us the XHR object which includes\\n  // fields for request, response, url, method, etc\\n  .wait(\\\"@getSearch\\\")\\n    .its(\\\"url\\\").should(\\\"include\\\", \\\"/search?query=Book\\\")\\n\\n  .get(\\\"#results\\\")\\n    .should(\\\"contain\\\", \\\"Book 1\\\")\\n    .and(\\\"contain\\\", \\\"Book 2\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n**The XHR object that [`cy.wait`](https://on.cypress.io/api/wait) yields you has everything you need to make assertions including:**\n\n- URL\n- Method\n- Status Code\n- Request Body\n- Request Headers\n- Response Body\n- Response Headers","excerpt":"A guide to managing XHR requests","slug":"network-requests-xhr","type":"basic","title":"Network Requests"}

Network Requests

A guide to managing XHR requests

# Contents - :fa-angle-right: [Strategy](#section-strategy) - [1: Don't Stub Responses](#section-1-don-1-stub-responses) - [2: Stub Responses](#section-2-stub-responses) - :fa-angle-right: [How to Stub Responses](#section-how-to-stub-responses) - :fa-angle-right: [Requests](#section-requests) - :fa-angle-right: [Server + Routing Table](#section-server-routing-table) - :fa-angle-right: [Fixtures](#section-fixtures) - :fa-angle-right: [Waiting](#section-waiting) - [Removing Flake](#section-removing-flake) - [Clear Source of Failure](#section-clear-source-of-failure) - [Asserting about the XHR Object](#section-asserting-about-the-xhr-object) *** # Strategy Cypress makes it easy to manage the entire lifecyle of AJAX / XHR requests within your application. Cypress provides you direct access to the XHR objects, enabling you to make assertions about its properties. Additionally you can even stub and mock a request's response. **Common testing scenarios:** - Asserting on a request's body - Asserting on a request's url - Asserting on a request's headers - Stubbing a response's body - Stubbing a response's status code - Stubbing a response's headers - Delaying a response - Waiting for a response to happen Within Cypress, you have the ability to choose whether to stub responses or allow them to actually hit your server. You can also mix and match within the same test by choosing to stub certain requests, while allowing others to hit your server. Let's investigate both strategies, why you would use one versus the other, and why you should regularly use both. *** ## 1: Don't Stub Responses Requests that aren't stubbed will actually reach your server. By *not* stubbing your responses, you are writing true **end to end** tests. This means you are driving your application the same way a real user would. > When requests are not stubbed, this gaurantees the *contract* between your client and server is working correctly. In other words, you can have confidence your server is sending the correct data in the correct structure for your client to consume. It is a good idea to have **end to end** tests around your application's *critical paths*. These typically include user login, signup, and other critical paths such as billing. **There are downsides to not stubbing responses you should be aware of:** - Since no responses are stubbed, that means your server has to *actually send real responses*. This can be problematic because you may have to *seed a database* before every test to generate state. For instance, if you were testing **pagination**, you'd have to seed the database with every object that it takes to replicate this feature in your application. - Since real responses go through every single layer of your server (controllers / models / views) the tests are often *much* slower than stubbed responses. If you are writing a traditional server-side application where most of the responses are `HTML` you will likely have few stubbed responses. However, most modern applications that serve `JSON` can take advantage of stubbing. [block:callout] { "type": "success", "body": "- Guaranteed to work in production\n- Test coverage around server endpoints\n- Great for traditional server-side HTML rendering", "title": "Benefits" } [/block] [block:callout] { "type": "danger", "body": "- Requires seeding\n- Much slower\n- Hard to test edge cases", "title": "Downsides" } [/block] [block:callout] { "type": "info", "body": "- Use sparingly\n- Great for the *critical paths* of your application\n- Helpful to have one test around the *happy path* of a feature", "title": "Suggestions" } [/block] *** ## 2: Stub Responses Stubbing responses enables you to control every aspect of the response, including the response body, the status, headers, and even network delay. Stubbing is extremely fast, most responses will be returned in less than 20ms. > Stubbing responses is a great way to control the data that is returned to your client. You don't have to do any work on the server. Your application will have no idea it's requests are being stubbed, so there are **no code changes** needed. In fact, stubbed requests will show up in the Network tab of your Developer Tools, and your application will continue to work after the test is finished. [block:callout] { "type": "success", "body": "- Easy control of response bodies, status, and headers\n- Force responses to take longer to simulate network delay\n- No code changes to your server or client code\n- Fast, < 20ms response times\n- Perfect for JSON API's", "title": "Benefits" } [/block] [block:callout] { "type": "danger", "body": "- No guarantee your stubbed responses match the actual data your server sends\n- No test coverage on some server endpoints\n- Not as useful if you're using traditional server side HTML rendering", "title": "Downsides" } [/block] [block:callout] { "type": "info", "body": "- Use for the vast majority of your testing\n- Mix and match, typically have one true end to end test, and then stub the rest", "title": "Suggestions" } [/block] *** # How to stub responses Cypress makes it easy to stub a response and control the `body`, `status`, `headers`, or even delay. To begin stubbing responses you have to do two things. 1. Start a [`cy.server`](https://on.cypress.io/api/server) 2. Provide a [`cy.route`](https://on.cypress.io/api/route) These two commands work together to control the behavior of your responses within the command's options. See [`cy.server` options](https://on.cypress.io/api/server#section-options) and [`cy.route` options](https://on.cypress.io/api/route#section-options) for instructions on how to stub responses. [`cy.server`](https://on.cypress.io/api/server) enables stubbing, while [`cy.route`](https://on.cypress.io/api/route) provides a routing table so Cypress understands which response should go with which request. *** # Requests Cypress will automatically indicate when an XHR request happens in your application. These are logged in the Command Log regardless of whether or not you are using stubbing. This provides you a visual indicator when a request has started and when it is finished. Additionally, Cypress will take a snapshot of the DOM when the request is made and another snapshot when the response comes back. By default, Cypress is configured to *ignore* requests that are used to fetch static content like `.js` or `.html` files. This keeps the Command Log less noisy. This option can be changed in the [configuration](https://on.cypress.io/guides/configuration). Cypress automatically collects the request `headers` and the request `body` and will make this available to you. *** # Server + Routing Table [block:code] { "codes": [ { "code": "cy\n // enable response stubbing\n .server()\n\n // Route all GET requests that have a\n // URL that matches the RegExp /users/\n // and force the response to be: []\n .route({\n method: \"GET\",\n url: /users/,\n response: []\n })\n", "language": "javascript" } ] } [/block] Each [`cy.route`](https://on.cypress.io/api/route) you provide will automatically route those requests to specific responses and control their body, response headers, or even force additional network delay. When you start a server and provide a routing table, Cypress will display this under "Routes" in the Command Log. ![Routing Table](https://cloud.githubusercontent.com/assets/1268976/10780221/91743ab8-7d11-11e5-9fe1-8bcbdf5e344c.png) Once you start a server with [`cy.server`](https://on.cypress.io/api/server), all requests will be controllable for the remainder of the test. When a new test runs, Cypress will restore the default behavior and remove all routing and stubbing. For a complete reference of the API and options, refer to the documentation for each command. - [`cy.server`](https://on.cypress.io/api/server) - [`cy.route`](https://on.cypress.io/api/route) *** # Fixtures When stubbing a response, you typically need to manage potentially large and complex JSON objects. Cypress has support for [fixtures](https://on.cypress.io/guides/creating-fixtures), and even allows you to integrate fixture syntax directly into responses. [block:code] { "codes": [ { "code": "cy\n .server()\n\n // we set the response to be the activites.json fixture\n .route(\"GET\", /activities/, \"fixture:activities.json\")\n", "language": "javascript" } ] } [/block] You can additionally reference [aliases](https://on.cypress.io/guides/using-aliases) within responses. These aliases do not have to point to fixtures, but that is a common use case. Separating out a fixture enables you to work and mutate that object prior to handing it off to a response. [block:code] { "codes": [ { "code": "cy\n .server()\n\n .fixture(\"activities.json\").as(\"activitiesJSON\")\n .route(\"GET\", /activities/, \"@activitiesJSON\")\n", "language": "javascript" } ] } [/block] *** # Waiting Whether or not you choose to stub responses, Cypress enables you to declaratively [`cy.wait`](https://on.cypress.io/api/wait) for requests and their responses. [block:code] { "codes": [ { "code": "cy\n .server()\n .route(/activities/, \"fixture:activities\").as(\"getActivities\")\n .route(/messages/, \"fixture:messages\").as(\"getMessages\")\n\n // visit the dashboard, which should make requests that match\n // the two routes above\n .visit(\"http://localhost:8888/dashboard\")\n\n // pass an array of Route Aliases which forces Cypress to wait\n // until it sees a response for each request that matches\n // each of these aliases\n .wait([\"@getActivities\", \"@getMessages\"])\n\n // these commands will not run until the wait command resolves above\n .get(\"h1\").should(\"contain\", \"Dashboard\")\n", "language": "javascript" } ] } [/block] Declaratively waiting for responses has many advantages: - You descrease test flake - Source of failure is clearer - You can make assertions about the XHR objects *** ## Removing Flake One advantage of declaratively waiting for requests is that it decreases test flake. You can think of [`cy.wait`](https://on.cypress.io/api/wait) as a guard that indicates to Cypress when you expect a request to be made that matches a specific routing alias. This prevents commands from running until responses come back and it guards against situations where your requests are initially delayed. **Auto-complete Example:** [block:code] { "codes": [ { "code": "cy\n .server()\n .route(/search/, [{item: \"Book 1\"}, {item: \"Book 2\"}]).as(\"getSearch\")\n\n // our autocomplete field is throttled\n // meaning it only makes a request after\n // 500ms from the last keyPress\n .get(\"#autocomplete\").type(\"Book\")\n\n // wait for the request + response\n // thus insulating us from the\n // throttled request\n .wait(\"@getSearch\")\n\n .get(\"#results\")\n .should(\"contain\", \"Book 1\")\n .and(\"contain\", \"Book 2\")\n", "language": "javascript" } ] } [/block] What makes this example above so powerful is that Cypress will automatically wait for a request that matches the `getSearch` alias. Instead of forcing Cypress to test the *side effect* of a successful request (the display of the Book results), you can test the actual *cause* of the results. *** ## Clear Source of Failure In our example above, we added an assertion to the display of the search results. **The search results working are coupled to a few things in our application:** 1. Our application making a request to the correct URL. 2. Our application correctly processing the response. 3. Our application inserting the results into the DOM. In this example, there are many possible sources of failure. In most testing tools, if our request failed to ever go out, we would normally only ever get an error once we attempt to find the results in the DOM and see that there is no matching element. This is problematic because it's unknown *why* the results failed to be displayed. Was there a problem with our rendering code? Did we modify or change an attribute such as an `id` or `class` on an element? Perhaps our server sent us different Book items. With Cypress, by adding a [`cy.wait`](https://on.cypress.io/api/wait) guard, you can more easily pinpoint your specific problem. If the request never went out, you'll receive errors like this. ![wait failure](https://cloud.githubusercontent.com/assets/1268976/10780062/a9c3245a-7d0f-11e5-9984-67d84650b0a0.png) Now we know exactly why our test failed. It had nothing to do with the DOM. Instead we can see that either our request never went out or a request went out to the wrong URL. *** ## Asserting about the XHR Object Another benefit of using [`cy.wait`](https://on.cypress.io/api/wait) on requests is that it allows you to access the actual `XHR` object. This is useful when you want to make assertions about this object. In our example above we can assert about the request object to verify that it sent data as a query string in the URL. Although we're mocking the response, we can still verify that our application sends the correct request. [block:code] { "codes": [ { "code": "cy\n .server()\n .route(/search/, [{item: \"Book 1\"}, {item: \"Book 2\"}]).as(\"getSearch\")\n\n .get(\"#autocomplete\").type(\"Book\")\n\n // this yields us the XHR object which includes\n // fields for request, response, url, method, etc\n .wait(\"@getSearch\")\n .its(\"url\").should(\"include\", \"/search?query=Book\")\n\n .get(\"#results\")\n .should(\"contain\", \"Book 1\")\n .and(\"contain\", \"Book 2\")\n", "language": "javascript" } ] } [/block] **The XHR object that [`cy.wait`](https://on.cypress.io/api/wait) yields you has everything you need to make assertions including:** - URL - Method - Status Code - Request Body - Request Headers - Response Body - Response Headers