Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to read the 'responseXML' property from 'XMLHttpRequest', responseType was 'text' #6630

Closed
craig-dae opened this issue Mar 3, 2020 · 16 comments
Labels
stage: needs information Not enough info to reproduce the issue

Comments

@craig-dae
Copy link

craig-dae commented Mar 3, 2020

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

@jennifer-shehane
Copy link
Member

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?

@jennifer-shehane jennifer-shehane added the stage: needs information Not enough info to reproduce the issue label Mar 4, 2020
@jennifer-shehane jennifer-shehane changed the title Documentation example for status code check does not work Failed to read the 'responseXML' property from 'XMLHttpRequest', responseType was 'text' Mar 4, 2020
@jennifer-shehane
Copy link
Member

Also, for the status code matching, you may be asking for something along the lines of either of these issues: #387 #521

@craig-dae
Copy link
Author

craig-dae commented Mar 4, 2020

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

@craig-dae
Copy link
Author

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!

@j-thebault
Copy link

j-thebault commented Mar 6, 2020

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

@craig-dae
Copy link
Author

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.

@harvitronix
Copy link

harvitronix commented Apr 2, 2020

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)

@jennifer-shehane
Copy link
Member

jennifer-shehane commented Apr 10, 2020

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?

@craig-dae
Copy link
Author

craig-dae commented Apr 10, 2020

@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

@villelahdenvuo
Copy link

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.

@Chofoteddy
Copy link

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 Cypress@4.7.0.

@craig-dae
Copy link
Author

craig-dae commented Jun 4, 2020

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)

@marracuene
Copy link

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.

@craig-dae
Copy link
Author

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);

@nodermatt
Copy link

This blog post still shows the old way to check a response status.

cy.get('@post').should('have.property', 'status', `201)

instead of

cy.get('@post').its('status').should('eq', 201)

I understand it might still be correct for the version that was out at the time the post was published. However, people (like me) using the latest version will stumble upon that post will encounter the error.

@flotwig
Copy link
Contributor

flotwig commented Dec 15, 2022

cy.route() was removed in Cypress 12.0.0, please try using cy.intercept() instead. Closing this issue since the relevant API has been deprecated and removed.

@flotwig flotwig closed this as not planned Won't fix, can't repro, duplicate, stale Dec 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stage: needs information Not enough info to reproduce the issue
Projects
None yet
Development

No branches or pull requests

9 participants