Giter Site home page Giter Site logo

wheresrhys / fetch-mock Goto Github PK

View Code? Open in Web Editor NEW
1.2K 1.2K 169.0 4.86 MB

Mock http requests made using fetch

Home Page: http://www.wheresrhys.co.uk/fetch-mock/

License: MIT License

JavaScript 95.58% Makefile 0.92% Ruby 0.08% TypeScript 3.42%

fetch-mock's People

Contributors

adam-nielsen avatar arcanis avatar ayzagen avatar benjamingr avatar birtles avatar caiopo avatar carlosescri avatar chet-manley avatar danny-andrews avatar dependabot[bot] avatar dmatteo avatar edmorley avatar evan-10e avatar grug avatar halt001 avatar ivansanchez avatar jackfranklin avatar leafrogers avatar leggsimon avatar lodrantl avatar m90 avatar mattisg avatar nynkelys avatar pimterry avatar protip avatar timnew avatar tregusti avatar vbauerster avatar wheresrhys avatar zoe7 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fetch-mock's Issues

Not matching when fetch is called with a Request object

The normalizeRequest() function in fetch-mock.js is supposed to check if it is called with a URL string or a Request object. This is failing, and falling back to the string case when fetch() is invoked with a Request object.

Here's an example:

let req = new Request('http://www.example.com', { method: 'GET' });
let p = fetch(req);

The following implementation works for me, but may be too simplistic of a fix:

function normalizeRequest (url, options) {
    if (typeof url === 'string') {
        return {
            url: url,
            method: options && options.method || 'GET'
        };
    } else {
        return {
            url: url.url,
            method: url.method
        };
    }
}

In Chrome realFetch throws Illegal invocation error.

I am actually unable to get anything to work as Chrome throws Illegal Invocation error. At the following line:

return this.realFetch(url, opts);

I'm assuming it's a binding context issue similar to this: typicode/fetchival#1

Or quite possibly I'm not using the library correctly.

I'm just using a basic example and I get the error:

import fetchMock from 'fetch-mock'
fetchMock.mock('http://www.example.com', 200);

Add a changelog

I'm in the process of updating the fetch-mock and our tests broke from the jump from 2.2.8 to 2.2.9. Could you please consider introducing a changelog to ease the pain of upgrades.

Does fetch-mock adhere to semver? I'm surprised things broke on a patch update.

debug

var debug = require('debug')('fetch-mock');

Support bower

bower install fetch-mock can install fetch-mock now, but it is not the build version, not generated folder es5.

Chainable mocking

Can probably stop calls to mock, when already mocked, throwing an error without a major release

Support ".json()" method?

Are there plans to support node-fetch's .json() method? If not, is there a workaround I'm missing?

delay responses

Is there any way to delay a response for a certain amount of time?

leverage 'browser' key in package.json

Hello!

Thanks for putting together this handy package!

One thing I'd like to be able to do is run tests in node as well as in the browser without having separate import/require statements (require('fetch-mock') vs require('fetch-mock/src/server')).

Have you considered leveraging the browser key in package.json?

Something like this should do it:

"main": "src/server.js",
"browser": "es5/client.js"

This should allow require('fetch-mock') to work for both browser and server (well, at least node v4 ๐Ÿ˜„)

Have you explored this at all?

Add support (fix bug) for functions returning a Promise

I tried to mock server delays and I needed a Promise to be created at a time when a request is made to a mocked url, not at a time when we define how to mock a response.
The current implementation does not currently handle a case when the response is mocked as a function returning a Promise. To fix it for my needs I added one line to fetchMock function, like this:

