简体   繁体   中英

Cypress, response body as BLOB instead of JSON, but JSON in chrome devtools

i've been struggling with this behaviour of Cypress that i do not understand and i need help.

When i set route and wait for the request i can see that the response body is in BLOB , when in chrome devtools response body arrives as JSON , so is in application. I have Content-type set to application/vnd.api+json . Cypress version 3.7.0. I also disabled Fetch because Cypress have problems with that Cypress documentation #wait

 cy.server();
 cy.route('POST', '**/services').as('postService');
 cy.get('[data-cy=AddServices_submit]').click();

 cy.wait('@postService').then((xhr) => {
     //xhr.response.body is BLOB
     //xhr.responseBody is BLOB
 })

Found similar question: Stackoverflow Similar question but this is not helpful for me.

Did any one had similar problems with response arriving as BLOB?

Any help would be great, if you need more information feel free to ask. Thanks

EDIT

I have a workaround to this problem if anyone needed one. But the problem Still occurs

cy.wait('@postService').then(async (xhr) => {
    const response = await new Response(xhr.responseBody).text();
    const jsonResponse = JSON.parse(response);
    // jsonResponse is real json
});

I got the same problem and it was solved by adding cypress fetch polyfill as here

If the link won't be available, I copy the content here:

In directory cypress/support/ in file hooks.js add this code:

// Cypress does not support listening to the fetch method
// Therefore, as a workaround we polyfill `fetch` with traditional XHR which
// are supported. See: https://github.com/cypress-io/cypress/issues/687
enableFetchWorkaround();

// private helpers
function enableFetchWorkaround() {
  let polyfill;

  before(() => {
    console.info('Load fetch XHR polyfill')
    cy.readFile('./cypress/support/polyfills/unfetch.umd.js').then((content) => {
      polyfill = content
    })
  });

  Cypress.on('window:before:load', (win) => {
    delete win.fetch;
    // since the application code does not ship with a polyfill
    // load a polyfilled "fetch" from the test
    win.eval(polyfill);
    win.fetch = win.unfetch;
  })
}

In directory cypress/support/ in file index.js import hooks.js

import './hooks'

In directory cypress/support/ add directory polyfills and add there file unfetch.umd.js with this code:

// cypress/support/polyfills/unfetch.umd.js

// Version: 4.1.0
// from: https://unpkg.com/unfetch/dist/unfetch.umd.js
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):e.unfetch=n()}(this,function(){return function(e,n){return n=n||{},new Promise(function(t,o){var r=new XMLHttpRequest,s=[],u=[],i={},f=function(){return{ok:2==(r.status/100|0),statusText:r.statusText,status:r.status,url:r.responseURL,text:function(){return Promise.resolve(r.responseText)},json:function(){return Promise.resolve(JSON.parse(r.responseText))},blob:function(){return Promise.resolve(new Blob([r.response]))},clone:f,headers:{keys:function(){return s},entries:function(){return u},get:function(e){return i[e.toLowerCase()]},has:function(e){return e.toLowerCase()in i}}}};for(var a in r.open(n.method||"get",e,!0),r.onload=function(){r.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm,function(e,n,t){s.push(n=n.toLowerCase()),u.push([n,t]),i[n]=i[n]?i[n]+","+t:t}),t(f())},r.onerror=o,r.withCredentials="include"==n.credentials,n.headers)r.setRequestHeader(a,n.headers[a]);r.send(n.body||null)})}});

So, it worked for me

Same problem here...

I manage to get the data as JSON when I use cy.request() but I can't when I use an alias with cy.wait()

Could you try this as a workaround ?

const setBodyAsJson = async (xhr) => ({ ...xhr, body: JSON.parse(String.fromCharCode.apply(null, new Uint8Array(await xhr.response.body.arrayBuffer()))) })

cy.server();
cy.route('POST', '**/services').as('postService');
cy.get('[data-cy=AddServices_submit]').click();

cy.wait('@postService').then(setBodyAsJson).then((res) => {
    // res should contain body as JSON
})

This does not explain why but in case your response.body is a Blob but responseBody is null , you can use this to read it:

        cy.wait('@postService', TIMEOUT)
        .its('response.body')
        .then(body => {
            return new Promise(done => {
                const reader = new FileReader();
                reader.onload = function() {
                    done(JSON.parse(this.result));
                };
                reader.readAsText(body);
            });
        })
        .then(object => {
            expect(typeof object).to.equal('object')
        });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM