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

implement `window.fetch` capturing/mocking #95

Open
terinjokes opened this Issue Jan 25, 2016 · 51 comments

Comments

@terinjokes
Copy link

terinjokes commented Jan 25, 2016

Many developers are migrating to window.fetch from XHRs due to the simplified async interface it exposes. I happen to be one of those developers.

Cypress should support window.fetch with similar abilities to those of XHRs: I should be able to query the request and response, wait on them, and mock with data and fixtures.

Cypress team edit

This feature will work seamlessly once Full network stubbing is implemented.

Workarounds

  • delete window.fetch before visiting the page to force your application to polyfill it on top of XHR. If the application does not include a polyfill, you can load one from your tests.
  • stub window.fetch directly in JavaScript

See these solutions in Stubbing window.fetch example recipe

@jennifer-shehane jennifer-shehane added this to the 0.17.0 milestone Jul 19, 2016

@brian-mann

This comment has been minimized.

Copy link
Member

brian-mann commented Aug 31, 2016

Per the 0.17.0 release at the very least window.fetch will actually work properly now.

It's on our radar to adding stubbing to these as well. We're a lot closer to being able to do it now.

@brian-mann brian-mann modified the milestones: 0.17.x, 0.17.0 Aug 31, 2016

@PhilippSpo

This comment has been minimized.

Copy link

PhilippSpo commented Nov 30, 2016

I would love to see this feature. I am very excited about stubbing. It will definitely solve a lot of problems when doing these tests. window.fetch is very widely used by now 👍

@thomas-huston-zocdoc

This comment has been minimized.

Copy link

thomas-huston-zocdoc commented Dec 7, 2016

My team would love this too! window.fetch is very commonly used in React applications now, so I'm sure other teams would appreciate this as well.

@nwehrle

This comment has been minimized.

Copy link

nwehrle commented Jan 16, 2017

Same here. We use fetch for it's simplicity in our react application. Until yet we use our own proxy that mocks the ajax requests, but your XHR approuch is much more readable.

@nwehrle

This comment has been minimized.

Copy link

nwehrle commented Jan 16, 2017

Maybe you could offer a way to use fetch outside the service-worker's context first and in a second phase you could add fetch in service-workers?

@jennifer-shehane jennifer-shehane removed this from the 0.17.x milestone Feb 3, 2017

@brian-mann

This comment has been minimized.

Copy link
Member

brian-mann commented Feb 11, 2017

There is now an example of using cy.stub to control window.fetch. It's not the same API as cy.route but it will work today!

We have a bunch of examples of it here: https://github.com/cypress-io/cypress-example-recipes#controlling-behavior-with-spies-stubs-and-clocks

@stigkj

This comment has been minimized.

Copy link

stigkj commented Feb 21, 2017

As not all browsers support window.fetch yet, I guess most use some form of polyfill for this. Then one could do something like this:

cy
  .visit('<some url>', {
    onBeforeLoad: (win) => {
      win.fetch = null
    }
  })

After doing this, the polyfill will just use XHR instead of fetch in the test, and one can use the normal Cypress's capturing/mocking tools. What do you think of this, @brian-mann?

@nwehrle

This comment has been minimized.

Copy link

nwehrle commented Feb 28, 2017

Thank you for the alternative approach. Will try that.
What is the state of the real implementation? https://github.com/cypress-io/cypress/projects/20

@mvandebunt

This comment has been minimized.

Copy link

mvandebunt commented Mar 6, 2017

@stigkj thx for the workaround/solution.
the solution in https://github.com/cypress-io/cypress-example-recipes#controlling-behavior-with-spies-stubs-and-clocks was working for several projects for me.
Now I need to test an app using redux-saga with yield call(POST, { url: '/api/login/users', options }); and there it is not working, your solution is working!

@mukaibot

This comment has been minimized.

Copy link

mukaibot commented Mar 28, 2017

@stigkj thanks for the work around, like @mvandebunt this has worked for me in Chromium 56 :)

I find this a bit easier than the spy approach. I'm looking forward to Cypress getting better support for window.fetch :)

@Graham42

This comment has been minimized.

Copy link
Contributor

Graham42 commented Nov 9, 2017

