cypress: Cannot read property '_setRequestBody' of undefined

Current behavior:

Whenever visiting a page in which the XHR id is protected via Object.defineProperties, cypress throws the following error:

Cannot read property '_setRequestBody' of undefined 

The issue here is that the following code in packages/driver/src/cypress/server.js is trying to override the XHR id with a unique id

add (xhr, attrs = {}) {
    const id = _.uniqueId('xhr')

    _.extend(xhr, attrs)
    xhr.id = id
    xhrs[id] = xhr
    proxies[id] = $XHR.create(xhr)

    return proxies[id]
}

But since the id property is immutable in my environment and is referencing the value of another property, like so

Object.defineProperties(XMLHttpRequest.prototype, {
    "id": {
        get: function() {
            return XMLHttpRequest.prototype._id
        }
    }
})

The result is that the code is not being able to locate the proxy for the request, returning undefined instead, thus, causing the error

proxy._setRequestBody(requestBody)

Desired behavior:

I would expect to be able to parameterise the property I want to be considered as an ID, in a way that I would be able to tell cypress to override the property _id instead of id.

Test code to reproduce

Reproduction is available here https://github.com/fltonii/cypress-test-tiny

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 16 (5 by maintainers)

Most upvoted comments

Hi All, I am experiencing the same issue. The UI library by SAP (Fiori Launchpad based on SAPUI5) is overwriting the XHR Id, which unfortunatly makes it impossible to use cypress for end-to-end UI tests for SAP software. Is there any option to switch to a different attribute name?

See the following code-snipped of the Fiori Launchpad library (as Fiori Launchpad itself is under commercial license i can unfortunatly not provide a running example - but the issue should be pretty clear from the screenshot). grafik

Regards, Timo

This code has been there for quite a while, so I don’t think this was a recently introduced thing.

I can recreate this with the following code:

it("Sample error when XHR id is not available", () => {
  cy.server()
  cy.route("GET", "/api/myService").as("myService");
  cy.visit("https://cy-test-page.uc.r.appspot.com");
  cy.wait("@myService");
  cy.get("#response").should("equal", `{"working":true}`);
});

Hi all,

i was launching to same problem few days ago with SAP CF Launchpad service. Currently it was not possible to cross tests fiori ui5 applications inside launchpad service because SAP want to cap XHR object. So my best solution for this was to add this code to /support/e2e.ts

Cypress.on('test:before:run', () => {
  const server = (cy as any).state('server');
  const { defineProperty } = Object;

  const serverAdd = server.add.bind(server);
  server.add = (xhr: XMLHttpRequest, attrs = {}) => {
    defineProperty(xhr, 'id', {
      writable: true,
      configurable: true
    });

    defineProperty(xhr, '_setRequestBody', {});

    defineProperty(xhr, '_getXhr', {});

    return serverAdd(xhr, attrs);
  };
});

Maybe there is a better way to change XHR object with intercept command from Cypress, but i didnt found how that suppouse to work. So maybe that saves you some time finding workarround.

Thanks. I tinkered with cy.intercept() but being new to cypress I couldn’t get a solution working. Below is what ended up working in our support file. Seems a simple attribute name change suggested by @timostark would solve this but we can get by with this too:

Cypress.on('test:before:run', () => {
    const server = (cy as any).state('server');

    const myProxies = {};

    const origAdd = server.add;
    server.add = (xhr, attrs = {}) => {
        const myXhrId = Cypress._.uniqueId('xhr');
        xhr.myXhrId = myXhrId;
        const proxy = origAdd(xhr, attrs);
        myProxies[myXhrId] = proxy;
        return proxy;
    }

    const origGetProxyFor = server.getProxyFor;
    server.getProxyFor = (xhr) => {
        let proxy = tc(() => origGetProxyFor(xhr));
        if (!proxy) proxy = myProxies[xhr.myXhrId];
        return proxy;
    }
})