volk
volk

Reputation: 842

cypress onRequest handler fails if any cy. method used inside

Basically, my task is next: when my app triggers outgoing xhr request I want to make some assertions on the request payload, and continue with other assertions, once the request is fulfilled. So what i did is used onRequest option on cy.route method which lets you have access to outgoing xhr request. My initial code looked like this:

cy.server();
cy.route({
  method:'POST',
  url:'/api/v3/table-metas/**',
  onRequest(xhr) {
    console.log('==========BEFORE========');
    cy.wrap(xhr).
    its('request').
    its('body').
    its('embedded').
    should('to.deep.equal',
      [
        {
          "attributes": {
            "name": "Test Name"
          },
          "type": "test_type"
        }
      ]
    ).debug();
    console.log('=============AFTER===========');
 }
}).as('getTableMetas');

But this code make my app think that request failed, and in cypress log it was showing me that request was pending until it failed with timeout. Then I decided to remove my assertion, and everything works fine!:

cy.server();
cy.route({
  method:'POST',
  url:'/api/v3/table-metas/**',
  onRequest(xhr) {
    console.log('==========BEFORE========');
    console.log('=============AFTER===========');
 }
}).as('getTableMetas');

Thus, I decided that the problem is in my assertion code, and did some testing with other cy methods, but it seems that any cy. method leads to exactly the same failure:

cy.server();
cy.route({
  method:'POST',
  url:'/api/v3/table-metas/**',
  onRequest(xhr) {
    console.log('==========BEFORE========');
    cy.log('AAAAAAAAAAAA');
    console.log('=============AFTER===========');
 }
}).as('getTableMetas');

Here is the screenshot of cypress log for the last part of code: enter image description here

What am I doing wrong here? If it is designed behavior of cypress, then how am I supposed to assert outgoing request body?

Would be grateful for any kind of help

Upvotes: 2

Views: 1214

Answers (1)

Oluwafemi Sule
Oluwafemi Sule

Reputation: 38922

When given an alias argument:

cy.wait() yields an object containing the HTTP request and response properties of the XHR. Source

A property getter can be chained to the yielded object from calling the waits method. e.g.

it('verifies request body', () => {
  cy.server();
  cy.route({
    method:'POST',
    url:'/api/v3/table-metas/**',
    onRequest(xhr) {
      console.log('==========BEFORE========');
      console.log('=============AFTER===========');
   }
  }).as('getTableMetas');
  
  // do some action that makes a request to the intercepted request

  cy.waits('@getTableMetas')
    .its('request.body.embedded')
    .should('to.deep.equal', [
      {
        "attributes": {
          "name": "Test Name"
        },
        "type": "test_type"
      }
    ]).debug();
});

Update:

onRequest is executed as a callback, calling cy.wraps creates a promise during the execution that is never resolved.

I suggest to use normal chai assertions in onRequest callback instead as they are synchronous.

expect(xhr.request.body.embedded).to.deep.equal([
        {
          "attributes": {
            "name": "Test Name"
          },
          "type": "test_type"
        }
      ]) 

Upvotes: 1

Related Questions