While people are waiting for this, As long as your app falls back to XHR (polyfill or other) you can use this in cypress/support/commands.js to use @stigkj 's solution across all tests

Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
  const opts = Object.assign({}, options, {
    onBeforeLoad: (window, ...args) => {
      window.fetch = null;
      if (options.onBeforeLoad) {
        return options.onBeforeLoad(window, ...args);
      }
    },
  });
  return originalFn(url, opts);
});
@brian-mann

This comment has been minimized.

Copy link
Member

brian-mann commented Nov 9, 2017

@Graham42 There is actually an easier way to do this and it will work not only for visits but all page transitions.

https://docs.cypress.io/api/events/catalog-of-events.html#Window-Before-Load

This event is called at the same time the onBeforeLoad callback is invoked.

You also won't have to overwrite the visit method

aduth added a commit to aduth/dones that referenced this issue Nov 19, 2017

Stub network handlers for e2e tests
Supported natively in Cypress, but not yet for window.fetch

See: cypress-io/cypress#95
@vschoettke

This comment has been minimized.

Copy link

vschoettke commented Nov 24, 2017

@Graham42 the overwrite of the visit command does not call onBeforeLoad for me (cypress 1.1.1) what version do you use?

@brian-mann

This comment has been minimized.

Copy link
Member

brian-mann commented Nov 24, 2017

@vschoettke Do not use the visit overwrite - use what I suggested in my comment here: #95 (comment)

There's nothing wrong per-se with overwriting visit but its unnecessary when you can use events which will apply to all page transitions.

@nmchaves

This comment has been minimized.

Copy link

nmchaves commented Nov 28, 2017

@brian-mann worked like a charm! I just put

// use `Cypress` instead of `cy` so this persists across all tests
Cypress.on("window:before:load", win => {
  win.fetch = null;
});

in support/index.js

@gnapse

This comment has been minimized.

Copy link

gnapse commented Nov 28, 2017

@nmchaves thanks! Your comment came just right in when I was about to ask if there was a way to make this global instead of inside the tests! You rock man!

@rkistinger

This comment has been minimized.

Copy link

rkistinger commented Dec 8, 2017

Thank you @nmchaves !! Make sure you are using the polyfill for this fallback behavior to work

@gnepud

This comment has been minimized.

Copy link

gnepud commented Dec 20, 2017

Thank your solution @nmchaves, but with it, i cant get response body by function xhr.responseJSON. Do you have same idea ?

@joyfulelement

This comment has been minimized.

Copy link

joyfulelement commented Dec 21, 2017

Has anyone successfully getting the network stub to work with fetch requests made via a page within an iframe?

@wheresrhys

This comment has been minimized.

Copy link

wheresrhys commented May 20, 2018

A solution I'm contemplating is, in test, injecting a polyfill.io script with fetch|always in the query string. This will always inject the fetch polyfill, built around XHR.

@rob-balfre

This comment has been minimized.

Copy link

rob-balfre commented May 30, 2018

Sorry to pile on but this just wasted hours of my time. Please state clearly in the docs you don't support fetch, especially on this page... https://docs.cypress.io/guides/guides/network-requests.html#

+1 this gets supported soon.

@wheresrhys

This comment has been minimized.

Copy link

wheresrhys commented May 31, 2018

Re my solution above #95 (comment), could cypress-io offer an option to inject such a script, fetchHack: true, - that way the docs would both highlight the problem and offer a one line solution.

IMHO such a complained about issue should not keep being pushed back to the next major release unless its arrival is imminent

@leegee

This comment has been minimized.

Copy link

leegee commented Jun 5, 2018

I loved cypress, but stopped using it because of this and the lack of support for anything non-Chromium.

Hope this changes.

@andreykovalenko

This comment has been minimized.

Copy link

andreykovalenko commented Aug 8, 2018

