DEV Community

loading...

Fetch API gotcha in cypress.io and how to fix it.

Mat Silva
Figuring out how to improve life in terms of tech.
・2 min read

The problem:
When you use the fetch API on the client side, you cannot stub routes in cypress.io because of the lack in support in cypress atm.

This is something I ran into when implementing the graphql apollo-client apollo-link-rest, since it uses the fetch api out of the box.

Here is what I did to fix it:
First I made sure to polyfill the fetch api using whatwg-fetch, but only in development or testing environments, since I don't need it in production builds.

So in my the main entry point to my app index.tsx, I added this near the top.

//**this will get stripped out of production builds by webpack */
//@ts-ignore
if (!PRODUCTION) {
    require('whatwg-fetch'); //for polyfill cypress test 
}

For my webpack.development.js config file, I added this:


plugins: [
    new webpack.DefinePlugin({
        PRODUCTION: JSON.stringify(false),
    }),
],

and in my webpack.production.js config file, I added this:


plugins: [
    new webpack.DefinePlugin({
        PRODUCTION: JSON.stringify(true),
    }),
],

Next I added a new visitWithDelWinFetch command to cypress which will delete the fetch api on the window object.

Cypress.Commands.add('visitWithDelWinFetch', (path, opts = {}) => {
    cy.visit(
        path,
        Object.assign(opts, {
            onBeforeLoad(win) {
                delete win.fetch;
            },
        })
    );
});

This will kick in the fetch polyfill. Now you'll be able to stub routes like you'd expect in cypress.

cy.server();
cy.route('/path/to/api/').as('getApiPath');
cy.visitWithDelWinFetch('/');

And to give credit where it's due, this was largely inspired by this solution in the comments.

Also note that if you don't care about ever using the fetch api in your tests, you could avoid having a separate visit command using this solution paired with the fetch polyfill.

Discussion (2)

Collapse
shivasrini profile image
Shiva Srinivasan

How would you delete the fetch call when there is no visit happening but the fetch call is either a webhook or an event. For example we have a form page where new users type in their email. Once the email is typed in and the user has clicked on the next field in the form a fetch call is made to check if the email is already in use. How do I mock that? I cannot do cy.visit. What is the alternative? Thank you for your help and great article

Collapse
matsilva profile image
Mat Silva Author

No problem Shiva.

I suspect you are navigating to the form page somehow via cypress, what are you using to do that?