From 26e9d1ea9cce8318b7940771ee1efa94d3a993ee Mon Sep 17 00:00:00 2001 From: Rhys Evans Date: Mon, 20 Aug 2018 21:58:05 +0100 Subject: [PATCH] relint docs --- docs/api.md | 90 +++++++++++++++++++++++-------------------- docs/installation.md | 7 ++-- docs/v6-v7-upgrade.md | 56 ++++++++++++++++++--------- 3 files changed, 89 insertions(+), 64 deletions(-) diff --git a/docs/api.md b/docs/api.md index 5bafde5b..2a2561da 100644 --- a/docs/api.md +++ b/docs/api.md @@ -15,43 +15,46 @@ ## 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. (For matching based on headers, query strings or other `fetch` options see the `options` parameter documented below). 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 - * `path:/posts/2018/7/3` to match urls with a given path - * `glob:http://*.*` to match glob patterns - * `express:/user/:user` to match [express style paths](https://www.npmjs.com/package/path-to-regexp) - * `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) + +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. (For matching based on headers, query strings or other `fetch` options see the `options` parameter documented below). 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 + - `path:/posts/2018/7/3` to match urls with a given path + - `glob:http://*.*` to match glob patterns + - `express:/user/:user` to match [express style paths](https://www.npmjs.com/package/path-to-regexp) + - `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) _Note that if using `end:` or an exact url matcher, `fetch-mock` ([for good reason](https://url.spec.whatwg.org/#url-equivalence)) is unable to distinguish whether URLs without a path end in a trailing slash or not i.e. `http://thing` is treated the same as `http://thing/`_ -* `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 - * `configObject` If an object _does not contain_ any properties aside from those listed below it is treated as config to build a `Response` - * `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 fetch returns a `Promise` rejected with the value of `throws` - * `sendAsJson`: This property determines whether or not the request body should be converted to `JSON` before being sent (defaults to `true`). - * `includeContentLength`: Set this property to true to automatically add the `content-length` header (defaults to `true`). - * `redirectUrl`: *experimental* the url the response should be from (to imitate followed redirects - will set `redirected: true` on the response) - * `object`: All objects that do not meet the criteria above are converted to `JSON` and returned as the body of a 200 response. - * `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. Defaults to `matcher.toString()` - * `method`: http method to match - * `headers`: key/value map of headers to match - * `query`: key/value map of query strings to match, in any order - * `matcher`: as specified above - * `response`: as specified above - * `repeat`: 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) - * `overwriteRoutes`: If the route you're adding clashes with an existing route, setting `true` here will overwrite the clashing route, `false` will add another route to the stack which will be used as a fallback (useful when using the `repeat` option). Adding a clashing route without specifying this option will throw an error. It can also be set as a global option (see the **Config** section below) + +- `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 + - `configObject` If an object _does not contain_ any properties aside from those listed below it is treated as config to build a `Response` + - `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 fetch returns a `Promise` rejected with the value of `throws` + - `sendAsJson`: This property determines whether or not the request body should be converted to `JSON` before being sent (defaults to `true`). + - `includeContentLength`: Set this property to true to automatically add the `content-length` header (defaults to `true`). + - `redirectUrl`: _experimental_ the url the response should be from (to imitate followed redirects - will set `redirected: true` on the response) + - `object`: All objects that do not meet the criteria above are converted to `JSON` and returned as the body of a 200 response. + - `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. Defaults to `matcher.toString()` + - `method`: http method to match + - `headers`: key/value map of headers to match + - `query`: key/value map of query strings to match, in any order + - `matcher`: as specified above + - `response`: as specified above + - `repeat`: 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) + - `overwriteRoutes`: If the route you're adding clashes with an existing route, setting `true` here will overwrite the clashing route, `false` will add another route to the stack which will be used as a fallback (useful when using the `repeat` option). Adding a clashing route without specifying this option will throw an error. It can also be set as a global option (see the **Config** section below) #### `sandbox()` @@ -104,15 +107,16 @@ _Note that `restore()` and `reset()` are both bound to fetchMock, and can be use ## Inspecting how `fetch()` has been called ### Filtering + Most of the methods below accept two parameters, `(filter, options)` -- `filter` Enables filtering fetch calls for the most commonly use cases. The behaviour can be counterintuitive. The following rules, applied in the order they are described, are used to try to retrieve calls. If any rule retrieves no calls the next rule will be tried. - - If `filter` is `undefined` all calls, matched _and_ unmatched, are returned - - If `filter` is `true` (or `fetchMock.MATCHED`) all calls that matched some route are returned - - If `filter` is `false` (or `fetchMock.UNMATCHED`) all calls that did not match any route are returned (when `.spy()`, `catch()` or `config.fallThroughToNetwork` were used to prevent errors being thrown) - - If `filter` is the name of a named route, all calls handled by that route are returned - - If `filter` is equal to `matcher` or `matcher.toString()` for a route, all calls handled by that route are returned - - `filter` is executed using the same execution plan as matchers used in `.mock()`. Any calls matched by it will be returned. If `options` is also passed this is used in a similar way to the options used by `mock()`. Alternatively, `options` can be a string specifying a `method` to filter by +- `filter` Enables filtering fetch calls for the most commonly use cases. The behaviour can be counterintuitive. The following rules, applied in the order they are described, are used to try to retrieve calls. If any rule retrieves no calls the next rule will be tried. + - If `filter` is `undefined` all calls, matched _and_ unmatched, are returned + - If `filter` is `true` (or `fetchMock.MATCHED`) all calls that matched some route are returned + - If `filter` is `false` (or `fetchMock.UNMATCHED`) all calls that did not match any route are returned (when `.spy()`, `catch()` or `config.fallThroughToNetwork` were used to prevent errors being thrown) + - If `filter` is the name of a named route, all calls handled by that route are returned + - If `filter` is equal to `matcher` or `matcher.toString()` for a route, all calls handled by that route are returned + - `filter` is executed using the same execution plan as matchers used in `.mock()`. Any calls matched by it will be returned. If `options` is also passed this is used in a similar way to the options used by `mock()`. Alternatively, `options` can be a string specifying a `method` to filter by #### `called(filter, method)` @@ -135,9 +139,11 @@ Returns the arguments for the last matched call to fetch Returns the url for the last matched call to fetch. When `fetch` was last called using a `Request` instance, the url will be extracted from this #### `lastOptions(filter, method)` + Returns the options for the last matched call to fetch. When `fetch` was last called using a `Request` instance, a set of `options` inferred from the `Request` will be returned #### `flush()` + Returns a `Promise` that resolves once all fetches handled by fetch-mock have resolved. Pass in `true` to wait for all response methods (`res.json()`, `res.text()`, etc.) to resolve too. Useful for testing code that uses `fetch` but doesn't return a promise. ## Config diff --git a/docs/installation.md b/docs/installation.md index 0e31f70f..d0048501 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -20,7 +20,6 @@ const fetchMock = require('fetch-mock'); const { fetchMock, MATCHED, UNMATCHED } = require('fetch-mock'); ``` - 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')`. @@ -28,11 +27,13 @@ Some exceptions include: - For server side tests running in nodejs 6 or lower use `require('fetch-mock/es5/server')`. You will also need to `npm i -D babel-polyfill` ## Global fetch + <<<<<<< HEAD ======= ->>>>>>> 315bf4bee040aa243eaf3b2a418741d35444bccb -By default fetch-mock assumes `fetch` is a global so once you've required fetch-mock refer to the quickstart and api docs. + +> > > > > > > 315bf4bee040aa243eaf3b2a418741d35444bccb +> > > > > > > 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 diff --git a/docs/v6-v7-upgrade.md b/docs/v6-v7-upgrade.md index 20feb8f6..15c3df75 100644 --- a/docs/v6-v7-upgrade.md +++ b/docs/v6-v7-upgrade.md @@ -1,6 +1,7 @@ # Upgrading from V6 to V7 <<<<<<< HEAD + # Changes ## `throws` option now rejects a Promise @@ -25,30 +26,37 @@ The `fetch` api can be called with either a `Request` object or a `url` with an ## Exporting as property -`fetch-mock` now has a property `fetchMock`, which means the libary can be imported using any of the below -======= +# `fetch-mock` now has a property `fetchMock`, which means the libary can be imported using any of the below + Most changes are relatively minor and shouldn't affect most users. # Changes ## `throws` option now rejects a Promise + A regression was introduced in v6 whereby the `throws: true` option woudl throw an uncaught error. The `fetch` api catches all its internal errors and returns a rejected `Promise` in every case, so this change has been reverted to be more useful for mocking typical `fetch` errors. ## Responses are wrapped in an ES Proxy + This is to enable a more powerful `flush()` method, able to wait for asynchronous resolution of response methods such as `.json()` and `.text()`. `flush(true)` will resolve only when Promises returnes by any response methods called before `flush()` have resolved ## Supports resolving dots in urls + As resolving `../` and `./` as relative paths is [speced url behaviour](https://url.spec.whatwg.org/#double-dot-path-segment), fetch-mock has been updated to also do this resolution when matching urls. URLs are normalised _before_ any matchers try to match against them as, to the `fetch` api, `http://thing/decoy/../quarry` is indistinguishable from `http://thing/quarry`, so it would make no sense to allow different mocking based on which variant is used. ## Agnostic as to whether hosts have a trailing slash or not + A side-effect of the above normalisation - using [whatwg-url](https://www.npmjs.com/package/whatwg-url) - is that fetch-mock is no longer able to distinguish between pathless URLs which do/do not end in a trailing slash i.e. `http://thing` behaves exactly the same as `http://thing/` when used in any of the library's APIs, and any mocks that match one will match the other. As mentioned above, URL normalization happens _before_ any matching is attempted. ## Request instances are normalized early to [url, options] pairs + The `fetch` api can be called with either a `Request` object or a `url` with an `options` object. To make the library easier to maintain and its APIs - in particular the call inspecting APIs such as `called()` - agnostic as to how `fetch` was called, Request objects are normalised early into `url`, `options` pairs. So the fetch args returned by `calls()` will always be of the form `[url, options]` even if `fetch` was called with a `Request` object. The original `Request` object is still provided as a third item in the args array in case it is needed. ## Exporting as property + `fetch-mock` now has a property `fetchMock`, which means the libarry can be imported using any of the below ->>>>>>> 315bf4bee040aa243eaf3b2a418741d35444bccb + +> > > > > > > 315bf4bee040aa243eaf3b2a418741d35444bccb ```js const fetchMock = require('fetch-mock'); @@ -59,11 +67,13 @@ const { fetchMock } = require('fetch-mock'); The reason for this should become clear in the next point ## Adds MATCHED and UNMATCHED constants + <<<<<<< HEAD ======= ->>>>>>> 315bf4bee040aa243eaf3b2a418741d35444bccb -The inspection APIs e.g. `calls()` can be passed `true` or `false` to return matched/unmatched calls respectively. To aid with more comprehensible code, fetchMock now exports `MATCHED` and `UNMATCHED` constants, equal to `true` and `false`. Using `true` or `false` still works, but I'd recommend using the constants. Compare the readbility of the following: + +> > > > > > > 315bf4bee040aa243eaf3b2a418741d35444bccb +> > > > > > > The inspection APIs e.g. `calls()` can be passed `true` or `false` to return matched/unmatched calls respectively. To aid with more comprehensible code, fetchMock now exports `MATCHED` and `UNMATCHED` constants, equal to `true` and `false`. Using `true` or `false` still works, but I'd recommend using the constants. Compare the readbility of the following: ```js const { fetchMock, MATCHED, UNMATCHED } = require('fetch-mock'); @@ -73,6 +83,7 @@ fetchMock.called(MATCHED); ``` ## Able to match requests based on the path of the url + <<<<<<< HEAD `fetchMock.mock('path:/apples/pears')` Will match any url whose `path` part is `/apples/pears` @@ -106,31 +117,38 @@ And, copied directly from the API docs: - If `filter` is the name of a named route, all calls handled by that route are returned - If `filter` is equal to `matcher` or `matcher.toString()` for a route, all calls handled by that route are returned - `filter` is executed using the same execution plan as matchers used in `.mock()`. Any calls matched by it will be returned. If `options` is also passed this is used in a similar way to the options used by `mock()`. Alternatively, `options` can be a string specifying a `method` to filter by + ======= `fetchMock.mock('path:/apples/pears')` Will match any url whose `path` part is `apples/pears` ## More powerful inspection filtering + Previously, any filter passed in to `calls(filter)` etc... would always be converted to a string and then be used to lookup whether any fetch calls had been handled by a route matcher that also had the same `toString()` value. This is still the case, but if no calls match, then the filter will be converted into an on the fly route matcher, which is then used to filter the list of calls that were handled by fetch. This measn e.g. you can use any regex or glob to filter the calls. ### Example + ```js -fetchMock.mock('*', 200) -await fetch('/main-course/lasagne', {method: 'POST', headers: {discount: true}}); +fetchMock.mock('*', 200); +await fetch('/main-course/lasagne', { + method: 'POST', + headers: { discount: true } +}); await fetch('/main-course/bolognaise'); -fetchMock.called(/l.+gne/) // true -fetchMock.called('glob:/*/lasagne', {method: 'post'}) // true -fetchMock.called((url, options) => options.headers.discount) // true +fetchMock.called(/l.+gne/); // true +fetchMock.called('glob:/*/lasagne', { method: 'post' }); // true +fetchMock.called((url, options) => options.headers.discount); // true ``` + And, copied directly from the API docs: - Most of the methods below accept two parameters, `(filter, options)` - - `filter` Enables filtering fetch calls for the most commonly use cases. The behaviour can be counterintuitive. The following rules, applied in the order they are described, are used to try to retrieve calls. If any rule retrieves no calls the next rule will be tried. - - If `filter` is `undefined` all calls, matched _and_ unmatched, are returned - - If `filter` is `true` (or `fetchMock.MATCHED`) all calls that matched some route are returned - - If `filter` is `false` (or `fetchMock.UNMATCHED`) all calls that did not match any route are returned (when `.spy()`, `catch()` or `config.fallThroughToNetwork` were used to prevent errors being thrown) - - If `filter` is the name of a named route, all calls handled by that route are returned - - If `filter` is equal to `matcher` or `matcher.toString()` for a route, all calls handled by that route are returned - - `filter` is executed using the same execution plan as matchers used in `.mock()`. Any calls matched by it will be returned. If `options` is also passed this is used in a similar way to the options used by `mock()`. Alternatively, `options` can be a string specifying a `method` to filter by + Most of the methods below accept two parameters, `(filter, options)` + - `filter` Enables filtering fetch calls for the most commonly use cases. The behaviour can be counterintuitive. The following rules, applied in the order they are described, are used to try to retrieve calls. If any rule retrieves no calls the next rule will be tried. + - If `filter` is `undefined` all calls, matched _and_ unmatched, are returned + - If `filter` is `true` (or `fetchMock.MATCHED`) all calls that matched some route are returned + - If `filter` is `false` (or `fetchMock.UNMATCHED`) all calls that did not match any route are returned (when `.spy()`, `catch()` or `config.fallThroughToNetwork` were used to prevent errors being thrown) + - If `filter` is the name of a named route, all calls handled by that route are returned + - If `filter` is equal to `matcher` or `matcher.toString()` for a route, all calls handled by that route are returned + - `filter` is executed using the same execution plan as matchers used in `.mock()`. Any calls matched by it will be returned. If `options` is also passed this is used in a similar way to the options used by `mock()`. Alternatively, `options` can be a string specifying a `method` to filter by ->>>>>>> 315bf4bee040aa243eaf3b2a418741d35444bccb +> > > > > > > 315bf4bee040aa243eaf3b2a418741d35444bccb