fetchMock (url, opts) {
    const response = this.router(url, opts);
    if (typeof response === 'function')  response = response(url, opts);  // <-- the new line

It moves evaluating the "mocking function" from mockResponse to fetchMock because fetchMock has proper logic (using "response.then") for Promises.

ES6 code in npm

npm package (2.1.0) contains not transpiled ES6 code which cases an error for me:

> [email protected] mocha:base /Users/sapegin/izumi/kao
> mocha --compilers js:babel/register --require mochasetup "./test"

/Users/sapegin/izumi/kao/node_modules/fetch-mock/server.js:3
const Response = require('node-fetch').Response;
^^^^^
SyntaxError: Use of const in strict mode.
    at exports.runInThisContext (vm.js:73:16)
    at Module._compile (module.js:443:25)
    at Module._extensions..js (module.js:478:10)
    at Object.require.extensions.(anonymous function) [as .js] (/Users/sapegin/izumi/kao/node_modules/babel-core/lib/api/register/node.js:214:7)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/Users/sapegin/izumi/kao/mochasetup.js:6:31)
    at Module._compile (module.js:460:26)
    at normalLoader (/Users/sapegin/izumi/kao/node_modules/babel-core/lib/api/register/node.js:199:5)
    at Object.require.extensions.(anonymous function) [as .js] (/Users/sapegin/izumi/kao/node_modules/babel-core/lib/api/register/node.js:216:7)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at /Users/sapegin/izumi/kao/node_modules/mocha/bin/_mocha:304:3
    at Array.forEach (native)
    at Object.<anonymous> (/Users/sapegin/izumi/kao/node_modules/mocha/bin/_mocha:303:10)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3
node v0.12.7
npm  v3.3.6

Version number question

File this under random question:

Noticed that the version numbers are incrementing without any actual code changes, is there a reason for that? With semantic versioning they should increase based on functionality changes rather than documentation, am I missing something?

Unable to use with Webpack

Because Sinon does not really work well with Webpack, using Karma-webpack with this lib will produce error on load. In order to make karma-webpack work with Sinon, plugin with karma-sinon is always required. I think this lib can be provided as a Karma plugin.

edit: I did not notice there was browserify instruction. But requiring fetch-mock/client does not work either.

FetchMock.getMock seems always undefined as of 4.0.0

I am using FetchMock with Mockery as Node 4 module, hence I need to get a handle on the mocked fetch() function.

Registering the node-fetch mock with myMock.getMock() as shown below leads to an undefined fetch function in the code under test.

'use strict';

var fetchMock = require('fetch-mock');
var mockery = require('mockery');

describe('fetch mockery', function () {

  beforeEach(function () {
    mockery.enable({useCleanCache: true});
    var myMock = fetchMock
      .mock('http://auth.service.com/user', '{"foo": 1}');
    mockery.registerMock('node-fetch', myMock.getMock());        <-- undefined
  });

  afterEach(function () {
    fetchMock.restore();
    mockery.deregisterMock('node-fetch');
    mockery.disable();
  });

  it('should mock a request', function () {

    var goFetch = require('../lib/fetchsample'); // just a call to fetch in a separate module

    return goFetch('http://auth.service.com/user').then(function (response) {
      return response.json();
    }).then(function (json) {
      console.log(json);
    });
  });

});

As a workaround, the necessary fetch function mock is availabe as myMock.mockedContext.fetch:

mockery.registerMock('node-fetch', myMock.mockedContext.fetch);

Maybe the fix would be to change getMock() in fetch-mock.js like so:

    /**
     * getMock
     * Returns a reference to the stub function used to mock fetch
     * @return {Function}
     */
    getMock () {
        return this.mockedContext.fetch;
    }

Or am I using fetch-mock incorrectly here?

Response status 204

Thank you for your lib! I tried to mock 204 status, but got the error:

Uncaught (in promise) TypeError: Failed to construct 'Response': Response with null body status cannot have body
    at TypeError (native)
    at mockResponse ...

with that line return _Promise.resolve(new Response(body, opts));
I suppose it couldn't mock 204 status as far as it hasn't response body.
I have the following routes:

fetchMock.mock({
    routes: [{
      name: 'route3',
      method: 'DELETE',
      matcher: 'path/to/my/api',
      response: 204,
    }]
});

Should I change the response config? Thanks in advance!

Asynchronous resolve

It would be handy to be able to specify an asynchronous resolve for the mock response for dealing with testing cancellation and other potential race conditions in an application.

This could be done by response accepting a promise.

Cannot mock relative URLs in v3.0.4

As of v3.0.4, mocking a relative URL results in an Error being thrown from the dependency module node-fetch:

Error: only absolute urls are supported
    at new Request (node_modules/fetch-mock/node_modules/node-fetch/lib/request.js:34:9)
    at toRequest (node_modules/fetch-mock/src/fetch-mock.js:65:13)
    at Object.route.matcher (node_modules/fetch-mock/src/fetch-mock.js:111:15)
    at node_modules/fetch-mock/src/fetch-mock.js:233:15
    at Array.some (native)
    at routes.forEach.routes.forEach.routes.some (node_modules/fetch-mock/src/fetch-mock.js:231:11)
    at mock (node_modules/fetch-mock/src/fetch-mock.js:329:21)
    ....

