2

I'm trying to overwrite an existing command in Cypress.io. I'm looking to log() a route response's status & the route's url to extend the functionality of the built-in route(). Unfortunately, I get this message The route undefined had a undefined status code. in the console. Note, I'm using the browser's console momentarily. Eventually, I'll use the log() built-in method. This is what I have tried so far:

cypress/support/commands.js
Cypress.Commands.overwrite('route', (originalFn, response) => {
  console.log(`The route ${response.url} had a ${response.status} status code.`);

  return originalFn(response);
});

Update:

I'm getting the route now, but I still don't get response or status. This is my current code:

Cypress.Commands.overwrite('route', (originalFn, url, response) => {
  console.log(`The route ${url} had ${response} status code`);
  return originalFn(url, response);
});
Lola Ichingbola
  • 3,035
  • 3
  • 16
Manuel Abascal
  • 5,616
  • 5
  • 35
  • 68
  • What are you calling cy.route() with? Arguments for overwrite are (originalFn, ...arguments to original fn), so if you call cy.route('myUrl', {myResp: ''}), callback will be called with (originalFn, 'myUrl', {myResp: ""}) – Daniel May 13 '20 at 18:08
  • @Daniel Thanks for your reply, I am not sure that I follow your question. – Manuel Abascal May 13 '20 at 18:51

2 Answers2

7

When using the pattern cy.route(method, url, response), the response parameter is use to stub the call and return the supplied response to your app, see (route() - Arguments)

response (String, Object, Array)

Supply a response body to stub in the matching route.

Note that creating an overwrite of cy.route() will be hooking into the route configuration, not the capture of the route.

The pattern cy.route(options) has an onResponse option which can be used to console.log() the response, but cy.log() does not work there, probably because we invoke a command inside a command.

Cypress.log() can be used instead.

cy.route({
  url: 'http://example.com',
  method: 'GET',
  onResponse: (response => {
    const message = `The route '${response.url}' had a ${response.status} status code.`;
    const log = Cypress.log({
      displayName: 'Route debugging',
      message: message,
      consoleProps: () => {
        // return an object which will
        // print to dev tools console on click
        return {
          message: message,
        }
      }
    })
    log.finish();  // remove log spinner
  })
})

/*
  Command log output:

    ROUTE DEBUGGING
    The route 'http://example.com' had a 200 status code.

*/
Community
  • 1
  • 1
Richard Matsen
  • 20,671
  • 3
  • 43
  • 77
2

Depending on what you're trying to achieve, there are a couple of options. Richard's answer above describes one approach - I'll attempt to cover some others.

(Note: The Cypress documentation at https://docs.cypress.io/ probably will give you a better understanding than this answer. I'll try to link the relevant articles inline)

(You can skip ahead to the section on 'Inspecting Api Responses' if you don't care why your code isn't working)

What's happening in your code

Let's look at the example code from https://docs.cypress.io/api/commands/route.html#Examples

cy.server()
cy.route('**/users').as('getUsers')
cy.visit('/users')
cy.wait('@getUsers')

Without your overwrite, cy.route here just registers the route, so you can wait for it later (Remember, cy.route does not make any api calls itself). With your overwrite, cy.route is completely replaced with your callback:

Cypress.Commands.overwrite('route', (originalFn, url, response) => {
  console.log(`The route ${url} had ${response} status code`);
  return originalFn(url, response);
});

So when cy.route('**/users') is called, it will instead evaluate

(originalFn, url, response) => {
  console.log(`The route ${url} had ${response} status code`); // Logs "The route **/users had undefined status code"
  return originalFn(url, response); // Registers the route with an mock value of undefined
})(originalCypressRouteFn, '**/users')

You can see why response is undefined - it's not passed in to the route call at all, since the request hasn't even been made.

Note that if we were attempting to mock the call instead (See https://docs.cypress.io/api/commands/route.html#With-Stubbing)

cy.route('https://localhost:7777/surveys/customer?email=john@doe.com', [
  {
    id: 1,
    name: 'john'
  }
])

You would instead log

"The route https://localhost:7777/surveys/customer?email=john@doe.com had [object Object] status code"

Inspecting Api Responses

If you just want to inspect the response from an api, you can use the using the built-in debugging tools (after calling cypress open). The browser's Network tab is available (which will record all requests made during a given test run), and you can additionally click on the response recorded in the left panel, which will log the request and response to the browser console.

If you're attempting to assert on the response to an api call, you can use cy.wait (See https://docs.cypress.io/guides/guides/network-requests.html#Waiting) to get access to the underlying xhr request after it finishes:

cy.wait('@apiCheck').then((xhr) => {
  assert.isNotNull(xhr.response.body.data, '1st API call has data')
})

If you want a record of the APIs calls made during a CLI run (using cypress run), you can:

  1. Print debug info, which will give you a lot of information, including all requests and responses (See https://docs.cypress.io/guides/references/troubleshooting.html#Print-DEBUG-logs): DEBUG=cypress:* cypress run (You can change cypress:* to limit the scope of the debug to just api calls, though I don't know off the top of my head what the namespace you'll want is)
  2. Use a plugin that records all requests (e.g. https://github.com/NeuraLegion/cypress-har-generator)
Daniel
  • 1,079
  • 1
  • 11
  • 25