2 years later still the same :(

@Pavel-Husakouski

This comment has been minimized.

Copy link

Pavel-Husakouski commented Aug 23, 2018

@brian-mann @jennifer-shehane @bahmutov Folks, could you at least implement some workaroud or tell when it is going to be ready?

@ahx

This comment has been minimized.

Copy link

ahx commented Aug 23, 2018

@Pavel-Husakouski I am using cy.stub as done in the examples and it works fine today.

@bahmutov

This comment has been minimized.

Copy link
Collaborator

bahmutov commented Aug 23, 2018

@Pavel-Husakouski just like @ahx said this example stubs or polyfills window.fetch in several ways to get around XHR limitation

@Pavel-Husakouski

This comment has been minimized.

Copy link

Pavel-Husakouski commented Aug 23, 2018

I've found the problem. The wait method was skipping actual requests and I thought that workaround with polyfill was not working. Looks like the wait method should match the request. If the app made, say, five requests to the same route, the wait method should be called five times to match the order of calls.

@matystl

This comment has been minimized.

Copy link

matystl commented Oct 9, 2018

We got strange behavior in our test. we used method for deleting fetch in event "window:before:load" which solved it in chrome but was failing in CI. Testing in headless electron localy was failing with kind of random behaviour (2 same test one after another and second was failing, sometimes it passed randomly, different behaviour with --headed and headless). We solved it by deleting SW and now its working. I found after it that it's documented here known-issues but it would be helpful to mention it in first comment in this issue to save other people some time.

@rachelfreeman

This comment has been minimized.

Copy link

rachelfreeman commented Oct 12, 2018

Please add support for cy.route with windows.fetch!!

@timpur

This comment has been minimized.

Copy link

timpur commented Oct 28, 2018

Can I ask why cypress doesn't just use something like Polly.Js. I think Polly could add alot of functionality to cypress and support many interfaces like xhr and fetch...

@jennifer-shehane

@edouard-lopez

This comment has been minimized.

Copy link

edouard-lopez commented Nov 27, 2018

update (2018-nov-29): I switch to axios due to lack of fetch API support in Election/Cypres.


Encounter the same issue while using ky. Here is how I fixed it, thanks to @rkistinger's comment:

yarn add whatwg-fetch

Then in my application index.js:

import 'whatwg-fetch'; // required until cypress support fetch API

Then write the test as follow:

it('Searching reduce results', function() {
  cy.server();
  cy.route('**/vocabulaire.json', 'fixture:vocabulaire.json');

  cy.visit('/', {
    onBeforeLoad: win => {
      win.fetch = null;
    }
  });
  // whatever your test does
});

Refactor

Once this work you can move the onBeforeLoad in support/index.js as suggested by @nmchaves's comment:

Cypress.on('window:before:load', win => {
  win.fetch = null;
});

edouard-lopez added a commit to parlr/lsf that referenced this issue Nov 27, 2018

@chrisjcook

This comment has been minimized.

Copy link

chrisjcook commented Nov 27, 2018

@edouard-lopez this works great in the interim and it's nice and clean. Thanks!

@vctormb

This comment has been minimized.

Copy link

vctormb commented Dec 20, 2018

@edouard-lopez great solution! How are you testing multiple routes at the same time?

@edouard-lopez

This comment has been minimized.

Copy link

edouard-lopez commented Dec 21, 2018

@vctormb You can put the onBeforeLoad in support/index.js. You can see my project's code.

@vctormb

This comment has been minimized.

Copy link

vctormb commented Dec 21, 2018

@edouard-lopez yea, I've tested here and it works great, but the problem is when you use two routes or more at the same time, it won't work. I had to use other approach to handle multiple routes with GraphQL. Take a look at this one: cypress-io/cypress-documentation#122 (comment)

@rodoabad

This comment has been minimized.

Copy link

rodoabad commented Mar 8, 2019

Any update on this guys?

@MatteoGioioso

This comment has been minimized.

Copy link

MatteoGioioso commented Mar 11, 2019

Hello, any update?
Unfortunately none of the solutions proposed worked.
The actual request goes through successfully but cypress keep catching a wrong request.

I have an app that use Service Worker heavily, so I cannot use axios or any workaround in the long run.
So please support fetch 🙏

@ErikSeyferth

This comment has been minimized.

Copy link

ErikSeyferth commented Mar 14, 2019

Please provide us with an update regarding fetch.

@reno1979

This comment has been minimized.

Copy link

reno1979 commented Mar 18, 2019

We are switching to web workers, we could use the fetch support. Any progress?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.