In my use case, I am writing tests for a Redux application which uses fetch to grab some i18n data defined in a JSON file. The code I am testing looks like this:

fetch(`public/i18n/${locale}.json`)
  .then(/* ...snip... */)

The tests are written in mocha and are executed through Node.js, so I use isomorphic-fetch assigned to the global object inside the test, to fill in for the browser's fetch function, and use fetch-mock to mock the response:

import fetchMock from 'fetch-mock'
import fetch from 'isomorphic-fetch'

global.fetch = fetch
/* ...snip... */
fetchMock.mock(`public/i18n/${locale}.json`, { /* fixture i18n data */ })

This code worked fine in v3.0.3 as fetch-mock wasn't using Request from node-fetch, which sets the absolute URL limitation (LIMITS.md in node-fetch repository).

Related issue in node-fetch: node-fetch/node-fetch#43

Unable to mock when using isomorphic-fetch

Here is a minimal repo to reproduce the issue (there is an npm test task). I just can't intercept the request. The example is almost the same as the first one from README. Here is the karma ouput:

START:
Hash: 8344a6c0a9b3c44a5636
Version: webpack 1.12.9
Time: 10ms
webpack: bundle is now VALID.
webpack: bundle is now INVALID.
Hash: 205e381c2cff60ba2ea2
Version: webpack 1.12.9
Time: 431ms
         Asset    Size  Chunks             Chunk Names
tests/index.js  164 kB       0  [emitted]  tests/index.js
chunk    {0} tests/index.js (tests/index.js) 57.8 kB [rendered]
    [0] ./tests/index.js 398 bytes {0} [built]
    [1] ./tests/framework/fetch.test.js 611 bytes {0} [optional] [built]
    [2] ./tests/framework/plugins.test.js 559 bytes {0} [optional] [built]
    [3] ./~/es6-promise/dist/es6-promise.js 32.3 kB {0} [built]
    [4] ./~/fetch-mock/es5/client.js 215 bytes {0} [built]
    [5] ./~/fetch-mock/es5/fetch-mock.js 10.8 kB {0} [built]
    [6] ./~/isomorphic-fetch/fetch-npm-browserify.js 233 bytes {0} [built]
    [7] ./~/process/browser.js 2.06 kB {0} [built]
    [8] (webpack)/buildin/amd-define.js 85 bytes {0} [built]
    [9] (webpack)/buildin/module.js 251 bytes {0} [built]
   [10] ./~/whatwg-fetch/fetch.js 9.93 kB {0} [built]
   [11] ./src ^.+\.jsx?$ 160 bytes {0} [built]
   [12] ./tests .+\.test\.jsx?$ 222 bytes {0} [built]
   [13] vertx (ignored) 15 bytes {0} [optional]
webpack: bundle is now VALID.
09 12 2015 00:08:05.365:INFO [karma]: Karma v0.13.15 server started at http://localhost:9876/
09 12 2015 00:08:05.371:INFO [launcher]: Starting browser PhantomJS
09 12 2015 00:08:07.449:INFO [PhantomJS 1.9.8 (Mac OS X 0.0.0)]: Connected on socket l6IlGACQCBhgBzfKAAAA with id 12541479
  fetch-mock
    โœ– mocks simplest http get request (slow: 2.002 secs)
  karma plugins
    โœ” exposes "expect" globally
    โœ” exposes "should" globally
    โœ” has chai-as-promised helpers

Finished in 2.031 secs / 2.005 secs

SUMMARY:
โœ” 3 tests completed
โš  1 test slow
โœ– 1 test failed

FAILED TESTS:
  fetch-mock
    โœ– mocks simplest http get request (slow: 2.002 secs)
      PhantomJS 1.9.8 (Mac OS X 0.0.0)
    timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

npm ERR! Test failed.  See above for more details.

Mockery doesn't work as expected

I setup the mockery and fetch-mock as following code:

import mockery from 'mockery'
import fetch from 'node-fetch'
import fetchMock from 'fetch-mock'
import MyModule from './MyModule'

