{"_id":"56902bc818c3920d00be8b57","category":{"_id":"569002f19ebef90d0087289d","pages":["56900352769f210d00132595","5690047121fcf0190071d943","569004924719c119002ce654","569004ceb700ce0d002f4b94","569023e518c3920d00be8b37","569023f748df220d004ca215","5690240af7eb9a0d00f4465d","5690241b48df220d004ca217","5690243e48df220d004ca219","56902453741e9c0d00af2fb5","56902463efcc380d0043a5a1","5690247b18c3920d00be8b39","56902492f7eb9a0d00f4465f","569024a16c49d70d00f18075","569024b2efcc380d0043a5a3","569024cc48df220d004ca21b","569024ea18c3920d00be8b3b","5690258618c3920d00be8b3f","5690259bf7eb9a0d00f44662","569025b06c49d70d00f18077","569029b418c3920d00be8b43","569029d4f7eb9a0d00f44667","569029e8e056c80d00fdec58","569029fb48df220d004ca221","56902a1c18c3920d00be8b46","56902a45f7eb9a0d00f44669","56902a6be056c80d00fdec5a","56902a78f7eb9a0d00f4466b","56902a8848df220d004ca224","56902aa018c3920d00be8b4b","56902ace6c49d70d00f18085","56902ae0741e9c0d00af2fc6","56902aee48df220d004ca226","56902af8f7eb9a0d00f44674","56902b26efcc380d0043a5b1","56902b8148df220d004ca22a","56902ba918c3920d00be8b55","56902bb96c49d70d00f1808b","56902bc818c3920d00be8b57","56902bd518c3920d00be8b59","56902be218c3920d00be8b5b","56902bf66c49d70d00f1808e","56902c05e056c80d00fdec5d","56902c196c49d70d00f18090","56902c2648df220d004ca22d","56902c34f7eb9a0d00f44678","56902c5518c3920d00be8b5d","56902c62741e9c0d00af2fcc","56902cde48df220d004ca230","56902cea741e9c0d00af2fcf","56902d0ae056c80d00fdec60","56902d20efcc380d0043a5b4","56902d3448df220d004ca232","5696c3fbf9203821005fe2fb","5696c3fb9e2d000d00947ab0","5696c3fbf9203821005fe2fa","5697efee8d2a770d00d2fd17","569802611c4dc823005426c7","56a65c82b3ffe00d00156eaf","56f01f88332da41700f24b74"],"project":"568fde81b700ce0d002f4b43","version":"568fde82b700ce0d002f4b46","__v":60,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-01-08T18:41:53.562Z","from_sync":false,"order":1,"slug":"commands","title":"Commands"},"version":{"_id":"568fde82b700ce0d002f4b46","__v":23,"project":"568fde81b700ce0d002f4b43","createdAt":"2016-01-08T16:06:26.373Z","releaseDate":"2016-01-08T16:06:26.373Z","categories":["568fde82b700ce0d002f4b47","568ff0e504440a1700e4cbbd","569002f19ebef90d0087289d","569004f4769f210d00132599","5690056d9ebef90d008728a0","569005d394c5030d0028813a","5690067804440a1700e4cbe2","569137eb3c4f510d00ec9b92","56913815e56a790d008dbfe3","569138ba3c4f510d00ec9b93","5691392f3c4f510d00ec9b94","56913bbe72f2810d007e4cb0","56933b8d6ebadc0d005b71d2","56933b8d6ebadc0d005b71d3","569564facaa32519009c41e6","5696a319b6d61f0d00acfb40","5696a319a857080d0082e8e8","5697efe43503e40d0061f4d1","5697efe48d2a770d00d2fd16","569e9597ffccd10d00a05c59","56a7a1523d33bc2100793d5c","56a7a32ecf6d771700baeee8","56b8b0f7ddeb231700e69825"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":false,"codename":"bar","version_clean":"1.0.0","version":"1.0"},"user":"568fffce769f210d0013258f","__v":0,"parentDoc":null,"project":"568fde81b700ce0d002f4b43","updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-01-08T21:36:08.625Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":52,"body":"[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"[Read about Network Requests first.](https://on.cypress.io/guides/network-requests-xhr)\",\n  \"title\": \"New to Cypress?\"\n}\n[/block]\n\nUse `cy.route` to manage the behavior of network requests.\n\n| | |\n|--- | --- |\n| **Returns** | `null` |\n| **Timeout** | *cannot timeout* |\n\n***\n\n# [cy.route( *url* )](#section-url-usage)\n\nSet a route matching the specific `url` which is not stubbed but can be waited on later. This will match `GET` request methods.\n\n***\n\n# [cy.route( *url*, *response* )](#section-url-and-response-usage)\n\nSet a route matching the `url` stubbed with the supplied `response`. This will match `GET` request methods.\n\n***\n\n# [cy.route( *method*, *url* )](#section-method-and-url-usage)\n\nSet a route matching the specific `method` and `url` which is not stubbed but can be waited on later.\n\n***\n\n# [cy.route( *method*, *url*, *response* )](#section-method-url-and-response-usage)\n\nSet a route matching the `method` and `url` stubbed with the supplied `response`.\n\n***\n\n# [cy.route( *function* )](#section-function-usage)\n\nSet a route by returning an object literal from your callback function.\n\nFunctions which return a promise will automatically be awaited.\n\n***\n\n# Options\n\nPass in an options object to change the default behavior of `cy.route`. By default `cy.route` inherits its options from [`cy.server`](https://on.cypress.io/api/server).\n\n**[cy.route( *options* )](#options-usage)**\n\nOption | Default | Notes\n--- | --- | ---\n`method` | `GET` | method to match against requests\n`url`    | `null` | string or RegExp url to match against request urls\n`response` | `null` | response body when stubbing routes\n`status` | `200` | response status code when stubbing routes\n`delay` | `0` | delay for stubbed responses (in ms)\n`headers` | `null` | response headers for stubbed routes\n`force404` | `false` | forcibly send XHR's to 404 status when these XHR's do not match any existing [`cy.routes`](https://on.cypress.io/api/routes)\n`onRequest` | `null` | callback function when a request is sent\n`onResponse` | `null` | callback function when a response is returned\n`onAbort` | `null` | callback function which fires anytime an XHR is aborted\n\nYou can also set options for all [cy.wait](https://on.cypress.io/api/wait) `requestTimeout` and `responseTimeout` globally in [configuration](https://on.cypress.io/guides/configuration) to control how long to wait for the request and response of the supplied route.\n\n***\n\n# Url Usage\n\n## Wait on non-stubbed XHR's by url\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"// by not passing a response to the route\\n// Cypress will pass this request through\\n// without stubbing it - but still allow\\n// us to wait for it later\\ncy\\n  .server()\\n  .route(/users/).as(\\\"getUsers\\\")\\n  .visit(\\\"/users\\\")\\n  .wait(\\\":::at:::getUsers\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n***\n\n# Method and Url Usage\n\n## Wait on non-stubbed XHR's by method + url\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"// by not passing a response to the route\\n// Cypress will pass this request through\\n// without stubbing it - but still allow\\n// us to wait for it later\\ncy\\n  .server()\\n  .route(\\\"POST\\\", /users/).as(\\\"postUser\\\")\\n  .visit(\\\"/users\\\")\\n  .get(\\\"#first-name\\\").type(\\\"Julius{enter}\\\")\\n  .wait(\\\"@postUser\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"[Check out our example recipe using cy.route to POST for login](https://github.com/cypress-io/cypress-example-recipes/blob/master/cypress/integration/logging_in_xhr_web_form_spec.js)\",\n  \"title\": \"Setup route to POST to login\"\n}\n[/block]\n\n***\n\n# Url and Response Usage\n\n## Url as a string\n\nWhen passing a `string` as the `url`, the XHR's URL must match exactly what you've written.\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .server()\\n  .route(\\\"/users\\\", [{id: 1, name: \\\"Pat\\\"}])\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n***\n\n## Url as a string glob\n\nAs of `0.16.3` we now accept glob patterns. Under the hood Cypress is using [minimatch](https://github.com/isaacs/minimatch) to match glob patterns with URL's.\n\nThis means you can take advantage of `*` and `**` support. This makes it **much** easier to route against dynamic segments without having to build up a complex `regex`.\n\nWe expose [`Cypress.minimatch`](https://on.cypress.io/api/cypress-minimatch) as a function which you can use in your Dev Tools console to test routes. You can iterate much faster on a working pattern than guessing at why something isn't working.\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"// match against any user id\\n// /users/123/comments     <-- matches\\n// /users/123/comments/465 <-- not matches\\ncy\\n  .server()\\n  .route(\\\"/users/*/comments\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"// use ** glob to match all segments\\n// /posts/1            <-- matches\\n// /posts/foo/bar/baz  <-- matches\\n// /posts/quuz?a=b&1=2 <-- matches\\ncy\\n  .server()\\n  .route(\\\"/posts/**\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n***\n\n## Override Url options\n\nWhen we check `glob` patterns with `minimatch` by default we use `{ matchBase: true}`.\n\nYou can override these options in `cy.server`.\n\nIf you'd like to permanently override these options you can do so by setting [`Cypress.Server.defaults(...)`](https://on.cypress.io/api/api-server).\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .server({\\n    urlMatchingOptions: { matchBase: false, dot: true }\\n  })\\n  .route(...)\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n***\n\n## Url as a RegExp\n\nWhen passing a RegExp as the `url`, the XHR's url will be tested against the regular expression and will apply if it passes.\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .server()\\n  .route(/users\\\\/\\\\d+/, {id: 1, name: \\\"Phoebe\\\"})\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"// Application Code\\n\\n$.get(\\\"/users/1337\\\", function(data){\\n  console.log(data) // => {id: 1, name: \\\"Phoebe\\\"}\\n})\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n***\n\n## Matching requests and routes\n\nAny request that matches the `method` and `url` of a route will be responded to based on the configuration of that route.\n\nIf a request doesn't match any route [it will automatically receive a 404](#notes). For instance given we have the following routes:\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .server()\\n  .route(/users/, [{id: 19, name: \\\"Laura\\\"}, {id: 20, name: \\\"Jamie\\\"}])\\n  .route(\\\"POST\\\", /messages/, {id: 123, message: \\\"Hi There!\\\"})\\n  .get(\\\"form\\\").submit()\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"// Application Code\\n\\n// when our form is submitted\\n$(\\\"form\\\").submit(function(){\\n  // send an AJAX to: GET /users\\n  $.get(\\\"/users\\\" )\\n\\n  // send an AJAX to: POST /messages\\n  $.post(\\\"/messages\\\", {some: \\\"data\\\"})\\n\\n  // send an AJAX to: GET /updates\\n  $.get(\\\"/updates\\\")\\n})\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n**The above application code will issue 3 AJAX requests:**\n\n1. The `GET /users` will match our 1st route and respond with a 200 status code and the array of users.\n2. The `POST /messages` will match our 2nd route and respond with a 200 status code with the message object.\n3. The `GET /updates` did not match any routes and its response automatically sent back a 404 status code with an empty response body.\n\n***\n\n## Matching origins and non origin URL's\n\nWhen Cypress matches up an outgoing XHR request to a `cy.route` it actually attempts to match it against both the fully qualified URL and then additionally without the URL's origin.\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy.route(\\\"/users/*\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\nThe following XHR's which were `xhr.open(...)` with these URLs would:\n\n**Match**\n- /users/1\n- http://localhost:2020/users/2\n- https://google.com/users/3\n\n**Not Match**\n- /users/4/foo\n- http://localhost:2020/users/5/foo\n\n***\n\n# Method, Url, and Response Usage\n\n## Specify the method\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .server()\\n\\n  // match all DELETE requests to \\\"/users\\\"\\n  // and respond with an empty JSON object\\n  .route(\\\"DELETE\\\", \\\"/users\\\", {})\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n***\n\n# Options Usage\n\n## Pass in an options object\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .server()\\n  .route({\\n    method: \\\"DELETE\\\",\\n    url: /user\\\\/\\\\d+/,\\n    status: 412,\\n    response: {\\n      rolesCount: 2\\n    },\\n    delay: 500,\\n    headers: {\\n      \\\"X-Token\\\": null\\n    },\\n    onRequest: function(xhr) {\\n      // do something with the\\n      // raw XHR object when the\\n      // request initially goes out\\n    },\\n    onResponse: function(xhr) {\\n      // do something with the\\n      // raw XHR object when the\\n      // response comes back\\n    }\\n  })\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n## Simulate a server redirect\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  // simulate the server returning 503 with\\n  // empty JSON response body\\n  .route({\\n    method: 'POST',\\n    url: '/login',\\n    response: {\\n      // simulate a redirect to another page\\n      redirect: '/error'\\n    }\\n  })\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"[Check out our example recipe using cy.route to simulate a 503 on POST to login](https://github.com/cypress-io/cypress-example-recipes/blob/master/cypress/integration/logging_in_xhr_web_form_spec.js)\",\n  \"title\": \"Setup route to error on POST to login\"\n}\n[/block]\n\n***\n\n## Use headers and fixtures for image route\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy.route({\\n  url: \\\"image.png\\\",\\n  response: \\\"fx:logo.png,binary\\\" // binary encoding\\n  headers: {\\n    \\\"content-type\\\": \\\"binary/octet-stream\\\" // set content-type headers\\n  }\\n})\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n***\n\n## Setting a delay for a specific route\n\nYou can optionally pass in a delay option which will cause a delay (in ms) to the response for matched requests. The example below will cause the response to be delayed by 3 secs.\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy.route({\\n  method: \\\"PATCH\\\",\\n  url: /activities\\\\/\\\\d+/,\\n  response: {},\\n  delay: 3000\\n})\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n***\n\n# Function Usage\n\n## Set the routing options by a callback function\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy.route(function(){\\n  // ...do some custom logic here..\\n\\n  // and return an appropriate routing object here\\n  return {\\n    method: \\\"POST\\\",\\n    url: \\\"/users/*/comments\\\",\\n    response: this.commentsFixture\\n  }\\n})\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n***\n\n## Functions which return promises are awaited\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy.route(function(){\\n  // a silly example of async return\\n  return new Cypress.Promise(function(resolve){\\n    // resolve this promise after 1 second\\n    setTimeout(function(){\\n      resolve({\\n        method: \\\"PUT\\\"\\n        url: \\\"/posts/**\\\"\\n        response: \\\"@postFixture\\\"\\n      })\\n    }, 1000)\\n  })\\n})\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n***\n\n# Notes\n\n## Understanding Stubbed vs Regular XHR's\n\nCypress indicates whether an XHR sent back a stubbed response vs actually going out to a server.\n\nXHR's that indicate `(XHR STUB)` in the Command Log have been stubbed and their response, status, headers, and delay have been controlled by your matching `cy.route`.\n\nXHR's that indicate `(XHR)` in the Command Log have not been stubbed and were passed directly through to a server.\n\n![screen shot 2015-12-21 at 7 03 57 pm](https://cloud.githubusercontent.com/assets/1268976/11944790/9b3fe2d8-a816-11e5-9e90-7405555d0c58.png)\n\nCypress also logs whether the XHR was stubbed or not to the console when you click on the command in the Command Log. It will indicate whether a request was stubbed, which url it matched or that it did not match any routes.\n\n![screen shot 2015-12-21 at 7 22 23 pm](https://cloud.githubusercontent.com/assets/1268976/11945010/0358123a-a819-11e5-9080-f4e0abf8aaa3.png)\n\nEven the `Initiator` is included, which is a stack trace to what caused the XHR to be sent.\n\n***\n\n## Requests that don't match a route\n\nYou can force routes that do not match a route to return 404:\n\nStatus | Body | Headers\n--- | --- | ---\n`404` | \"\" | `null`\n\nIf you'd like to enable this behavior you need to pass:\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy.server({force404: true})\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\nYou can [read more about this here.](https://on.cypress.io/api/server#prevent-sending-404s-to-unmatched-requests)\n\n***\n\n## Using Fixtures as Responses\n\nInstead of writing a response inline you can automatically connect a response with a fixture.\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .server()\\n  .route(/posts/, \\\"fixture:logo.png\\\").as(\\\"getLogo\\\")\\n  .route(/users/, \\\"fixture:users/all.json\\\").as(\\\"getUsers\\\")\\n  .route(/admin/, \\\"fixtures:users/admin.json\\\").as(\\\"getAdmin\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  // route after receiving the fixture and\\n  // working with the data\\n  .fixture(\\\"user\\\").then(function(user){\\n    user.firstName = \\\"Jennifer\\\"\\n\\n    // work with the users array here\\n    cy.route(\\\"GET\\\", \\\"user/123\\\", user)\\n  })\\n  .visit(\\\"/users\\\")\\n  .get(\\\".user\\\").should(\\\"include\\\", \\\"Jennifer\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\nYou can also reference fixtures as strings directly in the response\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"// we can link responses to fixtures simply\\n// by passing the fixture string with an '@'\\n// just like how you use aliases in\\n// cy.get(...) and cy.wait(...)\\ncy\\n  .fixture(\\\"user\\\").as(\\\"fxUser\\\")\\n  .route(\\\"POST\\\", \\\"/users/*\\\", \\\"@fxUser\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\nYou can [read more about fixtures here.](https://on.cypress.io/api/fixture)\n\n***\n\n## Using Response Functions\n\nYou can also use a function as a response which enables you to add logic surrounding the response.\n\nFunctions which return promises will automatically be awaited.\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"var commentsResponse = function(routeData){\\n  //routeData is a reference to the current route's information\\n\\n  return {\\n    data: someOtherFunction(routeData)\\n  }\\n}\\n\\ncy.route(\\\"POST\\\", \\\"/comments/**\\\", commentsResponse)\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\n***\n\n## Response Headers are automatically set\n\nBy default, Cypress will automatically set `Content-Type` and `Content-Length` based on what your `response body` looks like.\n\nIf you'd like to override this, explicitly pass in `headers` as an `object literal`.\n\n***\n\n# Command Log\n\n[block:code]\n{\n    \"codes\": [\n        {\n            \"code\": \"cy\\n  .server()\\n  .route(/accounts/).as(\\\"accountsGet\\\")\\n  .route(/company/, \\\"fixtures:company\\\").as(\\\"companyGet\\\")\\n  .route(/teams/,   \\\"fixtures:teams\\\").as(\\\"teamsGet\\\")\\n\",\n            \"language\": \"javascript\"\n        }\n    ]\n}\n[/block]\n\nWhenever you start a server and add routes, Cypress will display a new Instrument Log called **Routes**. It will list the routing table in the Instrument Log, including the `method`, `url`, `stubbed`, `alias` and number of matched requests:\n\n![screen shot 2015-12-21 at 7 04 41 pm](https://cloud.githubusercontent.com/assets/1268976/11944789/9b3f69b6-a816-11e5-8b8f-bf8a235cf700.png)\n\nWhen XHR's are made, Cypress will log them in the Command Log and indicate whether they matched a routing alias:\n\n![screen shot 2015-12-21 at 7 19 20 pm](https://cloud.githubusercontent.com/assets/1268976/11944892/ca762cf0-a817-11e5-8713-91ced4a36a8a.png)\n\nWhen clicking on `XHR Stub` within the Command Log, the console outputs the following:\n\n![screen shot 2015-12-21 at 7 22 23 pm copy](https://cloud.githubusercontent.com/assets/1268976/11944950/711af9e6-a818-11e5-86b6-d17554403355.png)\n\n***\n\n# Related\n\n- [Guide: Network Requests](https://on.cypress.io/guides/network-requests-xhr)\n- [Recipe: Loggin in - XHR Web Form](https://github.com/cypress-io/cypress-example-recipes/blob/master/cypress/integration/logging_in_xhr_web_form_spec.js)\n- [server](https://on.cypress.io/api/server)\n- [wait](https://on.cypress.io/api/wait)\n- [as](https://on.cypress.io/api/as)\n- [fixture](https://on.cypress.io/api/fixture)","excerpt":"Route responses to matching requests","slug":"route","type":"basic","title":"route"}

route

Route responses to matching requests

[block:callout] { "type": "info", "body": "[Read about Network Requests first.](https://on.cypress.io/guides/network-requests-xhr)", "title": "New to Cypress?" } [/block] Use `cy.route` to manage the behavior of network requests. | | | |--- | --- | | **Returns** | `null` | | **Timeout** | *cannot timeout* | *** # [cy.route( *url* )](#section-url-usage) Set a route matching the specific `url` which is not stubbed but can be waited on later. This will match `GET` request methods. *** # [cy.route( *url*, *response* )](#section-url-and-response-usage) Set a route matching the `url` stubbed with the supplied `response`. This will match `GET` request methods. *** # [cy.route( *method*, *url* )](#section-method-and-url-usage) Set a route matching the specific `method` and `url` which is not stubbed but can be waited on later. *** # [cy.route( *method*, *url*, *response* )](#section-method-url-and-response-usage) Set a route matching the `method` and `url` stubbed with the supplied `response`. *** # [cy.route( *function* )](#section-function-usage) Set a route by returning an object literal from your callback function. Functions which return a promise will automatically be awaited. *** # Options Pass in an options object to change the default behavior of `cy.route`. By default `cy.route` inherits its options from [`cy.server`](https://on.cypress.io/api/server). **[cy.route( *options* )](#options-usage)** Option | Default | Notes --- | --- | --- `method` | `GET` | method to match against requests `url` | `null` | string or RegExp url to match against request urls `response` | `null` | response body when stubbing routes `status` | `200` | response status code when stubbing routes `delay` | `0` | delay for stubbed responses (in ms) `headers` | `null` | response headers for stubbed routes `force404` | `false` | forcibly send XHR's to 404 status when these XHR's do not match any existing [`cy.routes`](https://on.cypress.io/api/routes) `onRequest` | `null` | callback function when a request is sent `onResponse` | `null` | callback function when a response is returned `onAbort` | `null` | callback function which fires anytime an XHR is aborted You can also set options for all [cy.wait](https://on.cypress.io/api/wait) `requestTimeout` and `responseTimeout` globally in [configuration](https://on.cypress.io/guides/configuration) to control how long to wait for the request and response of the supplied route. *** # Url Usage ## Wait on non-stubbed XHR's by url [block:code] { "codes": [ { "code": "// by not passing a response to the route\n// Cypress will pass this request through\n// without stubbing it - but still allow\n// us to wait for it later\ncy\n .server()\n .route(/users/).as(\"getUsers\")\n .visit(\"/users\")\n .wait(\"@getUsers\")\n", "language": "javascript" } ] } [/block] *** # Method and Url Usage ## Wait on non-stubbed XHR's by method + url [block:code] { "codes": [ { "code": "// by not passing a response to the route\n// Cypress will pass this request through\n// without stubbing it - but still allow\n// us to wait for it later\ncy\n .server()\n .route(\"POST\", /users/).as(\"postUser\")\n .visit(\"/users\")\n .get(\"#first-name\").type(\"Julius{enter}\")\n .wait(\"@postUser\")\n", "language": "javascript" } ] } [/block] [block:callout] { "type": "info", "body": "[Check out our example recipe using cy.route to POST for login](https://github.com/cypress-io/cypress-example-recipes/blob/master/cypress/integration/logging_in_xhr_web_form_spec.js)", "title": "Setup route to POST to login" } [/block] *** # Url and Response Usage ## Url as a string When passing a `string` as the `url`, the XHR's URL must match exactly what you've written. [block:code] { "codes": [ { "code": "cy\n .server()\n .route(\"/users\", [{id: 1, name: \"Pat\"}])\n", "language": "javascript" } ] } [/block] *** ## Url as a string glob As of `0.16.3` we now accept glob patterns. Under the hood Cypress is using [minimatch](https://github.com/isaacs/minimatch) to match glob patterns with URL's. This means you can take advantage of `*` and `**` support. This makes it **much** easier to route against dynamic segments without having to build up a complex `regex`. We expose [`Cypress.minimatch`](https://on.cypress.io/api/cypress-minimatch) as a function which you can use in your Dev Tools console to test routes. You can iterate much faster on a working pattern than guessing at why something isn't working. [block:code] { "codes": [ { "code": "// match against any user id\n// /users/123/comments <-- matches\n// /users/123/comments/465 <-- not matches\ncy\n .server()\n .route(\"/users/*/comments\")\n", "language": "javascript" } ] } [/block] [block:code] { "codes": [ { "code": "// use ** glob to match all segments\n// /posts/1 <-- matches\n// /posts/foo/bar/baz <-- matches\n// /posts/quuz?a=b&1=2 <-- matches\ncy\n .server()\n .route(\"/posts/**\")\n", "language": "javascript" } ] } [/block] *** ## Override Url options When we check `glob` patterns with `minimatch` by default we use `{ matchBase: true}`. You can override these options in `cy.server`. If you'd like to permanently override these options you can do so by setting [`Cypress.Server.defaults(...)`](https://on.cypress.io/api/api-server). [block:code] { "codes": [ { "code": "cy\n .server({\n urlMatchingOptions: { matchBase: false, dot: true }\n })\n .route(...)\n", "language": "javascript" } ] } [/block] *** ## Url as a RegExp When passing a RegExp as the `url`, the XHR's url will be tested against the regular expression and will apply if it passes. [block:code] { "codes": [ { "code": "cy\n .server()\n .route(/users\\/\\d+/, {id: 1, name: \"Phoebe\"})\n", "language": "javascript" } ] } [/block] [block:code] { "codes": [ { "code": "// Application Code\n\n$.get(\"/users/1337\", function(data){\n console.log(data) // => {id: 1, name: \"Phoebe\"}\n})\n", "language": "javascript" } ] } [/block] *** ## Matching requests and routes Any request that matches the `method` and `url` of a route will be responded to based on the configuration of that route. If a request doesn't match any route [it will automatically receive a 404](#notes). For instance given we have the following routes: [block:code] { "codes": [ { "code": "cy\n .server()\n .route(/users/, [{id: 19, name: \"Laura\"}, {id: 20, name: \"Jamie\"}])\n .route(\"POST\", /messages/, {id: 123, message: \"Hi There!\"})\n .get(\"form\").submit()\n", "language": "javascript" } ] } [/block] [block:code] { "codes": [ { "code": "// Application Code\n\n// when our form is submitted\n$(\"form\").submit(function(){\n // send an AJAX to: GET /users\n $.get(\"/users\" )\n\n // send an AJAX to: POST /messages\n $.post(\"/messages\", {some: \"data\"})\n\n // send an AJAX to: GET /updates\n $.get(\"/updates\")\n})\n", "language": "javascript" } ] } [/block] **The above application code will issue 3 AJAX requests:** 1. The `GET /users` will match our 1st route and respond with a 200 status code and the array of users. 2. The `POST /messages` will match our 2nd route and respond with a 200 status code with the message object. 3. The `GET /updates` did not match any routes and its response automatically sent back a 404 status code with an empty response body. *** ## Matching origins and non origin URL's When Cypress matches up an outgoing XHR request to a `cy.route` it actually attempts to match it against both the fully qualified URL and then additionally without the URL's origin. [block:code] { "codes": [ { "code": "cy.route(\"/users/*\")\n", "language": "javascript" } ] } [/block] The following XHR's which were `xhr.open(...)` with these URLs would: **Match** - /users/1 - http://localhost:2020/users/2 - https://google.com/users/3 **Not Match** - /users/4/foo - http://localhost:2020/users/5/foo *** # Method, Url, and Response Usage ## Specify the method [block:code] { "codes": [ { "code": "cy\n .server()\n\n // match all DELETE requests to \"/users\"\n // and respond with an empty JSON object\n .route(\"DELETE\", \"/users\", {})\n", "language": "javascript" } ] } [/block] *** # Options Usage ## Pass in an options object [block:code] { "codes": [ { "code": "cy\n .server()\n .route({\n method: \"DELETE\",\n url: /user\\/\\d+/,\n status: 412,\n response: {\n rolesCount: 2\n },\n delay: 500,\n headers: {\n \"X-Token\": null\n },\n onRequest: function(xhr) {\n // do something with the\n // raw XHR object when the\n // request initially goes out\n },\n onResponse: function(xhr) {\n // do something with the\n // raw XHR object when the\n // response comes back\n }\n })\n", "language": "javascript" } ] } [/block] ## Simulate a server redirect [block:code] { "codes": [ { "code": "cy\n // simulate the server returning 503 with\n // empty JSON response body\n .route({\n method: 'POST',\n url: '/login',\n response: {\n // simulate a redirect to another page\n redirect: '/error'\n }\n })\n", "language": "javascript" } ] } [/block] [block:callout] { "type": "info", "body": "[Check out our example recipe using cy.route to simulate a 503 on POST to login](https://github.com/cypress-io/cypress-example-recipes/blob/master/cypress/integration/logging_in_xhr_web_form_spec.js)", "title": "Setup route to error on POST to login" } [/block] *** ## Use headers and fixtures for image route [block:code] { "codes": [ { "code": "cy.route({\n url: \"image.png\",\n response: \"fx:logo.png,binary\" // binary encoding\n headers: {\n \"content-type\": \"binary/octet-stream\" // set content-type headers\n }\n})\n", "language": "javascript" } ] } [/block] *** ## Setting a delay for a specific route You can optionally pass in a delay option which will cause a delay (in ms) to the response for matched requests. The example below will cause the response to be delayed by 3 secs. [block:code] { "codes": [ { "code": "cy.route({\n method: \"PATCH\",\n url: /activities\\/\\d+/,\n response: {},\n delay: 3000\n})\n", "language": "javascript" } ] } [/block] *** # Function Usage ## Set the routing options by a callback function [block:code] { "codes": [ { "code": "cy.route(function(){\n // ...do some custom logic here..\n\n // and return an appropriate routing object here\n return {\n method: \"POST\",\n url: \"/users/*/comments\",\n response: this.commentsFixture\n }\n})\n", "language": "javascript" } ] } [/block] *** ## Functions which return promises are awaited [block:code] { "codes": [ { "code": "cy.route(function(){\n // a silly example of async return\n return new Cypress.Promise(function(resolve){\n // resolve this promise after 1 second\n setTimeout(function(){\n resolve({\n method: \"PUT\"\n url: \"/posts/**\"\n response: \"@postFixture\"\n })\n }, 1000)\n })\n})\n", "language": "javascript" } ] } [/block] *** # Notes ## Understanding Stubbed vs Regular XHR's Cypress indicates whether an XHR sent back a stubbed response vs actually going out to a server. XHR's that indicate `(XHR STUB)` in the Command Log have been stubbed and their response, status, headers, and delay have been controlled by your matching `cy.route`. XHR's that indicate `(XHR)` in the Command Log have not been stubbed and were passed directly through to a server. ![screen shot 2015-12-21 at 7 03 57 pm](https://cloud.githubusercontent.com/assets/1268976/11944790/9b3fe2d8-a816-11e5-9e90-7405555d0c58.png) Cypress also logs whether the XHR was stubbed or not to the console when you click on the command in the Command Log. It will indicate whether a request was stubbed, which url it matched or that it did not match any routes. ![screen shot 2015-12-21 at 7 22 23 pm](https://cloud.githubusercontent.com/assets/1268976/11945010/0358123a-a819-11e5-9080-f4e0abf8aaa3.png) Even the `Initiator` is included, which is a stack trace to what caused the XHR to be sent. *** ## Requests that don't match a route You can force routes that do not match a route to return 404: Status | Body | Headers --- | --- | --- `404` | "" | `null` If you'd like to enable this behavior you need to pass: [block:code] { "codes": [ { "code": "cy.server({force404: true})\n", "language": "javascript" } ] } [/block] You can [read more about this here.](https://on.cypress.io/api/server#prevent-sending-404s-to-unmatched-requests) *** ## Using Fixtures as Responses Instead of writing a response inline you can automatically connect a response with a fixture. [block:code] { "codes": [ { "code": "cy\n .server()\n .route(/posts/, \"fixture:logo.png\").as(\"getLogo\")\n .route(/users/, \"fixture:users/all.json\").as(\"getUsers\")\n .route(/admin/, \"fixtures:users/admin.json\").as(\"getAdmin\")\n", "language": "javascript" } ] } [/block] [block:code] { "codes": [ { "code": "cy\n // route after receiving the fixture and\n // working with the data\n .fixture(\"user\").then(function(user){\n user.firstName = \"Jennifer\"\n\n // work with the users array here\n cy.route(\"GET\", \"user/123\", user)\n })\n .visit(\"/users\")\n .get(\".user\").should(\"include\", \"Jennifer\")\n", "language": "javascript" } ] } [/block] You can also reference fixtures as strings directly in the response [block:code] { "codes": [ { "code": "// we can link responses to fixtures simply\n// by passing the fixture string with an '@'\n// just like how you use aliases in\n// cy.get(...) and cy.wait(...)\ncy\n .fixture(\"user\").as(\"fxUser\")\n .route(\"POST\", \"/users/*\", \"@fxUser\")\n", "language": "javascript" } ] } [/block] You can [read more about fixtures here.](https://on.cypress.io/api/fixture) *** ## Using Response Functions You can also use a function as a response which enables you to add logic surrounding the response. Functions which return promises will automatically be awaited. [block:code] { "codes": [ { "code": "var commentsResponse = function(routeData){\n //routeData is a reference to the current route's information\n\n return {\n data: someOtherFunction(routeData)\n }\n}\n\ncy.route(\"POST\", \"/comments/**\", commentsResponse)\n", "language": "javascript" } ] } [/block] *** ## Response Headers are automatically set By default, Cypress will automatically set `Content-Type` and `Content-Length` based on what your `response body` looks like. If you'd like to override this, explicitly pass in `headers` as an `object literal`. *** # Command Log [block:code] { "codes": [ { "code": "cy\n .server()\n .route(/accounts/).as(\"accountsGet\")\n .route(/company/, \"fixtures:company\").as(\"companyGet\")\n .route(/teams/, \"fixtures:teams\").as(\"teamsGet\")\n", "language": "javascript" } ] } [/block] Whenever you start a server and add routes, Cypress will display a new Instrument Log called **Routes**. It will list the routing table in the Instrument Log, including the `method`, `url`, `stubbed`, `alias` and number of matched requests: ![screen shot 2015-12-21 at 7 04 41 pm](https://cloud.githubusercontent.com/assets/1268976/11944789/9b3f69b6-a816-11e5-8b8f-bf8a235cf700.png) When XHR's are made, Cypress will log them in the Command Log and indicate whether they matched a routing alias: ![screen shot 2015-12-21 at 7 19 20 pm](https://cloud.githubusercontent.com/assets/1268976/11944892/ca762cf0-a817-11e5-8713-91ced4a36a8a.png) When clicking on `XHR Stub` within the Command Log, the console outputs the following: ![screen shot 2015-12-21 at 7 22 23 pm copy](https://cloud.githubusercontent.com/assets/1268976/11944950/711af9e6-a818-11e5-86b6-d17554403355.png) *** # Related - [Guide: Network Requests](https://on.cypress.io/guides/network-requests-xhr) - [Recipe: Loggin in - XHR Web Form](https://github.com/cypress-io/cypress-example-recipes/blob/master/cypress/integration/logging_in_xhr_web_form_spec.js) - [server](https://on.cypress.io/api/server) - [wait](https://on.cypress.io/api/wait) - [as](https://on.cypress.io/api/as) - [fixture](https://on.cypress.io/api/fixture)