Cypress: Failed to read the 'responseXML' property from 'XMLHttpRequest', `responseType` was 'text'

Created on 3 Mar 2020  路  14Comments  路  Source: cypress-io/cypress

Example from docs produces error.

From https://docs.cypress.io/guides/guides/network-requests.html#Assertions

// spy on POST requests to /users endpoint
cy.route('POST', '/users').as('new-user')
// trigger network calls by manipulating web app's user interface, then
cy.wait('@new-user')
  .should('have.property', 'status', 201)

In my example, I used:

cy.wait('@create').should('have.property', 'status', 201);

Produces the following error:

InvalidStateError: Failed to read the 'responseXML' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'document' (was 'text').

The following example works:

cy.wait('@create').then(({ status }) =>
  assert(status === 201, 'status is 201'),
);

Desired behavior:

Would like the example from the documents to work.

Preferably, I'd like cy.wait(...) to fail by default if a 200 isn't returned, or to have a really easy way of adding our preferred status code to return. Something like cy.wait('@create', 201).

Versions

4.0.1

needs information

Most helpful comment

Hello

I had the same issue when upgrading cypress from 3.6.0 to 4.1.0.

Failing code was

cy.wait('@alias')
  .should('have.property', 'status', 200);

lead to the same error on response type.

Changing my code to :

cy.wait('@alias)
  .its('status')
  .should('eq', 200)

fixed the issue

All 14 comments

The example from the website works for a standard XHR request and should work in your case, so there's something amiss. The test below works for example.

it('route status', () => {
  cy.visit('https://example.cypress.io/commands/network-requests')
  cy.server()

  cy.route('GET', 'comments/*').as('getComment')

  cy.get('.network-btn').click()
  cy.wait('@getComment').its('status').should('eq', 200)
})

It appears it's saying the responseType of your XHR request is text. It's a bit weird that it's warning this is only accessible is responseType is '' or document because '' defaults to text.

  • Ideally, can you provide us a test that we can run that reproduces this?
  • If not, can you run the test and when you see the error - click on the yellow error with DevTools open. Please take a screenshot of the full stack trace there and share it with us. I'd like to see where this error is throwing from.
  • Any insight into the responseType of your XHR request or any other info on what is unique about this request?

Also, for the status code matching, you may be asking for something along the lines of either of these issues: https://github.com/cypress-io/cypress/issues/387 https://github.com/cypress-io/cypress/issues/521

Your example works:

    cy.wait('@create')
      .its('status')
      .should('eq', 201);

The example from the instructions did not.

This is the stack trace you're asking for.

Screen Shot 2020-03-04 at 12 01 43 PM

For my purposes, the example you gave me solves my problem, so I got what I needed out of this issue report. I recommend you include both examples in your documentation.

Thanks for the help!

Hello

I had the same issue when upgrading cypress from 3.6.0 to 4.1.0.

Failing code was

cy.wait('@alias')
  .should('have.property', 'status', 200);

lead to the same error on response type.

Changing my code to :

cy.wait('@alias)
  .its('status')
  .should('eq', 200)

fixed the issue

Interesting, so it sounds like it might be a bug in the behavior of .should('have.property', 'status', 200); that was introduced in version 4.

I like the new syntax better anyway, so I'm going to switch to it. But it seems like both syntaxes should work.

FWIW, I ran into this issue as well.

The offending line was:

cy.get('@alias').should('have.length', 1)

Changing it to this solved the problem:

cy.get('@alias').its('length').should('eq', 1)

I can't reproduce this in Cypress 4.3.0. I imagine it has something specific to do with the requested url.

it('route status', () => {
  cy.visit('https://example.cypress.io/commands/network-requests')
  cy.server()
  cy.route('GET', 'comments/*').as('getComment')
  cy.get('.network-btn').click()
  cy.wait('@getComment').should('have.property', 'status', 200)
})

Screen Shot 2020-04-10 at 4 12 29 PM

Can someone provide a route to be used here that can reproduce this?

The stack trace mentions the responseType of the URL. Can y'all provide the responseType of the route that is failing?

@jennifer-shehane I just reproduced it again on our app, but I'm running it locally and can't give you access to our public endpoints.

Do these headers help?

Response Headers
HTTP/1.1 201 Created
server: nginx/1.16.1
date: Fri, 10 Apr 2020 12:16:58 GMT
content-type: application/json
allow: GET, POST, HEAD, OPTIONS
x-djangoquerycount-count: 22
x-content-type-options: nosniff
Vary: Origin, Accept-Encoding
access-control-allow-credentials: true
access-control-allow-origin: http://localhost.localdomain:8080
Content-Encoding: gzip
Connection: keep-alive
Transfer-Encoding: chunked

I'm getting the same error, except that the responseType is blob. I don't care about the response content. I just want to check if the request has been made or not, but using should directly fails because it tries to resolve the response value.

Using the its trick mentioned above works since it won't try to resolve the resopnse body.

I'm getting the same error, in my case, we must modify the code in order to run the test cases that work before Cypress version 4.

@jennifer-shehane the code below can help to reproduce the error.

My alias definition:

cy.server()
cy.route('POST', '**/api/user').as('user')

Original code (works in Cypress 3):

cy.wait('@user').then(xhr => {
    expect(xhr).to.have.property('status').to.equal(201)
    expect(xhr.response.body).to.have.property('prop1')
    return xhr.response.body.id
})

Error screenshot

But if upgrade to Cypress 4, we must use "Destructuring Assignment" if we want to get working our test just as before:

cy.wait('@user').then(({ status, response }) => {
    expect(status).to.equal(201)
    expect(response.body).to.have.property('prop1')
    return response.body.id
})

Success screenshot

But, Why? I don't see any breaking change on CHANGELOG.

I have [email protected].

This made my life easier:

Cypress.Commands.add(
  'withStatus',
  {
    prevSubject: true,
  },
  (subject, status) => {
    return cy.wrap(subject).its('status').should('eq', status);
  },
);

Used like:
cy.wait('@get').withStatus(200)

Your example works:

    cy.wait('@create')
      .its('status')
      .should('eq', 201);

The example from the instructions did not.

Still getting this issue in 4.12.1. Using @jennifer-shehane 's alternative as cited above, works and it is just as readable.

Can I recommend:

Cypress.Commands.add(
  'withStatus',
  {
    prevSubject: true,
  },
  (subject, status) => {
    if (Array.isArray(subject)) {
      cy.wrap(subject).then((subjects) =>
        subjects.forEach((_subject) =>
          cy.wrap(_subject).its('status').should('eq', status),
        ),
      );
    } else {
      return cy.wrap(subject).its('status').should('eq', status);
    }
  },
);

This works for both a single value or an array of values. Used like:
cy.wait('@load).withStatus(200);
or
cy.wait(['@load1', '@load2']).withStatus(200);

Was this page helpful?
0 / 5 - 0 ratings

Related issues

weskor picture weskor  路  3Comments

zbigniewkalinowski picture zbigniewkalinowski  路  3Comments

rbung picture rbung  路  3Comments

EirikBirkeland picture EirikBirkeland  路  3Comments

brian-mann picture brian-mann  路  3Comments