fetchMock.useNonGlobalFetch(fetch)
// ...
    beforeEach(() => {
      mockery.enable({ useCleanCache: true })
      mockery.registerMock('node-fetch', fetchMock.mock(pattern, 'POST', 200).getMock())
    })

    afterEach(() => {
      mockery.deregisterMock('node-fetch')
      mockery.disable()
    })

And during the test, I found the request doesn't get mocked as expected, all request hit the real server and fetchMock.called() returns false

Did I missed something or what should I do?!?!

TypeError: undefined is not an object (evaluating 'Request.prototype')

I have a strange error happening in 1.9 PhantomJS and latest Safari environments

TypeError: undefined is not an object (evaluating 'Request.prototype')

pointing me to

if (Request.prototype.isPrototypeOf(url)) {

I use it in my test like this

import fetchMock from 'fetch-mock'
//...
fetchMock.mock('http://my.api.url/v1/example', [{ ... }])

In Chrome, Firefox everything seems to work well.
Why could it happen and are there any advices how to debug it properly?

Cannot use in non-browserified client environment

The following statement on the README is not accurate:

Environment doesn't support requiring fetch-mock?

If your client-side code or tests do not use a loader that respects the browser field of package.json use require('fetch-mock/es5/client'). This can also be loaded directly in a script tag as ./node_modules/fetch-mock/es5/client.js (Disclaimer: I haven't actually tried this, but it should work)

es5/client.js is just a babel compiled version of src/client.js, which still attempts to use require. We need another folder (perhaps browser/) that contains a browserify-compiled version of src/client.js.

No License?

Like the library. Can you add LICENSE? MIT preferably...

Thanks

`.getMock()` returns undefined

Using browserify + fetch-mock, attempts to get a reference to the mock via .getMock() always seems to return undefined.

A glance at the code indicates that getMock just returns this.fetch which doesn't seem to be set anywhere.

Running Test Outside Browser Transpiled with Webpack Fails

Hi,

I'm trying to use fetch-mock in my mocha tess. The tests are put through webpack and then run via the mocha command in terminal. When I do this however, I get the following error related to requiring fetch-mock:

/built/bundle.js:8147
        theGlobal: window,
                   ^

ReferenceError: window is not defined
    at Object.i (/Users/fabioberger/Projects/js/dali-client/tests/built/bundle.js:8147:14)

It seems that window is not defined when running the webpack generated bundle.js outside of the browser. Is there a work around to this?

Thanks!

Karma browser testing issue

I am able to get fetch-mock to work great with jsdom by using global.fetch = require('node-fetch');, but unable to get it to work with Karma/PhantomJS/Chrome. I am sure there is something small I am missing (hopefully).

Here is the error I am getting:

PhantomJS 2.1.1 (Mac OS X 0.0.0)
Chrome 49.0.2623 (Mac OS X 10.11.3)
Error: Not Found
at /Users/chris/github/frontend/tests.webpack.js:65225:22 <- webpack:///src/pages/actions.js:49:20

karma.js:

...
      plugins: [
        // https://gist.github.com/Couto/b29676dd1ab8714a818f#gistcomment-1584602
        new webpack.ProvidePlugin({
          fetch: 'exports?self.fetch!whatwg-fetch',
        }),
...

test.js:

...
      afterEach(() => {
        fetchMock.restore();
      });

      it('create - success', function () {
        fetchMock.mock('/api/v1/new', {
          status: 200,
          body: { responseCode: 100 },
        });...
...
    fetch('/api/v1/new', {
      method: 'post',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(request),
...

If you have any thoughts please let me know.

API to search through calls using matcher syntax

This is one of the two related issues that led me to submit #83.

I propose an API that applies a matcher (string|RegExp|function(url, opts)) to the whole list of calls, regardless of any configured routes or their names. I consider this behavior useful in composing assertions that aren't possible with calls(routeName) or called(routeName), such as:

// Assuming a new method: fetchMock.testCalls
fetchMock.mock('^http://example.com/');
fetch('http://example.com/?arg1=123').then(() => {
  // called() would return false for each of the following
  fetchMock.testCalls('http://example.com/?arg1=123'); // true
  fetchMock.testCalls('^http://example.com/?arg1='); // true
  fetchMock.testCalls(/arg1=\d+$/); // true
});

So basically, it would do what I had the impression called() and calls() should do, as described in #87.
#83 contains a proposed implementation in the form of callsMatching() and calledMatching() filterCalls() and testCalls().

Support calling a route n times

I want to mock multiple calls to the same route - e.g.

fetchMock.mock('http://test.com', 500)
  .mock('http://test.com', {valid: 'response', after: 'error'}
  .getMock()

// code that calls a url multiple times depending on the response

Right now, the first defined route that matches always answers. Any way around that?

Remove requirement to name routes

Can make mocking multiple routes more onerous to set up, so would like to fallback to use matcher.toString() as the route name. If the user wants to access a particular route's calls they can specify a name for it as a convenience

calls() should probably always return an array of all fetch-mock calls in order, but this would be a breaking change.New method allCalls()/orderedCalls()? Or v3?

Behavior of called(matcher) and others may be confusing

This is one of the two related issues that led me to submit #83 (the other is #88).

calls, called, lastCall, lastUrl. lastOptions are all documented as taking a matcher argument. This argument can only meaningfully be a string naming an existing route, and thus it differs subtly from the meaning of matcher in what's probably the most visible API, mock():

matcher [required]: Condition for selecting which requests to mock Accepts any of the following
* string: ...
* RegExp: ...
* Function(url, opts): ...

Here is a case where my (incorrect) reading of the docs led to surprising behavior:

fetchMock.mock('^http://example.com/');
fetch('http://example.com/one/two').then(() => {
  fetchMock.called('^http://example.com/'); // true
  fetchMock.called('^http://example.com/one'); // false (surprising to me)
  fetchMock.called(/one\/two$/); // false (surprising to me)
});

how can I return an ArrayBuffer in the body?

Currently I'm just returning { sendAsJson: false, body: myArrayBuffer }, but I always wind up with:

     TypeError: Invalid non-string/buffer chunk
      at chunkInvalid (_stream_readable.js:399:10)
      at readableAddChunk (_stream_readable.js:144:12)
      at Readable.push (_stream_readable.js:130:10)
      at mockResponse (node_modules/fetch-mock/src/fetch-mock.js:59:6)
      at FetchMock.fetchMock (node_modules/fetch-mock/src/fetch-mock.js:253:12)

I'm able to hack around this by wrapping it in a Buffer: { sendAsJSON: false, body: Buffer.from(myArrayBuffer) }, but that's not documented. Is that the intended use?

Remove advanced features

Apologies for copying everyone in. I want to know if anyone's using the advanced features of this module https://github.com/wheresrhys/fetch-mock#advanced-usage? I'm planning on removing them in v4 and instead just documenting a few examples of how to achieve similar behaviour using beforeEach() blocks and .mock() chaining.

Speak now or forever hold your peace! (And happy New Year)

@meabed @dannynelson @choonkending @jwarby @JamesLuoau @developit @dominictobias @vbauerster @jfairbank @vyorkin @yagudaev @enricomarino @Rastopyr @danawoodman @noisecapella @goblindegook @vagusX @LucaColonnello @akatebi @pwalsh @albburtsev @sapegin @voy @badenkov @NOX73 @maksad @bs1180 @kaid @troybetz @yanivtal @mathieumg @sairion @christopherscott @s-shin

Clearing routes

I'm testing the same url route in a few different tests, i.e one test to see if a 200 response is handled correctly another to check that 400 response is handled correctly. fetch-mock seems to remember the mocked routes between tests and this obviously causes issues when you need the mocked url to return a different response. I'm currently setting the routes array to an empty array before each test. Is there a better way? reset() seems to only clear calls, matched call etc. Thanks

lastCall helper

also maybe lastUrl() and lastOptions()

Consider behaviour when fetch called with a Request

Look at the sinon spy API and consider which methods would be really useful to port over

Support swapping out Promise library

I'm trying to use fetch-mock to against environments which do not have Promise implemented natively.

I'm using isomorphic-fetch and replacing its Promise implementation with bluebird, so it works in these environments in my production code.

I'm using it something like this:

import 'isomorphic-fetch'
import Promise from 'bluebird'
fetch.Promise = Promise

It would be cool if fetch-mock used a similar mechanism, or (perhaps even better?) looked into the original fetch and used its .Promise property if it exists.

Let me know if you want me to try to PR this (I assume it would be pretty quick and self-evident how to do this)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.