-
Notifications
You must be signed in to change notification settings - Fork 176
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
52be431
commit 6c1976b
Showing
10 changed files
with
348 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Upgrading from V5 to V6 | ||
|
||
This is a long overdue refactor of the entire library. As feature requests have come in, the code and test suite had become increasingly spaghettified, and this new version is a massive improvement on the previous implementation. | ||
|
||
For the most common use cases, and the basic mocking and inspecting api, very little has changed. The main changes are around how fetch-mock is configured and installed, and turning a few nice new features on by default (couldn't do so in v5 as would've been a breaking change) | ||
|
||
Feedback gratefully received when in beta - please raise an issue :-) | ||
|
||
To try it out: | ||
``` | ||
npm install fetch-mock@6.0.0-beta.1 | ||
``` | ||
(Bear in mind that the docs may still include a few inaccuracies) | ||
|
||
# Changes | ||
|
||
## Configuration and installation | ||
- *No change to mocking fetch as a global* | ||
- Uses whatever version of `node-fetch` you have already installed in your project i.e. can be used with `node-fetch` 2 | ||
- `.sandbox()` no longer accepts a custom `Promise` implementation as a parameter | ||
- Sandboxes can now be 'sub-classed' i.e. define some mocks on a sandbox, then call `.sandbox()` on it to create a new one inheriting all its settings | ||
- No longer has a `setImplementations()` method. Instead, assign custom `Promise` and `fetch` helper classes directly to the `config` property of the fetch-mock instance. This may be done before or afeter sandboxing | ||
- No longer has a `configure()` method. Instead set options directly on the `.config` property. See the api docs for a complete list of options | ||
|
||
## Routing | ||
- `^` is no longer a valid way of matching the beginnig of strings; use `begin:` instead | ||
- `overrideRoutes` option allows for existing routes in a mock to be overwritten. It's also possible to define multiple routes with 'the same' matcher. Default behaviour is to error | ||
|
||
## Responses | ||
- `Content-Length` header generated by default for all responses (can be configured to not do so globally or per response.) | ||
- Objects will be converted to `JSON` responses if they contain any properties not listed in the docs as special response config options (previous behaviour was to convert if any of the properties were present). This mean that e.g. `{user: 'me', status: 'happy'}` can easily be sent as `JSON` | ||
- `__redirectUrl` option is now named `redirectUrl` | ||
- `times` option is now named `repeat` | ||
|
||
## Inspecting | ||
- All inspection methods now filter, in addition to the existing check against `matcher.toString()`, based on the following rules | ||
+ An exact url | ||
+ `true` for matched calls only | ||
+ `false` for unmatched calls only | ||
+ `undefined` includes all calls to `fetch` in order | ||
- When `fetch` was last called with a `Request` object, `lastUrl()` and `lastOpts()` give easier access to the `url` and full `Request` object |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
markdown: kramdown | ||
theme: jekyll-theme-slate | ||
title: fetch-mock | ||
description: Mock http requests made using fetch |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
- [Docs for latest version](/fetch-mock) | ||
- [Introduction](/fetch-mock/v5) | ||
- [Quickstart](/fetch-mock/v5/quickstart) | ||
- [Installation and usage](/fetch-mock/v5/installation) | ||
- API documentation | ||
- [Troubleshooting](/fetch-mock/v5/troubleshooting) | ||
- [Examples](/fetch-mock/v5/examples) | ||
|
||
# V5 API Documentation | ||
|
||
* [V4 - V5 upgrade guide](/fetch-mock/v5/v4-v5-upgrade) | ||
* [V4 docs](https://github.com/wheresrhys/fetch-mock/blob/95d79052efffef5c80b3d87d5050392293e1bfaa/README.md) | ||
|
||
## Mocking calls to `fetch` | ||
|
||
#### `mock(matcher, response, options)` or `mock(options)` | ||
Replaces `fetch()` with a stub which records its calls, grouped by route, and optionally returns a mocked `Response` object or passes the call through to `fetch()`. Calls to `.mock()` can be chained. *Note that once mocked, `fetch` will error on any unmatched calls. Use `.spy()` or `.catch()` to handle unmocked calls more gracefully* | ||
|
||
* `matcher`: Condition for selecting which requests to mock Accepts any of the following | ||
* `string`: Either | ||
* an exact url to match e.g. 'http://www.site.com/page.html' | ||
* '*' to match any url | ||
* `begin:http://www.site.com/` to match urls beginning with a string | ||
* `end:.jpg` to match urls ending with a string | ||
* `glob:http://*.*` to match glob patterns | ||
* `express:/user/:user` to match [express style paths](https://www.npmjs.com/package/path-to-regexp) | ||
* [deprecated] if the string begins with a `^`, the string following the `^` must begin the url e.g. '^http://www.site.com' would match 'http://www.site.com' or 'http://www.site.com/page.html' | ||
* `RegExp`: A regular expression to test the url against | ||
* `Function(url, opts)`: A function (returning a Boolean) that is passed the url and opts `fetch()` is called with (or, if `fetch()` was called with one, the `Request` instance) | ||
* `response`: Configures the http response returned by the mock. Can take any of the following values (or be a `Promise` for any of them, enabling full control when testing race conditions etc.) | ||
* `Response`: A `Response` instance - will be used unaltered | ||
* `number`: Creates a response with this status | ||
* `string`: Creates a 200 response with the string as the response body | ||
* `object`: As long as the object does not contain any of the properties below it is converted into a json string and returned as the body of a 200 response. If any of the properties below are defined it is used to configure a `Response` object | ||
* `body`: Set the response body (`string` or `object`) | ||
* `status`: Set the response status (default `200`) | ||
* `headers`: Set the response headers. (`object`) | ||
* `throws`: If this property is present then a `Promise` rejected with the value of `throws` is returned | ||
* `sendAsJson`: This property determines whether or not the request body should be JSON.stringified before being sent (defaults to true). | ||
* `includeContentLength`: Set this property to true to automatically add the `content-length` header (defaults to false). | ||
* `Function(url, opts)`: A function that is passed the url and opts `fetch()` is called with and that returns any of the responses listed above (or a `Promise` for any of them) | ||
* `options`: A configuration object with all/additional properties to define a route to mock | ||
* `name`: A unique string naming the route. Used to subsequently retrieve references to the calls, grouped by name. If not specified defaults to `matcher.toString()` *Note: If a non-unique name is provided no error will be thrown (because names are optional, so auto-generated ones may legitimately clash)* | ||
* `method`: http method to match | ||
* `headers`: key/value map of headers to match | ||
* `matcher`: as specified above | ||
* `response`: as specified above | ||
* `__redirectUrl`: *experimental* the url the response should be from (to imitate followed redirects - will set `redirected: true` on the response) | ||
* `times`: An integer, `n`, limiting the number of times the matcher can be used. If the route has already been called `n` times the route will be ignored and the call to `fetch()` will fall through to be handled by any other routes defined (which may eventually result in an error if nothing matches it) | ||
|
||
#### `once()` | ||
Shorthand for `mock()` which limits to being called one time only. (see `times` option above) | ||
|
||
#### `get()`, `post()`, `put()`, `delete()`, `head()`, `patch()` | ||
Shorthands for `mock()` restricted to a particular method *Tip: if you use some other method a lot you can easily define your own shorthands e.g.:* | ||
|
||
``` | ||
fetchMock.purge = function (matcher, response, options) { | ||
return this.mock(matcher, response, Object.assign({}, options, {method: 'PURGE'})); | ||
} | ||
``` | ||
|
||
#### `getOnce()`, `postOnce()`, `putOnce()`, `deleteOnce()`, `headOnce()`, `patchOnce()` | ||
Shorthands for `mock()` restricted to a particular method and that can only be called one time only | ||
|
||
#### `catch(response)` | ||
This is used to define how to respond to calls to fetch that don't match any of the defined mocks. It accepts the same types of response as a normal call to `.mock(matcher, response)`. It can also take an arbitrary function to completely customise behaviour of unmatched calls. It is chainable and can be called before or after other calls to `.mock()`. If `.catch() ` is called without any parameters then every unmatched call will receive a `200` response e.g. | ||
|
||
``` | ||
fetchMock | ||
.mock('http://my-api.com', 200) | ||
.catch(503) | ||
``` | ||
|
||
#### `spy()` | ||
Similar to `catch()`, this records the call history of unmatched calls, but instead of responding with a stubbed response, the request is passed through to native `fetch()` and is allowed to communicate over the network. | ||
|
||
#### `sandbox(Promise)` *experimental* | ||
This returns a drop-in mock for fetch which can be passed to other mocking libraries. It implements the full fetch-mock api and maintains its own state independent of other instances, so tests can be run in parallel. e.g. | ||
|
||
``` | ||
fetchMock.sandbox().mock('http://domain.com', 200) | ||
``` | ||
|
||
`sandbox()` can optionally be passed a custom promise implementation. If not provided, the `Promise` global is used. | ||
|
||
#### `flush()` | ||
Returns a promise that resolves once all fetches handled by fetch-mock have resolved. Useful for testing code that uses `fetch` but doesn't return a promise. | ||
|
||
#### `restore()` | ||
Chainable method that restores `fetch()` to its unstubbed state and clears all data recorded for its calls. | ||
|
||
#### `reset()` | ||
Chainable method that clears all data recorded for `fetch()`'s calls | ||
|
||
*Note that `restore()` and `reset()` are both bound to fetchMock, and can be used directly as callbacks e.g. `afterEach(fetchMock.restore)` will work just fine. There is no need for `afterEach(function () {fetchMock.restore()})`* | ||
|
||
## Analysing how `fetch()` has been called | ||
|
||
**For the methods below `matcherName`, if given, should be either the name of a route (see advanced usage below) or equal to `matcher.toString()` for any unnamed route. You _can_ pass in the original regex or function used as a matcher, but they will be converted to strings and used to look up values in fetch-mock's internal maps of calls, rather than used as regexes or functions** | ||
|
||
#### `called(matcherName)` | ||
Returns a Boolean indicating whether fetch was called and a route was matched. If `matcherName` is specified it only returns `true` if that particular route was matched. | ||
|
||
#### `done(matcherName)` | ||
Returns a Boolean indicating whether fetch was called the expected number of times (or at least once if the route defines no expectation is set for the route). If no `matcherName` is passed it returns `true` if every route has been called the number of expected times. | ||
|
||
#### `calls(matcherName)` | ||
Returns an object `{matched: [], unmatched: []}` containing arrays of all calls to fetch, grouped by whether fetch-mock matched them or not. If `matcherName` is specified then only calls to fetch matching that route are returned. | ||
|
||
#### `lastCall(matcherName)` | ||
Returns the arguments for the last matched call to fetch | ||
|
||
#### `lastUrl(matcherName)` | ||
Returns the url for the last matched call to fetch | ||
|
||
#### `lastOptions(matcherName)` | ||
Returns the options for the last matched call to fetch | ||
|
||
## Utilities | ||
|
||
#### `configure(opts)` | ||
Set some global config options, which include | ||
* `sendAsJson` [default `true`] - by default fetchMock will convert objects to JSON before sending. This is overrideable from each call but for some scenarios e.g. when dealing with a lot of array buffers, it can be useful to default to `false` | ||
* `includeContentLength` [default `false`]: When set to true this will make fetchMock automatically add the `content-length` header. This is especially useful when combined with `sendAsJson` because then fetchMock does the conversion to JSON for you and knows the resulting length so you don’t have to compute this yourself by basically doing the same conversion to JSON. | ||
|
||
#### `setImplementations(opts)` | ||
When using non global fetch (e.g. a ponyfill) or an alternative Promise implementation, this will configure fetch-mock to use your chosen implementations. `opts` is an object with one or more of the following properties: `Headers`,`Request`,`Response`,`Promise`. Note that `setImplementations(require('fetch-ponyfill')())` will configure fetch-mock to use all of fetch-ponyfill's classes. `setImplementations()` shoul, in most cases, be called only once, before any tests run. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
- [Docs for latest version](/fetch-mock) | ||
- [Introduction](/fetch-mock/v5) | ||
- [Quickstart](/fetch-mock/v5/quickstart) | ||
- [Installation and usage](/fetch-mock/v5/installation) | ||
- [API documentation](/fetch-mock/v5/api) | ||
- [Troubleshooting](/fetch-mock/v5/troubleshooting) | ||
- Examples | ||
|
||
# V5 Examples | ||
//todo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Version 5 docs | ||
- [Docs for latest version](/fetch-mock) | ||
|
||
fetch-mock allows mocking http requests made using fetch, or any one of the many libraries imitating its api such as [isomorphic-fetch](https://www.npmjs.com/package/isomorphic-fetch), [node-fetch](https://www.npmjs.com/package/node-fetch) and [fetch-ponyfill](https://www.npmjs.com/package/fetch-ponyfill). | ||
|
||
The library will run in most JavaScript environments, including nodejs, web workers and service workers, and any browser that either supports fetch natively or that can have a fetch polyfill/ponyfill installed. | ||
|
||
As well as shorthand methods for the simplest use cases, it offers a flexible API for customising all aspects of mocking behaviour. | ||
|
||
- Introduction | ||
- [Quickstart](/fetch-mock/v5/quickstart) | ||
- [Installation and usage](/fetch-mock/v5/installation) | ||
- [API documentation](/fetch-mock/v5/api) | ||
- [Troubleshooting](/fetch-mock/v5/troubleshooting) | ||
- [Examples](/fetch-mock/v5/examples) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
- [Docs for latest version](/fetch-mock) | ||
- [Introduction](/fetch-mock/v5) | ||
- [Quickstart](/fetch-mock/v5/quickstart) | ||
- Installation and usage | ||
- [API documentation](/fetch-mock/v5/api) | ||
- [Troubleshooting](/fetch-mock/v5/troubleshooting) | ||
- [Examples](/fetch-mock/v5/examples) | ||
|
||
# V5 Installation | ||
Install fetch-mock using `npm install --save-dev fetch-mock` | ||
|
||
In most environments use `const fetchMock = require('fetch-mock')` to use it in your code. Some exceptions include: | ||
|
||
* 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')`. | ||
* If you need to use fetch-mock without commonjs, you can include the precompiled `node_modules/fetch-mock/es5/client-browserified.js` in a script tag. This loads fetch-mock into the `fetchMock` global variable. | ||
* For server side tests running in nodejs 0.12 or lower use `require('fetch-mock/es5/server')` | ||
|
||
## Global fetch | ||
By default fetch-mock assumes `fetch` is a global so once you've required fetch-mock refer to the quickstart and api docs. | ||
|
||
### Polyfilling fetch | ||
Many older browsers will require polyfilling the `fetch` global | ||
|
||
* In nodejs `require('isomorphic-fetch')` before any of your tests. | ||
* In the browser `require('isomorphic-fetch')` can also be used, but it may be easier to `npm install whatwg-fetch` (the module isomorphic-fetch is built around) and load `./node_modules/whatwg-fetch/fetch.js` directly into the page, either in a script tag or by referencing in your test runner config. | ||
* When using karma-webpack it's best not to use the `webpack.ProvidePlugin` for this. Instead just add `node_modules/whatwg-fetch/fetch.js` to your list of files to include, or require it directly into your tests before requiring fetch-mock. | ||
|
||
## Non-global fetch | ||
|
||
When using a non-global fetch implementation (such as node-fetch or fetch-ponyfill) use the `sandbox()` method to return a function that can be used as a replacement for fetch, and be passed into your source code using your choice of mocking library. The function returned by `sandbox()` supports the full fetch-mock api so once generated it can be worked with as if it were the original `fetch-mock` object, e.g. | ||
|
||
``` | ||
const fetchMock = require('fetch-mock'); | ||
const myMock = fetchMock.sandbox().mock('/home', 200); | ||
// pass myMock in to your application code, instead of fetch, run it, then... | ||
expect(myMock.called('/home')).to.be.true; | ||
``` | ||
|
||
## References to Request, Response, Helpers and Promise | ||
If you're using a non-global fetch implementation, or wish to use a custom Promise implementation, you may need to tell fetch-mock to use these when matching requests and returning responses. Do this using the `.setImplementations()` method. e.g. | ||
|
||
``` | ||
fetchMock.setImplementations({Promise: require('Bluebird').promise}) | ||
``` | ||
|
||
In particular, when using fetch-ponyfill | ||
|
||
``` | ||
setImplementations(require('fetch-ponyfill')())` | ||
``` | ||
|
||
will set all the internal references to point at fetch-ponyfill's classes. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
- [Docs for latest version](/fetch-mock) | ||
- [Introduction](/fetch-mock/v5) | ||
- Quickstart | ||
- [Installation and usage](/fetch-mock/v5/installation) | ||
- [API documentation](/fetch-mock/v5/api) | ||
- [Troubleshooting](/fetch-mock/v5/troubleshooting) | ||
- [Examples](/fetch-mock/v5/examples) | ||
|
||
# V5 Quickstart | ||
|
||
## Setting up your mock | ||
|
||
The commonest use case is `fetchMock.mock(matcher, response)`, where `matcher` is a string or regex to match and `response` is a statusCode, string or object literal. You can also use `fetchMock.once(url ...)` to limit to a single call or `fetchMock.get()`, `fetchMock.post()` etc. to limit to a method. All these methods are chainable so you can easily define several mocks in a single test. | ||
|
||
## Analysing calls to your mock | ||
`fetchMock.called(matcher)` reports if any calls matched your mock (or leave `matcher` out if you just want to check `fetch` was called at all). `fetchMock.lastCall()`, `fetchMock.lastUrl()` or `fetchMock.lastOptions()` give you access to the parameters last passed in to `fetch`. `fetchMock.done()` will tell you if `fetch` was called the expected number of times. | ||
|
||
## Tearing down your mock | ||
`fetchMock.reset()` resets the call history. `fetchMock.restore()` will also restore `fetch()` to its native implementation | ||
|
||
## Example | ||
Example with node: suppose we have a file `make-request.js` with a function that calls `fetch`: | ||
|
||
```js | ||
module.exports = function makeRequest() { | ||
return fetch("http://httpbin.org/get").then(function(response) { | ||
return response.json(); | ||
}); | ||
}; | ||
``` | ||
|
||
We can use fetch-mock to mock `fetch`. In `mocked.js`: | ||
|
||
```js | ||
var fetchMock = require('fetch-mock'); | ||
var makeRequest = require('./make-request'); | ||
|
||
// Mock the fetch() global to always return the same value for GET | ||
// requests to all URLs. | ||
fetchMock.get('*', {hello: 'world'}); | ||
|
||
makeRequest().then(function(data) { | ||
console.log('got data', data); | ||
}); | ||
|
||
// Unmock. | ||
fetchMock.restore(); | ||
``` | ||
|
||
Result: | ||
|
||
```bash | ||
$ node mocked.js | ||
'got data' { hello: 'world' } | ||
``` |
Oops, something went wrong.