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

Does not work when mocking window.fetch #151

Closed
luxzeitlos opened this issue Jul 11, 2019 · 7 comments · Fixed by #153
Closed

Does not work when mocking window.fetch #151

luxzeitlos opened this issue Jul 11, 2019 · 7 comments · Fixed by #153
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@luxzeitlos
Copy link
Contributor

This is very bad for testing.
when using ky tools like pretender can not work, because ky stores a reference to fetch immediatly after its loaded with const fetch = getGlobal('fetch');.

This means when a tool like pretender overwrites window.fetch for testing ky does not use the new window.fetch but the stored reference to the real fetch and so does a real request.

Is there a good reason to not call getGlobal('fetch') whenever fetch is required? (currently only here and here)

I'm willing to do a PR, but only if it will be merged.

@szmarczak szmarczak added enhancement New feature or request help wanted Extra attention is needed labels Jul 11, 2019
@szmarczak
Copy link
Collaborator

I'm willing to do a PR, but only if it will be merged.

You can do a PR only if you want to. Nobody says you have to. That would be cool. Rejected PRs don't make you look bad. The opposite, they make you look better because you showed some effort.

I mean it would be cool to see this in production.

@szmarczak szmarczak changed the title does not work with pretender.js Does not work when mocking window.fetch Jul 11, 2019
@sholladay
Copy link
Collaborator

We swap out the fetch implementation just fine in ky-universal and in our tests. You simply need to overwrite window.fetch before ky is loaded. That seems like a reasonable requirement to me, because it avoids any race condition issues or other bugs caused by the order in which you mock fetch and use ky. You have to get the environment ready ahead of time.

@szmarczak
Copy link
Collaborator

@sholladay What about putting these:

ky/index.js

Lines 24 to 30 in 2ea165a

const document = getGlobal('document');
const Headers = getGlobal('Headers');
const Response = getGlobal('Response');
const ReadableStream = getGlobal('ReadableStream');
const fetch = getGlobal('fetch');
const AbortController = getGlobal('AbortController');
const FormData = getGlobal('FormData');

into an object and exposing it via ky.globals?

@sholladay
Copy link
Collaborator

sholladay commented Jul 12, 2019

I think I'd rather put the getGlobal() calls inline, as suggested above, instead of having these globals as part of our public API surface, personally.

I'm curious to know why mocking fetch before Ky loads is not enough. It's definitely a safer way to do things.

@sindresorhus
Copy link
Owner

I agree with @sholladay. The convention is to mock before importing something.

@szmarczak
Copy link
Collaborator

That's one way to go. If we were using ky.globals, we wouldn't have to do

https://github.com/sindresorhus/ky-universal/blob/ddb2a6417724e7b3cf994061aa688962616b5bd5/index.js#L6-L28

but just pass an object with these values. Although I don't see anything wrong with the current solution.
I'll leave it up to you guys, I'm good with both solutions 😃

@luxzeitlos
Copy link
Contributor Author

We swap out the fetch implementation just fine in ky-universal and in our tests.

Thats not true. The tests of ky actually spin up a test server.

I agree with @sholladay. The convention is to mock before importing something.

I highly disagree!

This makes it almost impossible to write independent tests with tools like mocha qunit or testem. Users expect tools like pretender to just work there. This is very important when running browser-only tests.

So people want to do things like this:

let server;
hooks.beforeEach(function() {
  server = new Pretender();
});
hooks.afterEach(function() {
  server.shutdown();
});

some context:
I'm trying to integrate ky into ember-fetch-service. This should be a replacement for ember-ajax which uses jQuery. The ember community currently uses a lot ember-ajax and ember-fetch (which is basically just the fetch mock). However this lacks important features. So I have to think about two kind of tests:

  1. my own testsuite for ember-fetch-service
  2. tests by users of ember-fetch-service

The later is especially problematic. I don't think its a good idea that all apps should need to hook into the test loader (which loads the app and test tests, so I think its the only place to import something before the app is loaded, which then always will import ky, because thats the way import works) to test a single component using ky with ember-fetch-service.
Also this means we can not just teardown pretender and recreate it to reset the state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants