From dd95c0d1da67f107c96cd36f90e76c52b4846e81 Mon Sep 17 00:00:00 2001 From: Rhys Evans Date: Fri, 19 Jul 2024 23:41:45 +0100 Subject: [PATCH 01/10] docs: started work documenting the core library --- docs/docs/APIOld/Inspection/_category_.json | 5 + docs/docs/APIOld/Inspection/done.md | 27 ++++ docs/docs/APIOld/Inspection/flush.md | 12 ++ .../APIOld/Inspection/inspecting-calls.md | 132 ++++++++++++++++ docs/docs/APIOld/Lifecycle/_category_.json | 5 + docs/docs/APIOld/Lifecycle/resetting.md | 22 +++ docs/docs/APIOld/Lifecycle/sandbox.md | 12 ++ docs/docs/APIOld/Routing/_category_.json | 5 + docs/docs/APIOld/Routing/add-matcher.md | 68 ++++++++ docs/docs/APIOld/Routing/catch.md | 10 ++ docs/docs/APIOld/Routing/shorthands.md | 60 +++++++ docs/docs/APIOld/_category_.json | 5 + docs/docs/core/fetchHandler.md | 13 ++ docs/docs/core/index.md | 13 ++ docs/docs/core/inspection-placeholder.md | 2 + docs/docs/core/route/_category_.json | 5 + docs/docs/core/route/index.md | 104 ++++++++++++ docs/docs/core/route/matcher.md | 149 ++++++++++++++++++ docs/docs/core/route/options.md | 61 +++++++ docs/docs/core/route/response.md | 80 ++++++++++ docs/docusaurus.config.js | 6 + docs/sidebars.js | 1 + 22 files changed, 797 insertions(+) create mode 100644 docs/docs/APIOld/Inspection/_category_.json create mode 100644 docs/docs/APIOld/Inspection/done.md create mode 100644 docs/docs/APIOld/Inspection/flush.md create mode 100644 docs/docs/APIOld/Inspection/inspecting-calls.md create mode 100644 docs/docs/APIOld/Lifecycle/_category_.json create mode 100644 docs/docs/APIOld/Lifecycle/resetting.md create mode 100644 docs/docs/APIOld/Lifecycle/sandbox.md create mode 100644 docs/docs/APIOld/Routing/_category_.json create mode 100644 docs/docs/APIOld/Routing/add-matcher.md create mode 100644 docs/docs/APIOld/Routing/catch.md create mode 100644 docs/docs/APIOld/Routing/shorthands.md create mode 100644 docs/docs/APIOld/_category_.json create mode 100644 docs/docs/core/fetchHandler.md create mode 100644 docs/docs/core/index.md create mode 100644 docs/docs/core/inspection-placeholder.md create mode 100644 docs/docs/core/route/_category_.json create mode 100644 docs/docs/core/route/index.md create mode 100644 docs/docs/core/route/matcher.md create mode 100644 docs/docs/core/route/options.md create mode 100644 docs/docs/core/route/response.md diff --git a/docs/docs/APIOld/Inspection/_category_.json b/docs/docs/APIOld/Inspection/_category_.json new file mode 100644 index 00000000..ba14420a --- /dev/null +++ b/docs/docs/APIOld/Inspection/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 5, + "collapsible": true, + "collapsed": true, +} diff --git a/docs/docs/APIOld/Inspection/done.md b/docs/docs/APIOld/Inspection/done.md new file mode 100644 index 00000000..8313e526 --- /dev/null +++ b/docs/docs/APIOld/Inspection/done.md @@ -0,0 +1,27 @@ +--- +sidebar_position: 2 + +--- +# .done(filter) + + +Returns a Boolean indicating whether `fetch` was called the expected number of times (or has been called at least once if `repeat` is undefined for the route). It does not take into account whether the `fetches` completed successfully. + +## Filter + +### undefined / true + +Returns true if all routes have been called the expected number of times + +### routeIdentifier + +`{String|RegExp|function}` + +All routes have an identifier: + +- If it's a named route, the identifier is the route's name +- If the route is unnamed, the identifier is the `matcher` passed in to `.mock()` + +Returns true if the routes specified by the identifier has been called the expected number of times + +If several routes have the same matcher/url, but use [mocking options](#apimockingmock_options), the recommended way to handle this is to [name each route](#api-mockingmock_options) and filter using those names diff --git a/docs/docs/APIOld/Inspection/flush.md b/docs/docs/APIOld/Inspection/flush.md new file mode 100644 index 00000000..84172eef --- /dev/null +++ b/docs/docs/APIOld/Inspection/flush.md @@ -0,0 +1,12 @@ +--- + +sidebar_position: 3 +--- +# .flush(waitForBody) + + +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. + +If `waitForBody` is `true`, the promise will wait for all body parsing methods (`res.json()`, `res.text()`, etc.) to resolve too. diff --git a/docs/docs/APIOld/Inspection/inspecting-calls.md b/docs/docs/APIOld/Inspection/inspecting-calls.md new file mode 100644 index 00000000..160aa7aa --- /dev/null +++ b/docs/docs/APIOld/Inspection/inspecting-calls.md @@ -0,0 +1,132 @@ +--- + +sidebar_position: 1 +tableOfContents: + maxHeadingLevel: 5 + +--- +# Inspecting calls + +## Methods + +### .calls(filter, options) + +Returns an array of all calls to fetch matching the given `filter` and `options`. Each call is returned as a `[url, options]` array. If `fetch` was called using a `Request` instance, the `url` and `options` will be inferred from it, and the original `Request` will be available as a `request` property on this array. + +### .called(filter, options) + +Returns a Boolean indicating whether any calls to `fetch` matched the given `filter` and `options` + +### .lastCall(filter, options) + +Returns the arguments for the last call to `fetch` matching the given `filter` and `options`. The call is returned as a `[url, options]` array. If `fetch` was called using a `Request` instance, the `url` and `options` will be inferred from it, and the original `Request` will be available as a `request` property on this array. + +### .lastUrl(filter, options) + +Returns the url for the last call to `fetch` matching the given `filter` and `options`. If `fetch` was last called using a `Request` instance, the url will be inferred from this + +### .lastOptions(filter, options) + +Returns the options for the last call to `fetch` matching the given `filter` and `options`. If `fetch` was last called using a `Request` instance, a set of `options` inferred from the `Request` will be returned + +### .lastResponse(filter, options) + +Returns the `Response` for the last call to `fetch` matching the given `filter` and `options`. This is an experimental feature, very difficult to implement well given fetch's very private treatment of response bodies. + +If `.lastResponse()` is called before fetch has been resolved then it will return `undefined` + +When doing all the following: + +- using node-fetch +- responding with a real network response (using spy() or fallbackToNetwork) +- using \`fetchMock.LastResponse()\` +- awaiting the body content + ... the response will hang unless your source code also awaits the response body. + This is an unavoidable consequence of the nodejs implementation of streams. + +To obtain json/text responses await the `.json()/.text()` methods of the response + +## Filtering + +`fetch-mock`'s inspection methods allow information about how `fetch` was called to be retrieved after your application code has run. Most inspection methods take two arguments — `(filter, options)` — which allow individual, or groups of, `fetch` calls to be extracted and examined. + +### Parameters + +#### filter + +Filter calls to `fetch` using one of the following criteria: + +##### undefined + +Retrieve all calls made to `fetch` + +##### true / "matched" + +Retrieve all calls to `fetch` matched by some route defined by `fetch-mock`. The string `'matched'` can be used instead of `true` to make tests more readable + +##### false / "unmatched" + +Retrieve all calls to `fetch` not matched by some route defined by `fetch-mock`. The string `'unmatched'` can be used instead of `false` to make tests more readable + +##### routeIdentifier + +`{String|RegExp|function}` + +All routes have an identifier: + +- If it's a [named route](#api-mockingmock_options), the identifier is the route's `name` +- If the route is unnamed, the identifier is the value of the `matcher` argument that was passed in to `.mock()` + +All calls that were handled by the route with the given identifier will be retrieved + +##### matcher + +`{String|RegExp|function}` +Any matcher compatible with the [mocking api](#api-mockingmock_matcher) can be passed in to filter the calls arbitrarily. The matcher will be executed using exactly the same rules as the mocking api + +#### options + +`{Object|String}` + +Either an object compatible with the [mocking api](#api-mockingmock_options) or a string specifying a http method to filter by. This will be used to filter the list of calls further + +### Caveats + +#### Confusing API + +The filtering API is powerful, but potentially confusing. If in doubt, [add a `name` to your route](#api-mockingmock_options), and pass that name in to retrieve exactly the calls you want. + +The API will be simplified and changed significantly in the next major version + +#### Regular Expression and Function matchers + +To retrieve calls handled by a route with a `RegExp` or `function` matcher, use a reference to the exact `RegExp`|`function` you used in your mock, e.g. + +```javascript +const matcherRX = /user\/biff/ +fm.mock(matcherRX, 200) +... +fm.called(matcherRX) +``` + +not + +```javascript +fm.mock(/user\/biff/, 200) +... +fm.called(/user\/biff/) +``` + +The second example _will_ retrieve the expected calls in simple test scenarios because if no routes match using the identifier the `RegExp` will be executed as a `RegExp` matcher. But in more complex scenarios where e.g. there are several routes handling similar paths, it might retrieve calls that were actually handled by different, similar route e.g. + +```javascript +const matcherRX = /user\/biff/ +fm + .mock('end:user/biff') + .mock(matcherRX, 200) +... +// this will retrieve calls handled by either route +fm.called(/user\/biff/) +// this will retrieve only calls handled by the second route +fm.called(matcherRX) +``` diff --git a/docs/docs/APIOld/Lifecycle/_category_.json b/docs/docs/APIOld/Lifecycle/_category_.json new file mode 100644 index 00000000..40b4fc51 --- /dev/null +++ b/docs/docs/APIOld/Lifecycle/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 3, + "collapsible": true, + "collapsed": true, +} diff --git a/docs/docs/APIOld/Lifecycle/resetting.md b/docs/docs/APIOld/Lifecycle/resetting.md new file mode 100644 index 00000000..234b93a4 --- /dev/null +++ b/docs/docs/APIOld/Lifecycle/resetting.md @@ -0,0 +1,22 @@ +--- + +sidebar_position: 2 +--- +# Resetting + + +## .restore() / .reset() + +Resets `fetch()` to its unstubbed state and clears all data recorded for its calls. `restore()` is an alias for `reset()`. Optionally pass in a `{sticky: true}` option to remove even sticky routes. + +Both methods are bound to fetchMock, and can be used directly as callbacks e.g. `afterEach(fetchMock.reset)` will work just fine. There is no need for `afterEach(() => fetchMock.reset())` + +## .resetHistory() + +Clears all data recorded for `fetch`'s calls. It _will not_ restore fetch to its default implementation + +`resetHistory()` is bound to fetchMock, and can be used directly as a callback e.g. `afterEach(fetchMock.resetHistory)` will work just fine. There is no need for `afterEach(() => fetchMock.resetHistory())` + +## .resetBehavior() + +Removes all mock routes from the instance of `fetch-mock`, and restores `fetch` to its original implementation if mocking globally. Will not clear data recorded for `fetch`'s calls. Optionally pass in a `{sticky: true}` option to remove even sticky routes. diff --git a/docs/docs/APIOld/Lifecycle/sandbox.md b/docs/docs/APIOld/Lifecycle/sandbox.md new file mode 100644 index 00000000..83a891dc --- /dev/null +++ b/docs/docs/APIOld/Lifecycle/sandbox.md @@ -0,0 +1,12 @@ +--- + +sidebar_position: 1 + +--- +# .sandbox() + +Returns a function that can be used as a drop-in replacement for `fetch`. Pass this into your mocking library of choice. The function returned by `sandbox()` has all the methods of `fetch-mock` exposed on it and maintains its own state independent of other instances, so tests can be run in parallel. + +```js +fetchMock.sandbox().mock('http://domain.com', 200); +``` diff --git a/docs/docs/APIOld/Routing/_category_.json b/docs/docs/APIOld/Routing/_category_.json new file mode 100644 index 00000000..40b4fc51 --- /dev/null +++ b/docs/docs/APIOld/Routing/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 3, + "collapsible": true, + "collapsed": true, +} diff --git a/docs/docs/APIOld/Routing/add-matcher.md b/docs/docs/APIOld/Routing/add-matcher.md new file mode 100644 index 00000000..d8f40e61 --- /dev/null +++ b/docs/docs/APIOld/Routing/add-matcher.md @@ -0,0 +1,68 @@ +--- +sidebar_position: 3 +--- +# .addMatcher(options) + + +Allows adding your own, reusable custom matchers to fetch-mock, for example a matcher for interacting with GraphQL queries, or an `isAuthorized` matcher that encapsulates the exact authorization conditions for the API you are mocking, and only requires a `true` or `false` to be input + +## Options + +### name + +`{String}` + +The name of your matcher. This will be the name of the property used to hold any input to your matcher. e.g. `graphqlVariables` + +### usesBody + +`{Boolean}` + +If your matcher requires access to the body of the request set this to true; because body can, in some cases, only be accessed by fetch-mock asynchronously, you will need to provide this hint in order to make sure the correct code paths are followed. + +### matcher + +`{Function}` + +A function which takes a route definition object as input, and returns a function of the signature `(url, options, request) => Boolean`. See the examples below for more detail. The function is passed the fetchMock instance as a second parameter in case you need to access any config. + +#### Examples + +##### Authorization + +```js +fetchMock + .addMatcher({ + name: 'isAuthorized', + matcher: + ({ isAuthorized }) => + (url, options) => { + const actuallyIsAuthorized = options.headers && options.headers.auth; + return isAuthorized ? actuallyIsAuthorized : !actuallyIsAuthorized; + }, + }) + .mock({ isAuthorized: true }, 200) + .mock({ isAuthorized: false }, 401); +``` + +##### GraphQL + +```js +fetchMock + .addMatcher({ + name: 'graphqlVariables', + matcher: ({graphqlVariables}) => (url, options) => { + if (!/\/graphql$/.test(url)) { + return false; + } + const body = JSON.parse(options.body) + return body.variables && Object.keys(body.variables).length === Object.keys(body.graphqlVariables).length && Object.entries(graphqlVariables).every(([key, val]) => body.variables[key] === val) + } + }) + .mock({graphqlVariables: {owner: 'wheresrhys'}}, {data: {account: { + name: 'wheresrhys', + repos: [ ... ] + }}}) +``` + +One intent behind this functionality is to allow companies or publishers of particular toolsets to provide packages that extend fetch-mock to provide a more user friendly experience for developers using fetch to interact with their APIs. The GraphQL use case is a good example of this - the things which a developer might want to match on are buried in the request body, and written in a non-javascript query language. Please get in touch if you'd like to collaborate on writing such a package. diff --git a/docs/docs/APIOld/Routing/catch.md b/docs/docs/APIOld/Routing/catch.md new file mode 100644 index 00000000..e6d884a2 --- /dev/null +++ b/docs/docs/APIOld/Routing/catch.md @@ -0,0 +1,10 @@ +--- + +sidebar_position: 3 + +--- +# .catch(response) + +Specifies how to respond to calls to `fetch` that don't match any mocks. + +It accepts any valid [fetch-mock response](#api-mockingmock_response), and can also take an arbitrary function to completely customise behaviour. If no argument is passed, then every unmatched call will receive a `200` response diff --git a/docs/docs/APIOld/Routing/shorthands.md b/docs/docs/APIOld/Routing/shorthands.md new file mode 100644 index 00000000..e59680db --- /dev/null +++ b/docs/docs/APIOld/Routing/shorthands.md @@ -0,0 +1,60 @@ +--- +sidebar_position: 2 + +--- +# Shorthand methods + + +These methods allow configuring routes for common use cases while avoiding writing configuration objects. Unless noted otherwise, each of the methods below have the same signature as `.mock(matcher, response, optionsOrName)` + +## .once() + +Shorthand for `mock()` which creates a route that can only mock a single request. (see `repeat` option above) + +## .any(response, options) + +Shorthand for `mock()` which creates a route that will return a response to any fetch request. + +## .anyOnce(response, options) + +Creates a route that responds to any single request + +## .get(), .post(), .put(), .delete(), .head(), .patch() + +Shorthands for `mock()` that create routes that only respond to requests using a particular http method. + +If you use some other method a lot you can easily define your own shorthands e.g. + +```javascript +fetchMock.purge = function (matcher, response, options) { + return this.mock( + matcher, + response, + Object.assign({}, options, { method: 'PURGE' }), + ); +}; +``` + +## .getOnce(), .postOnce(), .putOnce(), .deleteOnce(), .headOnce(), .patchOnce() + +Creates a route that only responds to a single request using a particular http method + +## .getAny(), .postAny(), .putAny(), .deleteAny(), .headAny(), .patchAny() + +Creates a route that responds to any requests using a particular http method. +As with `.any()`, these only accept the parameters `(response, options)`. + +## .getAnyOnce(), .postAnyOnce(), .putAnyOnce(), .deleteAnyOnce(), .headAnyOnce(), .patchAnyOnce() + +Creates a route that responds to any single request using a particular http method. +As with `.any()`, these only accept the parameters `(response, options)`. + +## .sticky() + +Shorthand for `mock()` which creates a route that persists even when `restore()`, `reset()` or `resetbehavior()` are called; + +This method is particularly useful for setting up fixtures that must remain in place for all tests, e.g. + +```js +fetchMock.sticky(/config-hub.com/, require('./fixtures/start-up-config.json')); +``` diff --git a/docs/docs/APIOld/_category_.json b/docs/docs/APIOld/_category_.json new file mode 100644 index 00000000..cac9949a --- /dev/null +++ b/docs/docs/APIOld/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 8, + "collapsible": false, + "collapsed": false, +} diff --git a/docs/docs/core/fetchHandler.md b/docs/docs/core/fetchHandler.md new file mode 100644 index 00000000..de6e2e77 --- /dev/null +++ b/docs/docs/core/fetchHandler.md @@ -0,0 +1,13 @@ +--- +sidebar_position: 1 +sidebar_label: .fetchHandler +--- +# fetchHandler + +`fetchMock.fetchHandler(url, requestInit)` + +A mock implementation of `fetch`. + +By default it will error. In order to return responses `.route()`, `.catch()` and other convenience methods of `fetchMock` must first be used to add routes to its internal router. + +All calls made using `fetchMock.fetchHandler` are recorded in `fetchMock.callHistory` diff --git a/docs/docs/core/index.md b/docs/docs/core/index.md new file mode 100644 index 00000000..2958c23e --- /dev/null +++ b/docs/docs/core/index.md @@ -0,0 +1,13 @@ +--- +sidebar_label: "@fetch-mock/core" +sidebar_position: 0 +--- +# @fetch-mock/core + +This library implements three main features + +1. A function, `fetchHandler`, that can be used as a drop in replacement for fetch. +2. A set of chainable API methods for adding routes to `fetchHandler`, which alter how it handles different requests. +3. Some low level APIs for accessing the call history of `fetchHandler` (these are not intended for direct use by the developer, but expose enough information for other libraries, such as `@fetch-mock/jest`, to provide more user friendly APIs built on top of this low level functionality). + +`@fetch-mock/core` **DOES NOT** actually replace your `fetch` implementation with `fetchHandler`; again this is left to wrapper libraries such as `@fetch-mock/jest`. This is because different testing frameworks have different opinions about this behaviour, and this core library deliberately avoids making decisions likely to clash with other tools in your testing toolchain. diff --git a/docs/docs/core/inspection-placeholder.md b/docs/docs/core/inspection-placeholder.md new file mode 100644 index 00000000..250be2bb --- /dev/null +++ b/docs/docs/core/inspection-placeholder.md @@ -0,0 +1,2 @@ + +Note that if you use matchers that target anything other than the url string, you may also need to add a `name` to your matcher object so that a) you can add multiple mocks on the same url that differ only in other properties (e.g. query strings or headers) b) if you [inspect](#api-inspectionfundamentals) the result of the fetch calls, retrieving the correct results will be easier. diff --git a/docs/docs/core/route/_category_.json b/docs/docs/core/route/_category_.json new file mode 100644 index 00000000..e93f8486 --- /dev/null +++ b/docs/docs/core/route/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 2.5, + "collapsible": true, + "collapsed": true, +} diff --git a/docs/docs/core/route/index.md b/docs/docs/core/route/index.md new file mode 100644 index 00000000..eb597d14 --- /dev/null +++ b/docs/docs/core/route/index.md @@ -0,0 +1,104 @@ +--- +sidebar_position: 2 +sidebar_label: .route() +--- +# route() + +`fetchMock.route(matcher, response, optionsOrName)` + +Adds a route to `fetchHandler`'s router. A route is a combination of + +- one or more rules for deciding whether a particular fetch request should be handled by the route +- configuration for generating an appropriate response + +## Parameters + +### matcher + +`{String|Regex|Function|Object}` + +Determines which calls to `fetch` should be handled by this route. If multiple criteria need to be applied at once, e.g. matching headers and a uirl pattern, then an object containing multiple matchers may be used. + +### response + +`{String|Object|Function|Promise|Response}` + +Response to send when a call is matched + +### optionsOrName + +`{Object|String}` + +More options to configure matching and response behaviour. Alternatively, when a `String` is provided it will be used as a name for the route (used when inspecting calls or removing routes) + +## Calling with a single options object + +`fetchMock.route(options)` is also supported, where `options` is an object that contains a `{response}` property and any number of matchers and other options. + +## Examples + +### Strings + +```js +fetchMock + .route('http://it.at.here/route', 200) + .route('begin:http://it', 200) + .route('end:here/route', 200) + .route('path:/route', 200) + .route('*', 200); +``` + +### Complex Matchers + +```js +fetchMock + .route(/.*\.here.*/, 200) + .route((url, opts) => opts.method === 'patch', 200) + .route('express:/:type/:id', 200, { + params: { + type: 'shoe', + }, + }) + .route( + { + headers: { Authorization: 'Bearer 123' }, + method: 'POST', + }, + 200, + ); +``` + +### Responses + +```js +fetchMock + .route('*', 'ok') + .route('*', 404) + .route('*', {results: []}) + .route('*', {throw: new Error('Bad kitty'))) + .route('*', new Promise(res => setTimeout(res, 1000, 404))) + .route('*', (url, opts) => { + status: 302, + headers: { + Location: url.replace(/^http/, 'https') + }, + })) +``` + +### End to end example + +```js +fetchMock.route('begin:http://it.at.here/api', 403).route( + { + url: 'begin:http://it.at.here/api', + headers: { + authorization: 'Basic dummy-token', + }, + }, + 200, +); + +callApi('/endpoint', 'dummy-token').then((res) => { + expect(res.status).to.equal(200); +}); +``` diff --git a/docs/docs/core/route/matcher.md b/docs/docs/core/route/matcher.md new file mode 100644 index 00000000..eb4e5236 --- /dev/null +++ b/docs/docs/core/route/matcher.md @@ -0,0 +1,149 @@ +--- +sidebar_position: 1 +--- +# matcher + +Determines whether a route should be used to generate a response for a request. + +URL matchers and function matchers can be passed in as standalone values. They can also be combined with other matchers by passing in an object containing one or more matchers. e.g. + +```js +{ + url: "begin: https://my.site", + method: 'post' +} +``` + + +## URL matchers + +All of the following can be passed in directly as the `matcher` argument or as the property `{url: ...}` when combining with other matchers or options. + +> Note that if using a Full url matcher or `end:`, 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/` + +### Full url + +`{String|URL}` +Match an exact url. Can be defined using a string or a `URL` instance, e.g. `"http://www.site.com/page.html"` + +The value `*` can be used to match any url + +### begin:... + +`{String}` +Match a url beginning with a string, e.g. `"begin:http://www.site.com"` + +### end:... + +`{String}` +Match a url ending with a string, e.g. `"end:.jpg"` + +### path:... + +`{String}` +Match a url which has a given path, e.g. `"path:/posts/2018/7/3"` + +### glob:... + +`{String}` +Match a url using a glob pattern, e.g. `"glob:http://*.*"` + +### RegExp + +`{RegExp}` +Matches a url that satisfies a regular expression, e.g. `/(article|post)\/\d+/` + +### express:... + +`{String}` +Match a url that satisfies an [express style path](https://www.npmjs.com/package/path-to-regexp), e.g. `"express:/user/:user"` + + +#### Matching express param values + +`{Object}` + +When the `express:` keyword is used in a string matcher, it can be combined with the `{params: ...}` matcher to match only requests whose express parameters evaluate to certain values. e.g. + +``` +{ + express: "/:section/user/:user", + params: {"section": "feed", "user": "geoff"} +} +``` + + + + +## Other matching criteria + +### method + +`{String}` + +Match only requests using this http method. Not case-sensitive, e.g. `{method: "get"}`, `{method: "POST"}` + +### headers + +`{Object|Headers}` + +Match only requests that have these headers set, e.g. `{headers: {"Accepts": "text/html"}}` + + +### query + +`{Object}` + +Match only requests that have these query parameters set (in any order). Query parameters are matched by using Node.js [querystring](https://nodejs.org/api/querystring.html) module. In summary the bahaviour is as follows + +- strings, numbers and booleans are coerced to strings +- arrays of values are coerced to repetitions of the key +- all other values, including `undefined`, are coerced to an empty string + The request will be matched whichever order keys appear in the query string. + Any query parameters sent in the request which are not included in the keys of the object provided will be ignored. + +#### Examples + +- `{{query: "q": "cute+kittenz"}}` `?q=cute kittenz` or `?q=cute+kittenz` or `?q=cute+kittenz&mode=big` +- `{{query: "tags": ["cute", "kittenz"]}}` `?tags=cute&tags=kittenz` +- `{{query: "q": undefined, inform: true}}` `?q=&inform=true` + + +### body + +`{Object}` + +Match only requests that send a JSON body with the exact structure and properties as the one provided here. + +Note that if matching on body _and_ using `Request` instances in your source code, this forces fetch-mock into an asynchronous flow _before_ it is able to route requests effectively. This means no [inspection methods](#api-inspectionfundamentals) can be used synchronously. You must first either await the fetches to resolve, or `await fetchMock.flush()`. The popular library [Ky](https://github.com/sindresorhus/ky) uses `Request` instances internally, and so also triggers this mode. + +e.g.`{body: { "key1": "value1", "key2": "value2" }}` + +#### matchPartialBody + +`{Boolean}` + +When matching a body, this option ignores any properties not mentioned in the matcher e.g. the following will ignore any properties of body that are not `"key1"`, and will therefore match the body `{ "key1": "value1", "key2": "value2" }`. +``` +{ + body: { "key1": "value1"}, + matchPartialBody: true +} +``` +This option can also be [set in the global configuration](/dummy) + + +## Function matchers + +`{Function(url, option, [Request]): {Boolean}}` + +For use cases not covered by all the built in matchers, a custom function can be used. It should return `true` to indicate a route should respond to a request. It will be passed the `url` and `options` `fetch` was called with. If `fetch` was called with a `Request` instance, it will be passed `url` and `options` inferred from the `Request` instance, with the original `Request` available as a third argument. + +As well as being passed as a standalone argument, it can also be added to the matcher object as the property `{functionMatcher: ...}` when combining with other matchers or options. + +### Examples + +- `(url, {headers}) => !!headers.Authorization` +- `(_, _, request) => !!request.headers.get('Authorization')` + + diff --git a/docs/docs/core/route/options.md b/docs/docs/core/route/options.md new file mode 100644 index 00000000..202f2ddd --- /dev/null +++ b/docs/docs/core/route/options.md @@ -0,0 +1,61 @@ +--- + +sidebar_position: 3 + +--- +# optionsOrName + +Either + +- An object containing further options for configuring mocking behaviour. +- A string, which will be used as the route's name + +## General options + +### name + +`{String}` + +A unique string naming the route. Used to subsequently retrieve references to the calls handled by it. Only needed for advanced use cases. + +### response + +Instead of defining the response as the second argument of `mock()`, it can be passed as a property on the first argument. See the [response documentation](#usageapimock_response) for valid values. + +### repeat + +`{Int}` + +Limits the number of times the route can be used. If the route has already been called `repeat` times, 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) + +### delay + +`{Int}` + +Delays responding for the number of milliseconds specified. + +### sticky + +`{Boolean}` + +Avoids a route being removed when `reset()`, `restore()` or `resetBehavior()` are called. _Note - this does not preserve the history of calls to the route_ + +### sendAsJson + +`{Boolean}` + +See [global configuration](#usageconfiguration) + +### includeContentLength + +`{Boolean}` + +See [global configuration](#usageconfiguration) + +### overwriteRoutes + +`{Boolean}` + +See [global configuration](#usageconfiguration) + + diff --git a/docs/docs/core/route/response.md b/docs/docs/core/route/response.md new file mode 100644 index 00000000..2b1e5580 --- /dev/null +++ b/docs/docs/core/route/response.md @@ -0,0 +1,80 @@ +--- + +sidebar_position: 2 + +--- +# response + +Configures the http response returned by the mock. Accepts any of the following values or a `Promise` for any of them (useful when testing race conditions, loading transitions etc.). Unless otherwise stated, all responses have a `200` status + +## Argument values + +### Response + +`{Response}` +A [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response) instance to return unaltered. + +Note that it must use the same constructor as that used in the `fetch` implementation your application uses. [See how to configure this](#usagecustom-classes) e.g. `new Response('ok', {status: 200})` + +### Status code + +`{Int}` +Return a `Response` with the given status code. The response's `statusText` will also be set to the [default value corresponding to the status](https://fetch.spec.whatwg.org/#dom-response-statustext), e.g. `200` + +### String + +`{String}` +Return a 200 `Response` with the string as the response body e.g. `"Bad Response"` + +### Response config + +`{Object}` + +If an object _only_ contains properties from among those listed below it is used to configure a `Response` to return. + +#### Object properties + +##### body + +`{String|Object}` +Set the `Response` body. See the non-config `Object` section of the docs below for behaviour when passed an `Object` e.g. `"Server responded ok"`, `{ token: 'abcdef' }` + +##### status + +`{Int}` +Sets the `Response` status e.g. `200` + +##### headers + +`{Object}` +Sets the `Response` headers, e.g `{'Content-Type': 'text/html'}` + +##### redirectUrl + +`{String}` +The url from which the `Response` should claim to originate from (to imitate followed directs). Will also set `redirected: true` on the response + +##### throws + +`{Error}` +Force `fetch` to return a `Promise` rejected with the value of `throws` e.g. `new TypeError('Failed to fetch')` + +### Object + +`{Object|ArrayBuffer|...` +If the `sendAsJson` option is set to `true`, any object that does not meet the criteria above will be converted to a `JSON` string and set as the response `body`. Otherwise, the object will be set as the response `body` (useful for `ArrayBuffer`s etc.) + +### Promise + +`{Promise}` +A `Promise` that resolves to any of the options documented above e.g. `new Promise(res => setTimeout(() => res(200), 50))` + +### Function + +`{Function}` +A function that returns any of the options documented above (including `Promise`. The function will be passed the `url` and `options` `fetch` was called with. If `fetch` was called with a `Request` instance, it will be passed `url` and `options` inferred from the `Request` instance, with the original `Request` passed as a third argument. + +#### Examples + +- `(url, opts) => opts.headers.Authorization ? 200 : 403` +- `(_, _, request) => request.headers.get('Authorization') ? 200 : 403` diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 2ce83d70..ed77c8d8 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -62,6 +62,12 @@ const config = { position: 'left', label: 'Docs', }, + { + type: 'docSidebar', + sidebarId: 'coreSidebar', + position: 'left', + label: 'core', + }, { href: 'https://github.com/wheresrhys/fetch-mock', label: 'GitHub', diff --git a/docs/sidebars.js b/docs/sidebars.js index 23f524dd..40cc392d 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -16,6 +16,7 @@ const sidebars = { // By default, Docusaurus generates a sidebar from the docs folder structure // tutorialSidebar: [{ type: 'autogenerated', dirName: 'tutorial' }], fetchMockSidebar: [{ type: 'autogenerated', dirName: 'fetch-mock' }], + coreSidebar: [{ type: 'autogenerated', dirName: 'core' }], // But you can create a sidebar manually /* From 9139f5a857468d22efbbbba43c53f15f3081527e Mon Sep 17 00:00:00 2001 From: Rhys Evans Date: Fri, 19 Jul 2024 23:43:06 +0100 Subject: [PATCH 02/10] docs: started work documenting the core library --- docs/docs/core/fetchHandler.md | 1 + docs/docs/core/index.md | 3 ++- docs/docs/core/inspection-placeholder.md | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/docs/core/fetchHandler.md b/docs/docs/core/fetchHandler.md index de6e2e77..36e7d59d 100644 --- a/docs/docs/core/fetchHandler.md +++ b/docs/docs/core/fetchHandler.md @@ -2,6 +2,7 @@ sidebar_position: 1 sidebar_label: .fetchHandler --- + # fetchHandler `fetchMock.fetchHandler(url, requestInit)` diff --git a/docs/docs/core/index.md b/docs/docs/core/index.md index 2958c23e..bcb6c78f 100644 --- a/docs/docs/core/index.md +++ b/docs/docs/core/index.md @@ -1,7 +1,8 @@ --- -sidebar_label: "@fetch-mock/core" +sidebar_label: '@fetch-mock/core' sidebar_position: 0 --- + # @fetch-mock/core This library implements three main features diff --git a/docs/docs/core/inspection-placeholder.md b/docs/docs/core/inspection-placeholder.md index 250be2bb..e8abdad3 100644 --- a/docs/docs/core/inspection-placeholder.md +++ b/docs/docs/core/inspection-placeholder.md @@ -1,2 +1 @@ - Note that if you use matchers that target anything other than the url string, you may also need to add a `name` to your matcher object so that a) you can add multiple mocks on the same url that differ only in other properties (e.g. query strings or headers) b) if you [inspect](#api-inspectionfundamentals) the result of the fetch calls, retrieving the correct results will be easier. From fad58fe2996d8bce5540a3ce761ff3bd33a381af Mon Sep 17 00:00:00 2001 From: Rhys Evans Date: Sat, 20 Jul 2024 12:29:22 +0100 Subject: [PATCH 03/10] docs: finished documenting .route() --- docs/docs/core/index.md | 2 +- docs/docs/core/route/index.md | 40 ++++++++++++++++++--- docs/docs/core/route/options.md | 20 ++++------- docs/docs/core/route/response.md | 61 +++++++++++++++++--------------- 4 files changed, 74 insertions(+), 49 deletions(-) diff --git a/docs/docs/core/index.md b/docs/docs/core/index.md index bcb6c78f..8662c45f 100644 --- a/docs/docs/core/index.md +++ b/docs/docs/core/index.md @@ -11,4 +11,4 @@ This library implements three main features 2. A set of chainable API methods for adding routes to `fetchHandler`, which alter how it handles different requests. 3. Some low level APIs for accessing the call history of `fetchHandler` (these are not intended for direct use by the developer, but expose enough information for other libraries, such as `@fetch-mock/jest`, to provide more user friendly APIs built on top of this low level functionality). -`@fetch-mock/core` **DOES NOT** actually replace your `fetch` implementation with `fetchHandler`; again this is left to wrapper libraries such as `@fetch-mock/jest`. This is because different testing frameworks have different opinions about this behaviour, and this core library deliberately avoids making decisions likely to clash with other tools in your testing toolchain. +`@fetch-mock/core` is not intended for direct use in tests. It **DOES NOT** actually replace your `fetch` implementation with `fetchHandler`; this is left to wrapper libraries such as `@fetch-mock/jest`. This is because different testing frameworks have different opinions about this behaviour, and this core library deliberately avoids making decisions likely to clash with other tools in your testing toolchain, so that the `fetchHandler` implementation is more portable. diff --git a/docs/docs/core/route/index.md b/docs/docs/core/route/index.md index eb597d14..edd493ab 100644 --- a/docs/docs/core/route/index.md +++ b/docs/docs/core/route/index.md @@ -4,7 +4,7 @@ sidebar_label: .route() --- # route() -`fetchMock.route(matcher, response, optionsOrName)` +`fetchMock.route(matcher, response, options)` Adds a route to `fetchHandler`'s router. A route is a combination of @@ -25,15 +25,45 @@ Determines which calls to `fetch` should be handled by this route. If multiple c Response to send when a call is matched -### optionsOrName +### options `{Object|String}` -More options to configure matching and response behaviour. Alternatively, when a `String` is provided it will be used as a name for the route (used when inspecting calls or removing routes) +More options to configure matching and response behaviour. Alternatively, when a `String` is provided it will be used as a name for the route (used when inspecting calls or removing routes). -## Calling with a single options object +## Alternate call patterns -`fetchMock.route(options)` is also supported, where `options` is an object that contains a `{response}` property and any number of matchers and other options. +As well as the function signature described above, the following patterns are supported. + +### Name as third parameter + +A string can be passed as the third parameter, and will be used as the route name. e.g. +`fetchMock.route('*', 200, 'catch-all')` is equivalent to `fetchMock.route('*', 200, {name: 'catch-all'})`. + +### Matchers on third parameter + +The matchers specified in the first parameter are merged internally with the options object passed as the third parameter. This means that it does not matter on which of these objects you specify options/matchers. + +This can be particularly useful for clearly and concisely expressing similar routes that only differ in e.g. different query strings or headers e.g. + +```js +fetchMock + .route('http://my.site', 401) + .route('http://my.site', 200, {headers: {auth: true}}) +``` + +### Single options object + +Matchers, options and a response can be combined on a single options object passed into the first parameter, e.g. + +```js +fetchMock.route({ + url: 'http://my.site', + repeat: 2 + response: 200 +}) + +``` ## Examples diff --git a/docs/docs/core/route/options.md b/docs/docs/core/route/options.md index 202f2ddd..26f96c27 100644 --- a/docs/docs/core/route/options.md +++ b/docs/docs/core/route/options.md @@ -3,14 +3,11 @@ sidebar_position: 3 --- -# optionsOrName +# options -Either +An object containing further options for configuring mocking behaviour. -- An object containing further options for configuring mocking behaviour. -- A string, which will be used as the route's name - -## General options +## Options ### name @@ -20,13 +17,13 @@ A unique string naming the route. Used to subsequently retrieve references to th ### response -Instead of defining the response as the second argument of `mock()`, it can be passed as a property on the first argument. See the [response documentation](#usageapimock_response) for valid values. +When using pattern 3. above, `response` can be passed as a property on the options object. See the [response documentation](#usageapimock_response) for valid values. ### repeat `{Int}` -Limits the number of times the route can be used. If the route has already been called `repeat` times, 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) +Limits the number of times the route will be used to respond. If the route has already been called `repeat` times, 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). ### delay @@ -38,7 +35,7 @@ Delays responding for the number of milliseconds specified. `{Boolean}` -Avoids a route being removed when `reset()`, `restore()` or `resetBehavior()` are called. _Note - this does not preserve the history of calls to the route_ +Avoids a route being removed when `removeRoutes()` is called. ### sendAsJson @@ -52,10 +49,5 @@ See [global configuration](#usageconfiguration) See [global configuration](#usageconfiguration) -### overwriteRoutes - -`{Boolean}` - -See [global configuration](#usageconfiguration) diff --git a/docs/docs/core/route/response.md b/docs/docs/core/route/response.md index 2b1e5580..e06f16d7 100644 --- a/docs/docs/core/route/response.md +++ b/docs/docs/core/route/response.md @@ -1,80 +1,83 @@ --- - sidebar_position: 2 - --- # response -Configures the http response returned by the mock. Accepts any of the following values or a `Promise` for any of them (useful when testing race conditions, loading transitions etc.). Unless otherwise stated, all responses have a `200` status +Configures the http response returned by `fetchHandler`. Unless otherwise stated, all responses have a `200` status -## Argument values -### Response +## Response `{Response}` -A [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response) instance to return unaltered. - -Note that it must use the same constructor as that used in the `fetch` implementation your application uses. [See how to configure this](#usagecustom-classes) e.g. `new Response('ok', {status: 200})` -### Status code +A [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response) instance to return unaltered. +## Status code `{Int}` -Return a `Response` with the given status code. The response's `statusText` will also be set to the [default value corresponding to the status](https://fetch.spec.whatwg.org/#dom-response-statustext), e.g. `200` -### String +Returns a `Response` with the given status code, e.g. `200`. The response's `statusText` will also be set to the [default value corresponding to the status](https://fetch.spec.whatwg.org/#dom-response-statustext). + +## String `{String}` -Return a 200 `Response` with the string as the response body e.g. `"Bad Response"` -### Response config +Returns a 200 `Response` with the string as the response body e.g. `"..."` -`{Object}` +## Response config -If an object _only_ contains properties from among those listed below it is used to configure a `Response` to return. +`{Object}` -#### Object properties +If the object _only_ contains properties from among those listed below it is used to configure a `Response` to return. -##### body +### body `{String|Object}` -Set the `Response` body. See the non-config `Object` section of the docs below for behaviour when passed an `Object` e.g. `"Server responded ok"`, `{ token: 'abcdef' }` -##### status +Set the `Response` body, e.g. `"Server responded ok"`, `{ token: 'abcdef' }`. See the `Object` section of the docs below for behaviour when passed an `Object`. + +### status `{Int}` + Sets the `Response` status e.g. `200` -##### headers +### headers `{Object}` + Sets the `Response` headers, e.g `{'Content-Type': 'text/html'}` -##### redirectUrl +### redirectUrl `{String}` -The url from which the `Response` should claim to originate from (to imitate followed directs). Will also set `redirected: true` on the response -##### throws +Sets the url from which the `Response` should claim to originate (to imitate followed directs). Will also set `redirected: true` on the response + +### throws `{Error}` -Force `fetch` to return a `Promise` rejected with the value of `throws` e.g. `new TypeError('Failed to fetch')` -### Object +Forces `fetch` to return a `Promise` rejected with the value of `throws` e.g. `new TypeError('Failed to fetch')` + +## Object `{Object|ArrayBuffer|...` -If the `sendAsJson` option is set to `true`, any object that does not meet the criteria above will be converted to a `JSON` string and set as the response `body`. Otherwise, the object will be set as the response `body` (useful for `ArrayBuffer`s etc.) -### Promise +If the `sendAsJson` option is set to `true`, any object that does not match the schema for a response config will be converted to a `JSON` string and set as the response `body`. Otherwise, the object will be set as the response `body` (useful for `ArrayBuffer`s etc.) + +## Promise `{Promise}` + A `Promise` that resolves to any of the options documented above e.g. `new Promise(res => setTimeout(() => res(200), 50))` -### Function +## Function `{Function}` + A function that returns any of the options documented above (including `Promise`. The function will be passed the `url` and `options` `fetch` was called with. If `fetch` was called with a `Request` instance, it will be passed `url` and `options` inferred from the `Request` instance, with the original `Request` passed as a third argument. -#### Examples +### Examples - `(url, opts) => opts.headers.Authorization ? 200 : 403` - `(_, _, request) => request.headers.get('Authorization') ? 200 : 403` From 478a11dca4ec68c6eea0560ec72a226c5b53eaf5 Mon Sep 17 00:00:00 2001 From: Rhys Evans Date: Sat, 20 Jul 2024 13:04:05 +0100 Subject: [PATCH 04/10] docs: documented call history --- docs/docs/APIOld/Inspection/_category_.json | 5 - docs/docs/APIOld/Inspection/done.md | 27 ---- docs/docs/APIOld/Inspection/flush.md | 12 -- .../APIOld/Inspection/inspecting-calls.md | 132 ------------------ docs/docs/APIOld/Routing/_category_.json | 5 - docs/docs/APIOld/Routing/catch.md | 10 -- docs/docs/core/CallHistory.md | 89 ++++++++++++ docs/docs/core/advanced/_category_.json | 1 + .../Routing => core/advanced}/add-matcher.md | 0 .../routing-shorthands.md} | 48 ++++--- 10 files changed, 121 insertions(+), 208 deletions(-) delete mode 100644 docs/docs/APIOld/Inspection/_category_.json delete mode 100644 docs/docs/APIOld/Inspection/done.md delete mode 100644 docs/docs/APIOld/Inspection/flush.md delete mode 100644 docs/docs/APIOld/Inspection/inspecting-calls.md delete mode 100644 docs/docs/APIOld/Routing/_category_.json delete mode 100644 docs/docs/APIOld/Routing/catch.md create mode 100644 docs/docs/core/CallHistory.md create mode 100644 docs/docs/core/advanced/_category_.json rename docs/docs/{APIOld/Routing => core/advanced}/add-matcher.md (100%) rename docs/docs/{APIOld/Routing/shorthands.md => core/routing-shorthands.md} (69%) diff --git a/docs/docs/APIOld/Inspection/_category_.json b/docs/docs/APIOld/Inspection/_category_.json deleted file mode 100644 index ba14420a..00000000 --- a/docs/docs/APIOld/Inspection/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 5, - "collapsible": true, - "collapsed": true, -} diff --git a/docs/docs/APIOld/Inspection/done.md b/docs/docs/APIOld/Inspection/done.md deleted file mode 100644 index 8313e526..00000000 --- a/docs/docs/APIOld/Inspection/done.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -sidebar_position: 2 - ---- -# .done(filter) - - -Returns a Boolean indicating whether `fetch` was called the expected number of times (or has been called at least once if `repeat` is undefined for the route). It does not take into account whether the `fetches` completed successfully. - -## Filter - -### undefined / true - -Returns true if all routes have been called the expected number of times - -### routeIdentifier - -`{String|RegExp|function}` - -All routes have an identifier: - -- If it's a named route, the identifier is the route's name -- If the route is unnamed, the identifier is the `matcher` passed in to `.mock()` - -Returns true if the routes specified by the identifier has been called the expected number of times - -If several routes have the same matcher/url, but use [mocking options](#apimockingmock_options), the recommended way to handle this is to [name each route](#api-mockingmock_options) and filter using those names diff --git a/docs/docs/APIOld/Inspection/flush.md b/docs/docs/APIOld/Inspection/flush.md deleted file mode 100644 index 84172eef..00000000 --- a/docs/docs/APIOld/Inspection/flush.md +++ /dev/null @@ -1,12 +0,0 @@ ---- - -sidebar_position: 3 ---- -# .flush(waitForBody) - - -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. - -If `waitForBody` is `true`, the promise will wait for all body parsing methods (`res.json()`, `res.text()`, etc.) to resolve too. diff --git a/docs/docs/APIOld/Inspection/inspecting-calls.md b/docs/docs/APIOld/Inspection/inspecting-calls.md deleted file mode 100644 index 160aa7aa..00000000 --- a/docs/docs/APIOld/Inspection/inspecting-calls.md +++ /dev/null @@ -1,132 +0,0 @@ ---- - -sidebar_position: 1 -tableOfContents: - maxHeadingLevel: 5 - ---- -# Inspecting calls - -## Methods - -### .calls(filter, options) - -Returns an array of all calls to fetch matching the given `filter` and `options`. Each call is returned as a `[url, options]` array. If `fetch` was called using a `Request` instance, the `url` and `options` will be inferred from it, and the original `Request` will be available as a `request` property on this array. - -### .called(filter, options) - -Returns a Boolean indicating whether any calls to `fetch` matched the given `filter` and `options` - -### .lastCall(filter, options) - -Returns the arguments for the last call to `fetch` matching the given `filter` and `options`. The call is returned as a `[url, options]` array. If `fetch` was called using a `Request` instance, the `url` and `options` will be inferred from it, and the original `Request` will be available as a `request` property on this array. - -### .lastUrl(filter, options) - -Returns the url for the last call to `fetch` matching the given `filter` and `options`. If `fetch` was last called using a `Request` instance, the url will be inferred from this - -### .lastOptions(filter, options) - -Returns the options for the last call to `fetch` matching the given `filter` and `options`. If `fetch` was last called using a `Request` instance, a set of `options` inferred from the `Request` will be returned - -### .lastResponse(filter, options) - -Returns the `Response` for the last call to `fetch` matching the given `filter` and `options`. This is an experimental feature, very difficult to implement well given fetch's very private treatment of response bodies. - -If `.lastResponse()` is called before fetch has been resolved then it will return `undefined` - -When doing all the following: - -- using node-fetch -- responding with a real network response (using spy() or fallbackToNetwork) -- using \`fetchMock.LastResponse()\` -- awaiting the body content - ... the response will hang unless your source code also awaits the response body. - This is an unavoidable consequence of the nodejs implementation of streams. - -To obtain json/text responses await the `.json()/.text()` methods of the response - -## Filtering - -`fetch-mock`'s inspection methods allow information about how `fetch` was called to be retrieved after your application code has run. Most inspection methods take two arguments — `(filter, options)` — which allow individual, or groups of, `fetch` calls to be extracted and examined. - -### Parameters - -#### filter - -Filter calls to `fetch` using one of the following criteria: - -##### undefined - -Retrieve all calls made to `fetch` - -##### true / "matched" - -Retrieve all calls to `fetch` matched by some route defined by `fetch-mock`. The string `'matched'` can be used instead of `true` to make tests more readable - -##### false / "unmatched" - -Retrieve all calls to `fetch` not matched by some route defined by `fetch-mock`. The string `'unmatched'` can be used instead of `false` to make tests more readable - -##### routeIdentifier - -`{String|RegExp|function}` - -All routes have an identifier: - -- If it's a [named route](#api-mockingmock_options), the identifier is the route's `name` -- If the route is unnamed, the identifier is the value of the `matcher` argument that was passed in to `.mock()` - -All calls that were handled by the route with the given identifier will be retrieved - -##### matcher - -`{String|RegExp|function}` -Any matcher compatible with the [mocking api](#api-mockingmock_matcher) can be passed in to filter the calls arbitrarily. The matcher will be executed using exactly the same rules as the mocking api - -#### options - -`{Object|String}` - -Either an object compatible with the [mocking api](#api-mockingmock_options) or a string specifying a http method to filter by. This will be used to filter the list of calls further - -### Caveats - -#### Confusing API - -The filtering API is powerful, but potentially confusing. If in doubt, [add a `name` to your route](#api-mockingmock_options), and pass that name in to retrieve exactly the calls you want. - -The API will be simplified and changed significantly in the next major version - -#### Regular Expression and Function matchers - -To retrieve calls handled by a route with a `RegExp` or `function` matcher, use a reference to the exact `RegExp`|`function` you used in your mock, e.g. - -```javascript -const matcherRX = /user\/biff/ -fm.mock(matcherRX, 200) -... -fm.called(matcherRX) -``` - -not - -```javascript -fm.mock(/user\/biff/, 200) -... -fm.called(/user\/biff/) -``` - -The second example _will_ retrieve the expected calls in simple test scenarios because if no routes match using the identifier the `RegExp` will be executed as a `RegExp` matcher. But in more complex scenarios where e.g. there are several routes handling similar paths, it might retrieve calls that were actually handled by different, similar route e.g. - -```javascript -const matcherRX = /user\/biff/ -fm - .mock('end:user/biff') - .mock(matcherRX, 200) -... -// this will retrieve calls handled by either route -fm.called(/user\/biff/) -// this will retrieve only calls handled by the second route -fm.called(matcherRX) -``` diff --git a/docs/docs/APIOld/Routing/_category_.json b/docs/docs/APIOld/Routing/_category_.json deleted file mode 100644 index 40b4fc51..00000000 --- a/docs/docs/APIOld/Routing/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 3, - "collapsible": true, - "collapsed": true, -} diff --git a/docs/docs/APIOld/Routing/catch.md b/docs/docs/APIOld/Routing/catch.md deleted file mode 100644 index e6d884a2..00000000 --- a/docs/docs/APIOld/Routing/catch.md +++ /dev/null @@ -1,10 +0,0 @@ ---- - -sidebar_position: 3 - ---- -# .catch(response) - -Specifies how to respond to calls to `fetch` that don't match any mocks. - -It accepts any valid [fetch-mock response](#api-mockingmock_response), and can also take an arbitrary function to completely customise behaviour. If no argument is passed, then every unmatched call will receive a `200` response diff --git a/docs/docs/core/CallHistory.md b/docs/docs/core/CallHistory.md new file mode 100644 index 00000000..eae29535 --- /dev/null +++ b/docs/docs/core/CallHistory.md @@ -0,0 +1,89 @@ +--- +sidebar_position: 4 +--- + +# Call history + +`fetchMock.callHistory` is an object used to record the history of all calls handled by `fetchMock.fetchHandler`. Calls are recorded in a standard format with the following properties: + +## CallLog + +- `{string} url` - The url being fetched +- `{NormalizedRequestOptions} options` - The options passed in to the fetch (may be derived from a `Request` if one was used) +- `{Request} [request]` - The `Request` passed to fetch, if one was used +- `{Route} [route]` - The route used to handle the request +- `{Response} [response]` - The `Response` returned to the user +- `{Promise[]} pendingPromises` - An internal structure used by the `.flush()` method documented below + +`fetchMock.callHistory` exposes the following methods. + +## .recordCall(callLog) + +For internal use. + +## .calls(filter, options) + +Returns an array of all calls matching the given `filter` and `options`. Each call is returned as a `CallLog`. + +## .called(filter, options) + +Returns a Boolean indicating whether any calls to `fetch` matched the given `filter` and `options` + +## .lastCall(filter, options) + +Returns the `CallLog` for the last call to `fetch` matching the given `filter` and `options`. + +## fetchMock.done(routeNames) + +_Note that this function is exposed on the `fetchMock` object, not on `fetchMock.callHistory`_ + +TODO, should callHistory just have access to `routes`... yes probably as these docs are horrible + +Returns a Boolean indicating whether `fetch` was called the expected number of times (or has been called at least once if `repeat` is not defined for the route). It does not take into account whether the `fetches` completed successfully. + +A single name or an array of names can be passed in the `routeNames` parameter to check only certain routes. If no routeNames are passed it runs over all routes. + +## .flush(waitForResponseMethods) + +Returns a `Promise` that resolves once all fetches handled by fetch-mock have resolved + +Useful for testing code that uses `fetch` but where the returned promise cannot be accessed from your tests. + +If `waitForBody` is `true`, the promise will wait for all body parsing methods (`res.json()`, `res.text()`, etc.) to resolve too. + +## Filtering + +Most of `fetchMock.callHistory`'s methods take two arguments — `(filter, options)` — which allow individual, or groups of, `fetch` calls to be extracted and examined. + +### filter + +Filter calls to `fetch` using one of the following criteria: + +#### undefined + +Retrieve all calls made to `fetch` + +#### true / "matched" + +Retrieve all calls to `fetch` matched by some route defined by `fetch-mock`. The string `'matched'` can be used instead of `true` to make tests more readable + +#### false / "unmatched" + +Retrieve all calls to `fetch` not matched by some route defined by `fetch-mock`, i.e. calls that are handled by `.catch()`. The string `'unmatched'` can be used instead of `false` to make tests more readable + +#### name + +`{String}` + +Retrieve all calls to `fetch` matched by a particular named route. + +#### matcher + +`{String|RegExp|function|Object}` +Any matcher compatible with the [route api](#api-mockingmock_matcher) can be passed in to filter the calls arbitrarily. + +### options + +`{Object}` + +An options object compatible with the [route api](#api-mockingmock_options) to be used to filter the list of calls further. diff --git a/docs/docs/core/advanced/_category_.json b/docs/docs/core/advanced/_category_.json new file mode 100644 index 00000000..8373896d --- /dev/null +++ b/docs/docs/core/advanced/_category_.json @@ -0,0 +1 @@ +{"position": 500, "label": "Advanced usage"} diff --git a/docs/docs/APIOld/Routing/add-matcher.md b/docs/docs/core/advanced/add-matcher.md similarity index 100% rename from docs/docs/APIOld/Routing/add-matcher.md rename to docs/docs/core/advanced/add-matcher.md diff --git a/docs/docs/APIOld/Routing/shorthands.md b/docs/docs/core/routing-shorthands.md similarity index 69% rename from docs/docs/APIOld/Routing/shorthands.md rename to docs/docs/core/routing-shorthands.md index e59680db..f7be9c1a 100644 --- a/docs/docs/APIOld/Routing/shorthands.md +++ b/docs/docs/core/routing-shorthands.md @@ -1,22 +1,44 @@ --- -sidebar_position: 2 - +sidebar_position: 3 +sidebar_label: Shorthands, .get(), .once() etc. --- -# Shorthand methods +# Routing shorthands + +These methods allow defining routes for common use cases while avoiding writing hard to read configuration objects. Unless noted otherwise, each of the methods below have the same signature as `.route()` + +## .catch() + +`.catch(response)` + +Specifies how to respond to calls to `fetch` that don't match any routes. + +It accepts any [response](#api-mockingmock_response) compatible with `.route()`. If no argument is passed, then every unmatched call will receive a `200` response. + +## .sticky() -These methods allow configuring routes for common use cases while avoiding writing configuration objects. Unless noted otherwise, each of the methods below have the same signature as `.mock(matcher, response, optionsOrName)` +Shorthand for `mock()` which creates a route that persists even when `restore()`, `reset()` or `resetbehavior()` are called; + +This method is particularly useful for setting up fixtures that must remain in place for all tests, e.g. + +```js +fetchMock.sticky(/config-hub.com/, require('./fixtures/start-up-config.json')); +``` ## .once() Shorthand for `mock()` which creates a route that can only mock a single request. (see `repeat` option above) -## .any(response, options) +## .any() + +`.any(response, options)` Shorthand for `mock()` which creates a route that will return a response to any fetch request. ## .anyOnce(response, options) +`.anyOnce(response, options)` + Creates a route that responds to any single request ## .get(), .post(), .put(), .delete(), .head(), .patch() @@ -41,20 +63,12 @@ Creates a route that only responds to a single request using a particular http m ## .getAny(), .postAny(), .putAny(), .deleteAny(), .headAny(), .patchAny() +`.___Any(response, options)` + Creates a route that responds to any requests using a particular http method. -As with `.any()`, these only accept the parameters `(response, options)`. ## .getAnyOnce(), .postAnyOnce(), .putAnyOnce(), .deleteAnyOnce(), .headAnyOnce(), .patchAnyOnce() -Creates a route that responds to any single request using a particular http method. -As with `.any()`, these only accept the parameters `(response, options)`. - -## .sticky() - -Shorthand for `mock()` which creates a route that persists even when `restore()`, `reset()` or `resetbehavior()` are called; - -This method is particularly useful for setting up fixtures that must remain in place for all tests, e.g. +`.___AnyOnce(response, options)` -```js -fetchMock.sticky(/config-hub.com/, require('./fixtures/start-up-config.json')); -``` +Creates a route that responds to any single request using a particular http method. From 42cc820c2a52acd939b0091b1440a856416f7c00 Mon Sep 17 00:00:00 2001 From: Rhys Evans Date: Sat, 20 Jul 2024 13:23:42 +0100 Subject: [PATCH 05/10] docs: documented resetting methods --- docs/docs/APIOld/Lifecycle/_category_.json | 5 -- docs/docs/APIOld/Lifecycle/resetting.md | 22 ----- docs/docs/APIOld/Lifecycle/sandbox.md | 12 --- docs/docs/APIOld/_category_.json | 5 -- docs/docs/core/CallHistory.md | 83 ++++++++++--------- docs/docs/core/fetchHandler.md | 4 +- ...-shorthands.md => more-routing-methods.md} | 4 +- docs/docs/core/resetting.md | 44 ++++++++++ docs/docs/core/route/_category_.json | 4 +- 9 files changed, 95 insertions(+), 88 deletions(-) delete mode 100644 docs/docs/APIOld/Lifecycle/_category_.json delete mode 100644 docs/docs/APIOld/Lifecycle/resetting.md delete mode 100644 docs/docs/APIOld/Lifecycle/sandbox.md delete mode 100644 docs/docs/APIOld/_category_.json rename docs/docs/core/{routing-shorthands.md => more-routing-methods.md} (96%) create mode 100644 docs/docs/core/resetting.md diff --git a/docs/docs/APIOld/Lifecycle/_category_.json b/docs/docs/APIOld/Lifecycle/_category_.json deleted file mode 100644 index 40b4fc51..00000000 --- a/docs/docs/APIOld/Lifecycle/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 3, - "collapsible": true, - "collapsed": true, -} diff --git a/docs/docs/APIOld/Lifecycle/resetting.md b/docs/docs/APIOld/Lifecycle/resetting.md deleted file mode 100644 index 234b93a4..00000000 --- a/docs/docs/APIOld/Lifecycle/resetting.md +++ /dev/null @@ -1,22 +0,0 @@ ---- - -sidebar_position: 2 ---- -# Resetting - - -## .restore() / .reset() - -Resets `fetch()` to its unstubbed state and clears all data recorded for its calls. `restore()` is an alias for `reset()`. Optionally pass in a `{sticky: true}` option to remove even sticky routes. - -Both methods are bound to fetchMock, and can be used directly as callbacks e.g. `afterEach(fetchMock.reset)` will work just fine. There is no need for `afterEach(() => fetchMock.reset())` - -## .resetHistory() - -Clears all data recorded for `fetch`'s calls. It _will not_ restore fetch to its default implementation - -`resetHistory()` is bound to fetchMock, and can be used directly as a callback e.g. `afterEach(fetchMock.resetHistory)` will work just fine. There is no need for `afterEach(() => fetchMock.resetHistory())` - -## .resetBehavior() - -Removes all mock routes from the instance of `fetch-mock`, and restores `fetch` to its original implementation if mocking globally. Will not clear data recorded for `fetch`'s calls. Optionally pass in a `{sticky: true}` option to remove even sticky routes. diff --git a/docs/docs/APIOld/Lifecycle/sandbox.md b/docs/docs/APIOld/Lifecycle/sandbox.md deleted file mode 100644 index 83a891dc..00000000 --- a/docs/docs/APIOld/Lifecycle/sandbox.md +++ /dev/null @@ -1,12 +0,0 @@ ---- - -sidebar_position: 1 - ---- -# .sandbox() - -Returns a function that can be used as a drop-in replacement for `fetch`. Pass this into your mocking library of choice. The function returned by `sandbox()` has all the methods of `fetch-mock` exposed on it and maintains its own state independent of other instances, so tests can be run in parallel. - -```js -fetchMock.sandbox().mock('http://domain.com', 200); -``` diff --git a/docs/docs/APIOld/_category_.json b/docs/docs/APIOld/_category_.json deleted file mode 100644 index cac9949a..00000000 --- a/docs/docs/APIOld/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "position": 8, - "collapsible": false, - "collapsed": false, -} diff --git a/docs/docs/core/CallHistory.md b/docs/docs/core/CallHistory.md index eae29535..8c0ff947 100644 --- a/docs/docs/core/CallHistory.md +++ b/docs/docs/core/CallHistory.md @@ -4,9 +4,11 @@ sidebar_position: 4 # Call history -`fetchMock.callHistory` is an object used to record the history of all calls handled by `fetchMock.fetchHandler`. Calls are recorded in a standard format with the following properties: +`fetchMock.callHistory` is an object used to record the history of all calls handled by `fetchMock.fetchHandler`. -## CallLog +## CallLog schema + +Calls are recorded, and returned, in a standard format with the following properties: - `{string} url` - The url being fetched - `{NormalizedRequestOptions} options` - The options passed in to the fetch (may be derived from a `Request` if one was used) @@ -15,45 +17,9 @@ sidebar_position: 4 - `{Response} [response]` - The `Response` returned to the user - `{Promise[]} pendingPromises` - An internal structure used by the `.flush()` method documented below -`fetchMock.callHistory` exposes the following methods. - -## .recordCall(callLog) - -For internal use. - -## .calls(filter, options) - -Returns an array of all calls matching the given `filter` and `options`. Each call is returned as a `CallLog`. - -## .called(filter, options) - -Returns a Boolean indicating whether any calls to `fetch` matched the given `filter` and `options` - -## .lastCall(filter, options) - -Returns the `CallLog` for the last call to `fetch` matching the given `filter` and `options`. - -## fetchMock.done(routeNames) - -_Note that this function is exposed on the `fetchMock` object, not on `fetchMock.callHistory`_ - -TODO, should callHistory just have access to `routes`... yes probably as these docs are horrible - -Returns a Boolean indicating whether `fetch` was called the expected number of times (or has been called at least once if `repeat` is not defined for the route). It does not take into account whether the `fetches` completed successfully. - -A single name or an array of names can be passed in the `routeNames` parameter to check only certain routes. If no routeNames are passed it runs over all routes. - -## .flush(waitForResponseMethods) - -Returns a `Promise` that resolves once all fetches handled by fetch-mock have resolved - -Useful for testing code that uses `fetch` but where the returned promise cannot be accessed from your tests. - -If `waitForBody` is `true`, the promise will wait for all body parsing methods (`res.json()`, `res.text()`, etc.) to resolve too. - ## Filtering -Most of `fetchMock.callHistory`'s methods take two arguments — `(filter, options)` — which allow individual, or groups of, `fetch` calls to be extracted and examined. +Most of `fetchMock.callHistory`'s methods take two arguments — `(filter, options)` — which allow `fetch` calls to be extracted and examined. ### filter @@ -87,3 +53,42 @@ Any matcher compatible with the [route api](#api-mockingmock_matcher) can be pas `{Object}` An options object compatible with the [route api](#api-mockingmock_options) to be used to filter the list of calls further. + +## Methods +`fetchMock.callHistory` exposes the following methods. + +### .recordCall(callLog) + +For internal use. + +### .calls(filter, options) + +Returns an array of all calls matching the given `filter` and `options`. Each call is returned as a `CallLog`. + +### .called(filter, options) + +Returns a Boolean indicating whether any calls to `fetch` matched the given `filter` and `options` + +### .lastCall(filter, options) + +Returns the `CallLog` for the last call to `fetch` matching the given `filter` and `options`. + +### fetchMock.done(routeNames) + +_Note that this function is exposed on the `fetchMock` object, not on `fetchMock.callHistory`_ + +TODO, should callHistory just have access to `routes`... yes probably as these docs are horrible + +Returns a Boolean indicating whether `fetch` was called the expected number of times (or has been called at least once if `repeat` is not defined for the route). It does not take into account whether the `fetches` completed successfully. + +A single name or an array of names can be passed in the `routeNames` parameter to check only certain routes. If no routeNames are passed it runs over all routes. + +### .flush(waitForResponseMethods) + +Returns a `Promise` that resolves once all fetches handled by fetch-mock have resolved + +Useful for testing code that uses `fetch` but where the returned promise cannot be accessed from your tests. + +If `waitForBody` is `true`, the promise will wait for all body parsing methods (`res.json()`, `res.text()`, etc.) to resolve too. + + diff --git a/docs/docs/core/fetchHandler.md b/docs/docs/core/fetchHandler.md index 36e7d59d..921cf8c5 100644 --- a/docs/docs/core/fetchHandler.md +++ b/docs/docs/core/fetchHandler.md @@ -11,4 +11,6 @@ A mock implementation of `fetch`. By default it will error. In order to return responses `.route()`, `.catch()` and other convenience methods of `fetchMock` must first be used to add routes to its internal router. -All calls made using `fetchMock.fetchHandler` are recorded in `fetchMock.callHistory` +All calls made using `fetchMock.fetchHandler` are recorded in `fetchMock.callHistory`. + + diff --git a/docs/docs/core/routing-shorthands.md b/docs/docs/core/more-routing-methods.md similarity index 96% rename from docs/docs/core/routing-shorthands.md rename to docs/docs/core/more-routing-methods.md index f7be9c1a..36e0ef1f 100644 --- a/docs/docs/core/routing-shorthands.md +++ b/docs/docs/core/more-routing-methods.md @@ -1,9 +1,9 @@ --- sidebar_position: 3 -sidebar_label: Shorthands, .get(), .once() etc. +sidebar_label: More routing methods --- -# Routing shorthands +# More routing methods These methods allow defining routes for common use cases while avoiding writing hard to read configuration objects. Unless noted otherwise, each of the methods below have the same signature as `.route()` diff --git a/docs/docs/core/resetting.md b/docs/docs/core/resetting.md new file mode 100644 index 00000000..6ddda213 --- /dev/null +++ b/docs/docs/core/resetting.md @@ -0,0 +1,44 @@ +--- + +sidebar_position: 5 +--- + +# Resetting +The methods below can be used to restore some or all of fetchMock's behaviour toits default state. + +## .removeRoutes(options) + +This method removes some or all of the routes that have been added to fetch mock. It accepts the following options. + +### names +An array of named routes to remove. If no value is passed then all routes compatible with the other options passed are removed. + +### includeSticky +A boolean indicating whether or not to remove sticky routes. + +### includeFallback +A boolean indicating whether or not to remove the fallback route (added using `.catch()`) + + +## .clearHistory() +Clears all data recorded for `fetch`'s calls. + +## .createInstance() + +Can be used to create a standalone instance of fetch mock that is completely independent of other instances. + +In older environments - where `fetch` was not a global and test files often ran in a shared process - this was very useful for increasing parallelisation. But in more modern setups - global `fetch` and isolated processes per test file - it's less relevant. + +It can however be used as an alternative to `fetchMock.removeRoutes().clearHistory()` by creating a completely new fetchMock instance and swapping this for the previously used one. + +It can also be used to "fork" a previous instance as routes are cloned from one instance to another. However call history is always reset for new instances. + +```js +fetchMock.route('http://my.site', 200) +fetchMock.fetchHandler('http://my.site') + +const newFM = fetchMock.createInstance(); + +newFM.routes.routes // Array[1] +newFM.callHistory.calls() // Array[0] +``` diff --git a/docs/docs/core/route/_category_.json b/docs/docs/core/route/_category_.json index e93f8486..98a74b37 100644 --- a/docs/docs/core/route/_category_.json +++ b/docs/docs/core/route/_category_.json @@ -1,5 +1,5 @@ { "position": 2.5, - "collapsible": true, - "collapsed": true, + "collapsible": false, + "collapsed": false, } From 2041bb026281550231be52a05fb1914ea3271c67 Mon Sep 17 00:00:00 2001 From: Rhys Evans Date: Sat, 20 Jul 2024 13:28:37 +0100 Subject: [PATCH 06/10] docs: added structure to document multiple libraries --- .../{ => @fetch-mock}/core/CallHistory.md | 5 ++--- .../core/advanced/_category_.json | 0 .../core/advanced/add-matcher.md | 0 .../{ => @fetch-mock}/core/fetchHandler.md | 2 -- docs/docs/{ => @fetch-mock}/core/index.md | 2 +- .../core/inspection-placeholder.md | 0 .../core/more-routing-methods.md | 0 docs/docs/{ => @fetch-mock}/core/resetting.md | 19 +++++++++++-------- .../core/route/_category_.json | 0 .../{ => @fetch-mock}/core/route/index.md | 0 .../{ => @fetch-mock}/core/route/matcher.md | 0 .../{ => @fetch-mock}/core/route/options.md | 0 .../{ => @fetch-mock}/core/route/response.md | 0 docs/docs/@fetch-mock/index.md | 6 ++++++ docs/docusaurus.config.js | 6 +++--- docs/sidebars.js | 2 +- 16 files changed, 24 insertions(+), 18 deletions(-) rename docs/docs/{ => @fetch-mock}/core/CallHistory.md (98%) rename docs/docs/{ => @fetch-mock}/core/advanced/_category_.json (100%) rename docs/docs/{ => @fetch-mock}/core/advanced/add-matcher.md (100%) rename docs/docs/{ => @fetch-mock}/core/fetchHandler.md (99%) rename docs/docs/{ => @fetch-mock}/core/index.md (98%) rename docs/docs/{ => @fetch-mock}/core/inspection-placeholder.md (100%) rename docs/docs/{ => @fetch-mock}/core/more-routing-methods.md (100%) rename docs/docs/{ => @fetch-mock}/core/resetting.md (86%) rename docs/docs/{ => @fetch-mock}/core/route/_category_.json (100%) rename docs/docs/{ => @fetch-mock}/core/route/index.md (100%) rename docs/docs/{ => @fetch-mock}/core/route/matcher.md (100%) rename docs/docs/{ => @fetch-mock}/core/route/options.md (100%) rename docs/docs/{ => @fetch-mock}/core/route/response.md (100%) create mode 100644 docs/docs/@fetch-mock/index.md diff --git a/docs/docs/core/CallHistory.md b/docs/docs/@fetch-mock/core/CallHistory.md similarity index 98% rename from docs/docs/core/CallHistory.md rename to docs/docs/@fetch-mock/core/CallHistory.md index 8c0ff947..62a46780 100644 --- a/docs/docs/core/CallHistory.md +++ b/docs/docs/@fetch-mock/core/CallHistory.md @@ -4,7 +4,7 @@ sidebar_position: 4 # Call history -`fetchMock.callHistory` is an object used to record the history of all calls handled by `fetchMock.fetchHandler`. +`fetchMock.callHistory` is an object used to record the history of all calls handled by `fetchMock.fetchHandler`. ## CallLog schema @@ -55,6 +55,7 @@ Any matcher compatible with the [route api](#api-mockingmock_matcher) can be pas An options object compatible with the [route api](#api-mockingmock_options) to be used to filter the list of calls further. ## Methods + `fetchMock.callHistory` exposes the following methods. ### .recordCall(callLog) @@ -90,5 +91,3 @@ Returns a `Promise` that resolves once all fetches handled by fetch-mock have re Useful for testing code that uses `fetch` but where the returned promise cannot be accessed from your tests. If `waitForBody` is `true`, the promise will wait for all body parsing methods (`res.json()`, `res.text()`, etc.) to resolve too. - - diff --git a/docs/docs/core/advanced/_category_.json b/docs/docs/@fetch-mock/core/advanced/_category_.json similarity index 100% rename from docs/docs/core/advanced/_category_.json rename to docs/docs/@fetch-mock/core/advanced/_category_.json diff --git a/docs/docs/core/advanced/add-matcher.md b/docs/docs/@fetch-mock/core/advanced/add-matcher.md similarity index 100% rename from docs/docs/core/advanced/add-matcher.md rename to docs/docs/@fetch-mock/core/advanced/add-matcher.md diff --git a/docs/docs/core/fetchHandler.md b/docs/docs/@fetch-mock/core/fetchHandler.md similarity index 99% rename from docs/docs/core/fetchHandler.md rename to docs/docs/@fetch-mock/core/fetchHandler.md index 921cf8c5..64b01b29 100644 --- a/docs/docs/core/fetchHandler.md +++ b/docs/docs/@fetch-mock/core/fetchHandler.md @@ -12,5 +12,3 @@ A mock implementation of `fetch`. By default it will error. In order to return responses `.route()`, `.catch()` and other convenience methods of `fetchMock` must first be used to add routes to its internal router. All calls made using `fetchMock.fetchHandler` are recorded in `fetchMock.callHistory`. - - diff --git a/docs/docs/core/index.md b/docs/docs/@fetch-mock/core/index.md similarity index 98% rename from docs/docs/core/index.md rename to docs/docs/@fetch-mock/core/index.md index 8662c45f..101d9976 100644 --- a/docs/docs/core/index.md +++ b/docs/docs/@fetch-mock/core/index.md @@ -1,6 +1,6 @@ --- sidebar_label: '@fetch-mock/core' -sidebar_position: 0 +sidebar_position: 1 --- # @fetch-mock/core diff --git a/docs/docs/core/inspection-placeholder.md b/docs/docs/@fetch-mock/core/inspection-placeholder.md similarity index 100% rename from docs/docs/core/inspection-placeholder.md rename to docs/docs/@fetch-mock/core/inspection-placeholder.md diff --git a/docs/docs/core/more-routing-methods.md b/docs/docs/@fetch-mock/core/more-routing-methods.md similarity index 100% rename from docs/docs/core/more-routing-methods.md rename to docs/docs/@fetch-mock/core/more-routing-methods.md diff --git a/docs/docs/core/resetting.md b/docs/docs/@fetch-mock/core/resetting.md similarity index 86% rename from docs/docs/core/resetting.md rename to docs/docs/@fetch-mock/core/resetting.md index 6ddda213..98072f32 100644 --- a/docs/docs/core/resetting.md +++ b/docs/docs/@fetch-mock/core/resetting.md @@ -1,9 +1,9 @@ --- - sidebar_position: 5 --- # Resetting + The methods below can be used to restore some or all of fetchMock's behaviour toits default state. ## .removeRoutes(options) @@ -11,34 +11,37 @@ The methods below can be used to restore some or all of fetchMock's behaviour to This method removes some or all of the routes that have been added to fetch mock. It accepts the following options. ### names -An array of named routes to remove. If no value is passed then all routes compatible with the other options passed are removed. + +An array of named routes to remove. If no value is passed then all routes compatible with the other options passed are removed. ### includeSticky + A boolean indicating whether or not to remove sticky routes. ### includeFallback -A boolean indicating whether or not to remove the fallback route (added using `.catch()`) +A boolean indicating whether or not to remove the fallback route (added using `.catch()`) ## .clearHistory() + Clears all data recorded for `fetch`'s calls. ## .createInstance() Can be used to create a standalone instance of fetch mock that is completely independent of other instances. -In older environments - where `fetch` was not a global and test files often ran in a shared process - this was very useful for increasing parallelisation. But in more modern setups - global `fetch` and isolated processes per test file - it's less relevant. +In older environments - where `fetch` was not a global and test files often ran in a shared process - this was very useful for increasing parallelisation. But in more modern setups - global `fetch` and isolated processes per test file - it's less relevant. It can however be used as an alternative to `fetchMock.removeRoutes().clearHistory()` by creating a completely new fetchMock instance and swapping this for the previously used one. It can also be used to "fork" a previous instance as routes are cloned from one instance to another. However call history is always reset for new instances. ```js -fetchMock.route('http://my.site', 200) -fetchMock.fetchHandler('http://my.site') +fetchMock.route('http://my.site', 200); +fetchMock.fetchHandler('http://my.site'); const newFM = fetchMock.createInstance(); -newFM.routes.routes // Array[1] -newFM.callHistory.calls() // Array[0] +newFM.routes.routes; // Array[1] +newFM.callHistory.calls(); // Array[0] ``` diff --git a/docs/docs/core/route/_category_.json b/docs/docs/@fetch-mock/core/route/_category_.json similarity index 100% rename from docs/docs/core/route/_category_.json rename to docs/docs/@fetch-mock/core/route/_category_.json diff --git a/docs/docs/core/route/index.md b/docs/docs/@fetch-mock/core/route/index.md similarity index 100% rename from docs/docs/core/route/index.md rename to docs/docs/@fetch-mock/core/route/index.md diff --git a/docs/docs/core/route/matcher.md b/docs/docs/@fetch-mock/core/route/matcher.md similarity index 100% rename from docs/docs/core/route/matcher.md rename to docs/docs/@fetch-mock/core/route/matcher.md diff --git a/docs/docs/core/route/options.md b/docs/docs/@fetch-mock/core/route/options.md similarity index 100% rename from docs/docs/core/route/options.md rename to docs/docs/@fetch-mock/core/route/options.md diff --git a/docs/docs/core/route/response.md b/docs/docs/@fetch-mock/core/route/response.md similarity index 100% rename from docs/docs/core/route/response.md rename to docs/docs/@fetch-mock/core/route/response.md diff --git a/docs/docs/@fetch-mock/index.md b/docs/docs/@fetch-mock/index.md new file mode 100644 index 00000000..4e1f3010 --- /dev/null +++ b/docs/docs/@fetch-mock/index.md @@ -0,0 +1,6 @@ +--- +sidebar_position: 0 +--- +# @fetch-mock suite + +This is a new, work in progress suite of libraries intended to replace fetch-mock. diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index ed77c8d8..34e45429 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -60,13 +60,13 @@ const config = { type: 'docSidebar', sidebarId: 'fetchMockSidebar', position: 'left', - label: 'Docs', + label: 'fetch-mock docs', }, { type: 'docSidebar', - sidebarId: 'coreSidebar', + sidebarId: 'suiteSidebar', position: 'left', - label: 'core', + label: '@fetch-mock docs', }, { href: 'https://github.com/wheresrhys/fetch-mock', diff --git a/docs/sidebars.js b/docs/sidebars.js index 40cc392d..f2deec48 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -16,7 +16,7 @@ const sidebars = { // By default, Docusaurus generates a sidebar from the docs folder structure // tutorialSidebar: [{ type: 'autogenerated', dirName: 'tutorial' }], fetchMockSidebar: [{ type: 'autogenerated', dirName: 'fetch-mock' }], - coreSidebar: [{ type: 'autogenerated', dirName: 'core' }], + suiteSidebar: [{ type: 'autogenerated', dirName: '@fetch-mock' }], // But you can create a sidebar manually /* From 8b71559c31ea464c0aec988034d24f1fc2bbea2b Mon Sep 17 00:00:00 2001 From: Rhys Evans Date: Sat, 20 Jul 2024 13:36:16 +0100 Subject: [PATCH 07/10] docs: moved addmatcher docs into routing methods docs --- .../@fetch-mock/core/advanced/_category_.json | 1 - .../@fetch-mock/core/advanced/add-matcher.md | 68 ------------------ .../core/inspection-placeholder.md | 1 - .../@fetch-mock/core/more-routing-methods.md | 70 +++++++++++++++++++ docs/docs/@fetch-mock/index.md | 1 + docs/docusaurus.config.js | 1 + docs/sidebars.js | 13 ---- docs/src/css/custom.css | 11 +++ 8 files changed, 83 insertions(+), 83 deletions(-) delete mode 100644 docs/docs/@fetch-mock/core/advanced/_category_.json delete mode 100644 docs/docs/@fetch-mock/core/advanced/add-matcher.md delete mode 100644 docs/docs/@fetch-mock/core/inspection-placeholder.md diff --git a/docs/docs/@fetch-mock/core/advanced/_category_.json b/docs/docs/@fetch-mock/core/advanced/_category_.json deleted file mode 100644 index 8373896d..00000000 --- a/docs/docs/@fetch-mock/core/advanced/_category_.json +++ /dev/null @@ -1 +0,0 @@ -{"position": 500, "label": "Advanced usage"} diff --git a/docs/docs/@fetch-mock/core/advanced/add-matcher.md b/docs/docs/@fetch-mock/core/advanced/add-matcher.md deleted file mode 100644 index d8f40e61..00000000 --- a/docs/docs/@fetch-mock/core/advanced/add-matcher.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -sidebar_position: 3 ---- -# .addMatcher(options) - - -Allows adding your own, reusable custom matchers to fetch-mock, for example a matcher for interacting with GraphQL queries, or an `isAuthorized` matcher that encapsulates the exact authorization conditions for the API you are mocking, and only requires a `true` or `false` to be input - -## Options - -### name - -`{String}` - -The name of your matcher. This will be the name of the property used to hold any input to your matcher. e.g. `graphqlVariables` - -### usesBody - -`{Boolean}` - -If your matcher requires access to the body of the request set this to true; because body can, in some cases, only be accessed by fetch-mock asynchronously, you will need to provide this hint in order to make sure the correct code paths are followed. - -### matcher - -`{Function}` - -A function which takes a route definition object as input, and returns a function of the signature `(url, options, request) => Boolean`. See the examples below for more detail. The function is passed the fetchMock instance as a second parameter in case you need to access any config. - -#### Examples - -##### Authorization - -```js -fetchMock - .addMatcher({ - name: 'isAuthorized', - matcher: - ({ isAuthorized }) => - (url, options) => { - const actuallyIsAuthorized = options.headers && options.headers.auth; - return isAuthorized ? actuallyIsAuthorized : !actuallyIsAuthorized; - }, - }) - .mock({ isAuthorized: true }, 200) - .mock({ isAuthorized: false }, 401); -``` - -##### GraphQL - -```js -fetchMock - .addMatcher({ - name: 'graphqlVariables', - matcher: ({graphqlVariables}) => (url, options) => { - if (!/\/graphql$/.test(url)) { - return false; - } - const body = JSON.parse(options.body) - return body.variables && Object.keys(body.variables).length === Object.keys(body.graphqlVariables).length && Object.entries(graphqlVariables).every(([key, val]) => body.variables[key] === val) - } - }) - .mock({graphqlVariables: {owner: 'wheresrhys'}}, {data: {account: { - name: 'wheresrhys', - repos: [ ... ] - }}}) -``` - -One intent behind this functionality is to allow companies or publishers of particular toolsets to provide packages that extend fetch-mock to provide a more user friendly experience for developers using fetch to interact with their APIs. The GraphQL use case is a good example of this - the things which a developer might want to match on are buried in the request body, and written in a non-javascript query language. Please get in touch if you'd like to collaborate on writing such a package. diff --git a/docs/docs/@fetch-mock/core/inspection-placeholder.md b/docs/docs/@fetch-mock/core/inspection-placeholder.md deleted file mode 100644 index e8abdad3..00000000 --- a/docs/docs/@fetch-mock/core/inspection-placeholder.md +++ /dev/null @@ -1 +0,0 @@ -Note that if you use matchers that target anything other than the url string, you may also need to add a `name` to your matcher object so that a) you can add multiple mocks on the same url that differ only in other properties (e.g. query strings or headers) b) if you [inspect](#api-inspectionfundamentals) the result of the fetch calls, retrieving the correct results will be easier. diff --git a/docs/docs/@fetch-mock/core/more-routing-methods.md b/docs/docs/@fetch-mock/core/more-routing-methods.md index 36e0ef1f..d8654cc5 100644 --- a/docs/docs/@fetch-mock/core/more-routing-methods.md +++ b/docs/docs/@fetch-mock/core/more-routing-methods.md @@ -72,3 +72,73 @@ Creates a route that responds to any requests using a particular http method. `.___AnyOnce(response, options)` Creates a route that responds to any single request using a particular http method. + + + +## .addMatcher(options) + + +Allows adding your own, reusable custom matchers to fetch-mock, for example a matcher for interacting with GraphQL queries, or an `isAuthorized` matcher that encapsulates the exact authorization conditions for the API you are mocking, and only requires a `true` or `false` to be input + +### Options + +#### name + +`{String}` + +The name of your matcher. This will be the name of the property used to hold any input to your matcher. e.g. `graphqlVariables` + +#### usesBody + +`{Boolean}` + +If your matcher requires access to the body of the request set this to true; because body can, in some cases, only be accessed by fetch-mock asynchronously, you will need to provide this hint in order to make sure the correct code paths are followed. + +#### matcher + +`{Function}` + +A function which takes a route definition object as input, and returns a function of the signature `(url, options, request) => Boolean`. See the examples below for more detail. The function is passed the fetchMock instance as a second parameter in case you need to access any config. + +##### Examples + +###### Authorization + +```js +fetchMock + .addMatcher({ + name: 'isAuthorized', + matcher: + ({ isAuthorized }) => + (url, options) => { + const actuallyIsAuthorized = options.headers && options.headers.auth; + return isAuthorized ? actuallyIsAuthorized : !actuallyIsAuthorized; + }, + }) + .mock({ isAuthorized: true }, 200) + .mock({ isAuthorized: false }, 401); +``` + +###### GraphQL + +```js +fetchMock + .addMatcher({ + name: 'graphqlVariables', + matcher: ({graphqlVariables}) => (url, options) => { + if (!/\/graphql$/.test(url)) { + return false; + } + const body = JSON.parse(options.body) + return body.variables && Object.keys(body.variables).length === Object.keys(body.graphqlVariables).length && Object.entries(graphqlVariables).every(([key, val]) => body.variables[key] === val) + } + }) + .mock({graphqlVariables: {owner: 'wheresrhys'}}, {data: {account: { + name: 'wheresrhys', + repos: [ ... ] + }}}) +``` + +One intent behind this functionality is to allow companies or publishers of particular toolsets to provide packages that extend fetch-mock to provide a more user friendly experience for developers using fetch to interact with their APIs. The GraphQL use case is a good example of this - the things which a developer might want to match on are buried in the request body, and written in a non-javascript query language. Please get in touch if you'd like to collaborate on writing such a package. + + diff --git a/docs/docs/@fetch-mock/index.md b/docs/docs/@fetch-mock/index.md index 4e1f3010..3034cd27 100644 --- a/docs/docs/@fetch-mock/index.md +++ b/docs/docs/@fetch-mock/index.md @@ -1,6 +1,7 @@ --- sidebar_position: 0 --- + # @fetch-mock suite This is a new, work in progress suite of libraries intended to replace fetch-mock. diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 34e45429..e01f18f5 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -67,6 +67,7 @@ const config = { sidebarId: 'suiteSidebar', position: 'left', label: '@fetch-mock docs', + className: "new" }, { href: 'https://github.com/wheresrhys/fetch-mock', diff --git a/docs/sidebars.js b/docs/sidebars.js index f2deec48..e76a1fb7 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -17,19 +17,6 @@ const sidebars = { // tutorialSidebar: [{ type: 'autogenerated', dirName: 'tutorial' }], fetchMockSidebar: [{ type: 'autogenerated', dirName: 'fetch-mock' }], suiteSidebar: [{ type: 'autogenerated', dirName: '@fetch-mock' }], - - // But you can create a sidebar manually - /* - tutorialSidebar: [ - 'intro', - 'hello', - { - type: 'category', - label: 'Tutorial', - items: ['tutorial-basics/create-a-document'], - }, - ], - */ }; export default sidebars; diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index 2bc6a4cf..81ce6700 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -28,3 +28,14 @@ --ifm-color-primary-lightest: #4fddbf; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); } + + +a.navbar__link.new::after { + content: '(experimental)'; + display: inline-block; + padding-left: 3px; + color: green; + vertical-align: super; + font-size: 0.8em; + +} From 2c5f3a066d775bbad159784507ccdd5976e3b3f7 Mon Sep 17 00:00:00 2001 From: Rhys Evans Date: Sat, 20 Jul 2024 13:37:36 +0100 Subject: [PATCH 08/10] chore: removed some docusaurus example files --- docs/docs/intro.md | 47 --------------------------------- docs/docusaurus.config.js | 2 +- docs/src/pages/markdown-page.md | 7 ----- 3 files changed, 1 insertion(+), 55 deletions(-) delete mode 100644 docs/docs/intro.md delete mode 100644 docs/src/pages/markdown-page.md diff --git a/docs/docs/intro.md b/docs/docs/intro.md deleted file mode 100644 index 45e8604c..00000000 --- a/docs/docs/intro.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -sidebar_position: 1 ---- - -# Tutorial Intro - -Let's discover **Docusaurus in less than 5 minutes**. - -## Getting Started - -Get started by **creating a new site**. - -Or **try Docusaurus immediately** with **[docusaurus.new](https://docusaurus.new)**. - -### What you'll need - -- [Node.js](https://nodejs.org/en/download/) version 18.0 or above: - - When installing Node.js, you are recommended to check all checkboxes related to dependencies. - -## Generate a new site - -Generate a new Docusaurus site using the **classic template**. - -The classic template will automatically be added to your project after you run the command: - -```bash -npm init docusaurus@latest my-website classic -``` - -You can type this command into Command Prompt, Powershell, Terminal, or any other integrated terminal of your code editor. - -The command also installs all necessary dependencies you need to run Docusaurus. - -## Start your site - -Run the development server: - -```bash -cd my-website -npm run start -``` - -The `cd` command changes the directory you're working with. In order to work with your newly created Docusaurus site, you'll need to navigate the terminal there. - -The `npm run start` command builds your website locally and serves it through a development server, ready for you to view at http://localhost:3000/. - -Open `docs/intro.md` (this page) and edit some lines: the site **reloads automatically** and displays your changes. diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index e01f18f5..02d997e6 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -67,7 +67,7 @@ const config = { sidebarId: 'suiteSidebar', position: 'left', label: '@fetch-mock docs', - className: "new" + className: 'new', }, { href: 'https://github.com/wheresrhys/fetch-mock', diff --git a/docs/src/pages/markdown-page.md b/docs/src/pages/markdown-page.md deleted file mode 100644 index 9756c5b6..00000000 --- a/docs/src/pages/markdown-page.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Markdown page example ---- - -# Markdown page example - -You don't need React to write simple standalone pages. From 6be048370903760c2af8a8aea6a2b0d069c436e9 Mon Sep 17 00:00:00 2001 From: Rhys Evans Date: Sat, 20 Jul 2024 13:38:33 +0100 Subject: [PATCH 09/10] chore: prettier markdown files --- .../@fetch-mock/core/more-routing-methods.md | 5 ----- docs/docs/@fetch-mock/core/route/index.md | 7 ++++--- docs/docs/@fetch-mock/core/route/matcher.md | 17 +++++------------ docs/docs/@fetch-mock/core/route/options.md | 8 ++------ docs/docs/@fetch-mock/core/route/response.md | 5 +++-- docs/docs/fetch-mock/API/Inspection/done.md | 3 +-- docs/docs/fetch-mock/API/Inspection/flush.md | 3 +-- .../API/Inspection/inspecting-calls.md | 3 +-- docs/docs/fetch-mock/API/Lifecycle/resetting.md | 3 +-- docs/docs/fetch-mock/API/Lifecycle/sandbox.md | 3 +-- .../API/Mocking/Parameters/matcher.md | 2 +- .../API/Mocking/Parameters/options.md | 3 +-- .../API/Mocking/Parameters/response.md | 3 +-- docs/docs/fetch-mock/API/Mocking/add-matcher.md | 2 +- docs/docs/fetch-mock/API/Mocking/catch.md | 3 +-- docs/docs/fetch-mock/API/Mocking/mock.md | 3 +-- docs/docs/fetch-mock/API/Mocking/shorthands.md | 3 +-- docs/docs/fetch-mock/API/Mocking/spy.md | 3 +-- docs/docs/fetch-mock/Troubleshooting/cookies.md | 3 +-- .../Troubleshooting/custom-classes.md | 3 +-- .../fetch-mock/Troubleshooting/debug-mode.md | 3 +-- .../Troubleshooting/global-non-global.md | 3 +-- .../fetch-mock/Troubleshooting/importing.md | 3 +-- .../Troubleshooting/troubleshooting.md | 3 +-- docs/docs/fetch-mock/Usage/Usage.md | 3 +-- docs/docs/fetch-mock/Usage/cheatsheet.md | 3 +-- docs/docs/fetch-mock/Usage/configuration.md | 3 +-- docs/docs/fetch-mock/Usage/installation.md | 3 +-- docs/docs/fetch-mock/Usage/quickstart.md | 3 +-- docs/docs/fetch-mock/Usage/requirements.md | 3 +-- docs/docs/fetch-mock/Usage/versions.md | 3 ++- 31 files changed, 41 insertions(+), 77 deletions(-) diff --git a/docs/docs/@fetch-mock/core/more-routing-methods.md b/docs/docs/@fetch-mock/core/more-routing-methods.md index d8654cc5..c3795db6 100644 --- a/docs/docs/@fetch-mock/core/more-routing-methods.md +++ b/docs/docs/@fetch-mock/core/more-routing-methods.md @@ -73,11 +73,8 @@ Creates a route that responds to any requests using a particular http method. Creates a route that responds to any single request using a particular http method. - - ## .addMatcher(options) - Allows adding your own, reusable custom matchers to fetch-mock, for example a matcher for interacting with GraphQL queries, or an `isAuthorized` matcher that encapsulates the exact authorization conditions for the API you are mocking, and only requires a `true` or `false` to be input ### Options @@ -140,5 +137,3 @@ fetchMock ``` One intent behind this functionality is to allow companies or publishers of particular toolsets to provide packages that extend fetch-mock to provide a more user friendly experience for developers using fetch to interact with their APIs. The GraphQL use case is a good example of this - the things which a developer might want to match on are buried in the request body, and written in a non-javascript query language. Please get in touch if you'd like to collaborate on writing such a package. - - diff --git a/docs/docs/@fetch-mock/core/route/index.md b/docs/docs/@fetch-mock/core/route/index.md index edd493ab..f24f0d48 100644 --- a/docs/docs/@fetch-mock/core/route/index.md +++ b/docs/docs/@fetch-mock/core/route/index.md @@ -2,11 +2,12 @@ sidebar_position: 2 sidebar_label: .route() --- + # route() `fetchMock.route(matcher, response, options)` -Adds a route to `fetchHandler`'s router. A route is a combination of +Adds a route to `fetchHandler`'s router. A route is a combination of - one or more rules for deciding whether a particular fetch request should be handled by the route - configuration for generating an appropriate response @@ -33,7 +34,7 @@ More options to configure matching and response behaviour. Alternatively, when a ## Alternate call patterns -As well as the function signature described above, the following patterns are supported. +As well as the function signature described above, the following patterns are supported. ### Name as third parameter @@ -49,7 +50,7 @@ This can be particularly useful for clearly and concisely expressing similar rou ```js fetchMock .route('http://my.site', 401) - .route('http://my.site', 200, {headers: {auth: true}}) + .route('http://my.site', 200, { headers: { auth: true } }); ``` ### Single options object diff --git a/docs/docs/@fetch-mock/core/route/matcher.md b/docs/docs/@fetch-mock/core/route/matcher.md index eb4e5236..23626ce6 100644 --- a/docs/docs/@fetch-mock/core/route/matcher.md +++ b/docs/docs/@fetch-mock/core/route/matcher.md @@ -1,20 +1,20 @@ --- sidebar_position: 1 --- + # matcher Determines whether a route should be used to generate a response for a request. -URL matchers and function matchers can be passed in as standalone values. They can also be combined with other matchers by passing in an object containing one or more matchers. e.g. +URL matchers and function matchers can be passed in as standalone values. They can also be combined with other matchers by passing in an object containing one or more matchers. e.g. ```js { - url: "begin: https://my.site", + url: "begin: https://my.site", method: 'post' } ``` - ## URL matchers All of the following can be passed in directly as the `matcher` argument or as the property `{url: ...}` when combining with other matchers or options. @@ -58,7 +58,6 @@ Matches a url that satisfies a regular expression, e.g. `/(article|post)\/\d+/` `{String}` Match a url that satisfies an [express style path](https://www.npmjs.com/package/path-to-regexp), e.g. `"express:/user/:user"` - #### Matching express param values `{Object}` @@ -72,9 +71,6 @@ When the `express:` keyword is used in a string matcher, it can be combined with } ``` - - - ## Other matching criteria ### method @@ -89,7 +85,6 @@ Match only requests using this http method. Not case-sensitive, e.g. `{method: " Match only requests that have these headers set, e.g. `{headers: {"Accepts": "text/html"}}` - ### query `{Object}` @@ -108,7 +103,6 @@ Match only requests that have these query parameters set (in any order). Query p - `{{query: "tags": ["cute", "kittenz"]}}` `?tags=cute&tags=kittenz` - `{{query: "q": undefined, inform: true}}` `?q=&inform=true` - ### body `{Object}` @@ -124,14 +118,15 @@ e.g.`{body: { "key1": "value1", "key2": "value2" }}` `{Boolean}` When matching a body, this option ignores any properties not mentioned in the matcher e.g. the following will ignore any properties of body that are not `"key1"`, and will therefore match the body `{ "key1": "value1", "key2": "value2" }`. + ``` { body: { "key1": "value1"}, matchPartialBody: true } ``` -This option can also be [set in the global configuration](/dummy) +This option can also be [set in the global configuration](/dummy) ## Function matchers @@ -145,5 +140,3 @@ As well as being passed as a standalone argument, it can also be added to the ma - `(url, {headers}) => !!headers.Authorization` - `(_, _, request) => !!request.headers.get('Authorization')` - - diff --git a/docs/docs/@fetch-mock/core/route/options.md b/docs/docs/@fetch-mock/core/route/options.md index 26f96c27..40daafca 100644 --- a/docs/docs/@fetch-mock/core/route/options.md +++ b/docs/docs/@fetch-mock/core/route/options.md @@ -1,8 +1,7 @@ --- - sidebar_position: 3 - --- + # options An object containing further options for configuring mocking behaviour. @@ -35,7 +34,7 @@ Delays responding for the number of milliseconds specified. `{Boolean}` -Avoids a route being removed when `removeRoutes()` is called. +Avoids a route being removed when `removeRoutes()` is called. ### sendAsJson @@ -48,6 +47,3 @@ See [global configuration](#usageconfiguration) `{Boolean}` See [global configuration](#usageconfiguration) - - - diff --git a/docs/docs/@fetch-mock/core/route/response.md b/docs/docs/@fetch-mock/core/route/response.md index e06f16d7..444da0ea 100644 --- a/docs/docs/@fetch-mock/core/route/response.md +++ b/docs/docs/@fetch-mock/core/route/response.md @@ -1,11 +1,11 @@ --- sidebar_position: 2 --- + # response Configures the http response returned by `fetchHandler`. Unless otherwise stated, all responses have a `200` status - ## Response `{Response}` @@ -13,6 +13,7 @@ Configures the http response returned by `fetchHandler`. Unless otherwise stated A [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response) instance to return unaltered. ## Status code + `{Int}` Returns a `Response` with the given status code, e.g. `200`. The response's `statusText` will also be set to the [default value corresponding to the status](https://fetch.spec.whatwg.org/#dom-response-statustext). @@ -33,7 +34,7 @@ If the object _only_ contains properties from among those listed below it is use `{String|Object}` -Set the `Response` body, e.g. `"Server responded ok"`, `{ token: 'abcdef' }`. See the `Object` section of the docs below for behaviour when passed an `Object`. +Set the `Response` body, e.g. `"Server responded ok"`, `{ token: 'abcdef' }`. See the `Object` section of the docs below for behaviour when passed an `Object`. ### status diff --git a/docs/docs/fetch-mock/API/Inspection/done.md b/docs/docs/fetch-mock/API/Inspection/done.md index 8313e526..e419de5b 100644 --- a/docs/docs/fetch-mock/API/Inspection/done.md +++ b/docs/docs/fetch-mock/API/Inspection/done.md @@ -1,9 +1,8 @@ --- sidebar_position: 2 - --- -# .done(filter) +# .done(filter) Returns a Boolean indicating whether `fetch` was called the expected number of times (or has been called at least once if `repeat` is undefined for the route). It does not take into account whether the `fetches` completed successfully. diff --git a/docs/docs/fetch-mock/API/Inspection/flush.md b/docs/docs/fetch-mock/API/Inspection/flush.md index 84172eef..a99f79dd 100644 --- a/docs/docs/fetch-mock/API/Inspection/flush.md +++ b/docs/docs/fetch-mock/API/Inspection/flush.md @@ -1,9 +1,8 @@ --- - sidebar_position: 3 --- -# .flush(waitForBody) +# .flush(waitForBody) Returns a `Promise` that resolves once all fetches handled by fetch-mock have resolved diff --git a/docs/docs/fetch-mock/API/Inspection/inspecting-calls.md b/docs/docs/fetch-mock/API/Inspection/inspecting-calls.md index 160aa7aa..634eb4f3 100644 --- a/docs/docs/fetch-mock/API/Inspection/inspecting-calls.md +++ b/docs/docs/fetch-mock/API/Inspection/inspecting-calls.md @@ -1,10 +1,9 @@ --- - sidebar_position: 1 tableOfContents: maxHeadingLevel: 5 - --- + # Inspecting calls ## Methods diff --git a/docs/docs/fetch-mock/API/Lifecycle/resetting.md b/docs/docs/fetch-mock/API/Lifecycle/resetting.md index 234b93a4..41bb048f 100644 --- a/docs/docs/fetch-mock/API/Lifecycle/resetting.md +++ b/docs/docs/fetch-mock/API/Lifecycle/resetting.md @@ -1,9 +1,8 @@ --- - sidebar_position: 2 --- -# Resetting +# Resetting ## .restore() / .reset() diff --git a/docs/docs/fetch-mock/API/Lifecycle/sandbox.md b/docs/docs/fetch-mock/API/Lifecycle/sandbox.md index 83a891dc..a1bd8687 100644 --- a/docs/docs/fetch-mock/API/Lifecycle/sandbox.md +++ b/docs/docs/fetch-mock/API/Lifecycle/sandbox.md @@ -1,8 +1,7 @@ --- - sidebar_position: 1 - --- + # .sandbox() Returns a function that can be used as a drop-in replacement for `fetch`. Pass this into your mocking library of choice. The function returned by `sandbox()` has all the methods of `fetch-mock` exposed on it and maintains its own state independent of other instances, so tests can be run in parallel. diff --git a/docs/docs/fetch-mock/API/Mocking/Parameters/matcher.md b/docs/docs/fetch-mock/API/Mocking/Parameters/matcher.md index ee07e00d..8bbf78c3 100644 --- a/docs/docs/fetch-mock/API/Mocking/Parameters/matcher.md +++ b/docs/docs/fetch-mock/API/Mocking/Parameters/matcher.md @@ -1,6 +1,7 @@ --- sidebar_position: 1 --- + # matcher Criteria for deciding which requests to mock. @@ -74,7 +75,6 @@ The url and function matchers described above can be combined with other criteri In particular, **headers**, **query string parameters**, **request bodies** and **express parameter values** can all be used as matching criteria. - #### Examples - `{url: 'end:/user/profile', headers: {Authorization: 'Basic 123'}}` diff --git a/docs/docs/fetch-mock/API/Mocking/Parameters/options.md b/docs/docs/fetch-mock/API/Mocking/Parameters/options.md index d9c374cf..ee378c47 100644 --- a/docs/docs/fetch-mock/API/Mocking/Parameters/options.md +++ b/docs/docs/fetch-mock/API/Mocking/Parameters/options.md @@ -1,8 +1,7 @@ --- - sidebar_position: 3 - --- + # optionsOrName Either diff --git a/docs/docs/fetch-mock/API/Mocking/Parameters/response.md b/docs/docs/fetch-mock/API/Mocking/Parameters/response.md index 2b1e5580..839107c2 100644 --- a/docs/docs/fetch-mock/API/Mocking/Parameters/response.md +++ b/docs/docs/fetch-mock/API/Mocking/Parameters/response.md @@ -1,8 +1,7 @@ --- - sidebar_position: 2 - --- + # response Configures the http response returned by the mock. Accepts any of the following values or a `Promise` for any of them (useful when testing race conditions, loading transitions etc.). Unless otherwise stated, all responses have a `200` status diff --git a/docs/docs/fetch-mock/API/Mocking/add-matcher.md b/docs/docs/fetch-mock/API/Mocking/add-matcher.md index d8f40e61..086e70b8 100644 --- a/docs/docs/fetch-mock/API/Mocking/add-matcher.md +++ b/docs/docs/fetch-mock/API/Mocking/add-matcher.md @@ -1,8 +1,8 @@ --- sidebar_position: 3 --- -# .addMatcher(options) +# .addMatcher(options) Allows adding your own, reusable custom matchers to fetch-mock, for example a matcher for interacting with GraphQL queries, or an `isAuthorized` matcher that encapsulates the exact authorization conditions for the API you are mocking, and only requires a `true` or `false` to be input diff --git a/docs/docs/fetch-mock/API/Mocking/catch.md b/docs/docs/fetch-mock/API/Mocking/catch.md index e6d884a2..efb6b12b 100644 --- a/docs/docs/fetch-mock/API/Mocking/catch.md +++ b/docs/docs/fetch-mock/API/Mocking/catch.md @@ -1,8 +1,7 @@ --- - sidebar_position: 3 - --- + # .catch(response) Specifies how to respond to calls to `fetch` that don't match any mocks. diff --git a/docs/docs/fetch-mock/API/Mocking/mock.md b/docs/docs/fetch-mock/API/Mocking/mock.md index 7de5b93f..fe71455c 100644 --- a/docs/docs/fetch-mock/API/Mocking/mock.md +++ b/docs/docs/fetch-mock/API/Mocking/mock.md @@ -1,8 +1,7 @@ --- - sidebar_position: 1 - --- + # .mock(matcher, response, optionsOrName) Initialises or extends a stub implementation of fetch, applying a `route` that matches `matcher`, delivers a `Response` configured using `response`, and that respects the additional `options`. The stub will record its calls so they can be inspected later. If `.mock` is called on the top level `fetch-mock` instance, this stub function will also replace `fetch` globally. Calling `.mock()` with no arguments will carry out this stubbing without defining any mock responses. diff --git a/docs/docs/fetch-mock/API/Mocking/shorthands.md b/docs/docs/fetch-mock/API/Mocking/shorthands.md index e59680db..2660320a 100644 --- a/docs/docs/fetch-mock/API/Mocking/shorthands.md +++ b/docs/docs/fetch-mock/API/Mocking/shorthands.md @@ -1,9 +1,8 @@ --- sidebar_position: 2 - --- -# Shorthand methods +# Shorthand methods These methods allow configuring routes for common use cases while avoiding writing configuration objects. Unless noted otherwise, each of the methods below have the same signature as `.mock(matcher, response, optionsOrName)` diff --git a/docs/docs/fetch-mock/API/Mocking/spy.md b/docs/docs/fetch-mock/API/Mocking/spy.md index 975a9c43..c3318eea 100644 --- a/docs/docs/fetch-mock/API/Mocking/spy.md +++ b/docs/docs/fetch-mock/API/Mocking/spy.md @@ -1,8 +1,7 @@ --- - sidebar_position: 4 - --- + # .spy(matcher) Records call history while passing each call on to `fetch` to be handled by the network. Optionally pass in a `matcher` to scope this to only matched calls, e.g. to fetch a specific resource from the network. diff --git a/docs/docs/fetch-mock/Troubleshooting/cookies.md b/docs/docs/fetch-mock/Troubleshooting/cookies.md index 544db39f..7ef727e2 100644 --- a/docs/docs/fetch-mock/Troubleshooting/cookies.md +++ b/docs/docs/fetch-mock/Troubleshooting/cookies.md @@ -1,8 +1,7 @@ --- - sidebar_position: 5 - --- + # Setting cookies in the browser The `Set-Cookie` header is used to set cookies in the browser. This behaviour is part of the [browser/http spec](https://tools.ietf.org/html/rfc6265#section-4.1), not the fetch spec. As fetch-mock prevents requests getting out of js and into the browser, `Set-Cookie` will have no effect. diff --git a/docs/docs/fetch-mock/Troubleshooting/custom-classes.md b/docs/docs/fetch-mock/Troubleshooting/custom-classes.md index bec1bfaf..b8766258 100644 --- a/docs/docs/fetch-mock/Troubleshooting/custom-classes.md +++ b/docs/docs/fetch-mock/Troubleshooting/custom-classes.md @@ -1,9 +1,8 @@ --- sidebar_position: 4 - --- -# Custom fetch implementation +# Custom fetch implementation `fetch-mock` uses `Request`, `Response` and `Headers` constructors internally, and obtains these from `node-fetch` in Node.js, or `window` in the browser. If you are using an alternative implementation of `fetch` you will need to configure `fetch-mock` to use its implementations of these constructors instead. These should be set on the `fetchMock.config` object, e.g. diff --git a/docs/docs/fetch-mock/Troubleshooting/debug-mode.md b/docs/docs/fetch-mock/Troubleshooting/debug-mode.md index 4b9a9290..dd17b0e1 100644 --- a/docs/docs/fetch-mock/Troubleshooting/debug-mode.md +++ b/docs/docs/fetch-mock/Troubleshooting/debug-mode.md @@ -1,9 +1,8 @@ --- sidebar_position: 5 - --- -# Debugging +# Debugging The first step when debugging tests should be to run with the environment variable `DEBUG=fetch-mock*`. This will output additional logs for debugging purposes. diff --git a/docs/docs/fetch-mock/Troubleshooting/global-non-global.md b/docs/docs/fetch-mock/Troubleshooting/global-non-global.md index be576843..060fce49 100644 --- a/docs/docs/fetch-mock/Troubleshooting/global-non-global.md +++ b/docs/docs/fetch-mock/Troubleshooting/global-non-global.md @@ -1,9 +1,8 @@ --- sidebar_position: 1 - --- -# Global or non-global +# Global or non-global `fetch` can be used by your code globally or locally. It's important to determine which one applies to your codebase as it will impact how you use `fetch-mock` diff --git a/docs/docs/fetch-mock/Troubleshooting/importing.md b/docs/docs/fetch-mock/Troubleshooting/importing.md index d79a65c9..e846426c 100644 --- a/docs/docs/fetch-mock/Troubleshooting/importing.md +++ b/docs/docs/fetch-mock/Troubleshooting/importing.md @@ -1,9 +1,8 @@ --- sidebar_position: 2 - --- -# Importing the correct version +# Importing the correct version _Note that the documentation below applies to version 9 and below._ diff --git a/docs/docs/fetch-mock/Troubleshooting/troubleshooting.md b/docs/docs/fetch-mock/Troubleshooting/troubleshooting.md index 40272a04..f94b2bd4 100644 --- a/docs/docs/fetch-mock/Troubleshooting/troubleshooting.md +++ b/docs/docs/fetch-mock/Troubleshooting/troubleshooting.md @@ -1,9 +1,8 @@ --- sidebar_position: 1 - --- -# Troubleshooting +# Troubleshooting The first step when debugging tests should be to run with the environment variable `DEBUG=fetch-mock*`. This will output additional logs for debugging purposes. diff --git a/docs/docs/fetch-mock/Usage/Usage.md b/docs/docs/fetch-mock/Usage/Usage.md index 203ec614..2fd4da2f 100644 --- a/docs/docs/fetch-mock/Usage/Usage.md +++ b/docs/docs/fetch-mock/Usage/Usage.md @@ -1,7 +1,6 @@ --- - - --- + fetch-mock is the most comprehensive library for mocking the fetch API. It allows mocking http requests made using [fetch](https://fetch.spec.whatwg.org/) or a library imitating its api, such as [node-fetch](https://www.npmjs.com/package/node-fetch). diff --git a/docs/docs/fetch-mock/Usage/cheatsheet.md b/docs/docs/fetch-mock/Usage/cheatsheet.md index 94158060..dba1a15c 100644 --- a/docs/docs/fetch-mock/Usage/cheatsheet.md +++ b/docs/docs/fetch-mock/Usage/cheatsheet.md @@ -1,9 +1,8 @@ --- sidebar_position: 3 - --- -# Cheatsheet +# Cheatsheet - [Installation](#installation) - [Set up and teardown](#setup-and-teardown) diff --git a/docs/docs/fetch-mock/Usage/configuration.md b/docs/docs/fetch-mock/Usage/configuration.md index 4853d944..abdf0f4a 100644 --- a/docs/docs/fetch-mock/Usage/configuration.md +++ b/docs/docs/fetch-mock/Usage/configuration.md @@ -1,9 +1,8 @@ --- - sidebar_position: 4 --- -# Configuration +# Configuration On any `fetch-mock` instance, set configuration options directly on the `fetchMock.config` object. e.g. diff --git a/docs/docs/fetch-mock/Usage/installation.md b/docs/docs/fetch-mock/Usage/installation.md index bac01a8b..3d1fb14a 100644 --- a/docs/docs/fetch-mock/Usage/installation.md +++ b/docs/docs/fetch-mock/Usage/installation.md @@ -1,9 +1,8 @@ --- sidebar_position: 1 - --- -# Installation +# Installation Install fetch-mock using diff --git a/docs/docs/fetch-mock/Usage/quickstart.md b/docs/docs/fetch-mock/Usage/quickstart.md index 4da778e7..a13b2abc 100644 --- a/docs/docs/fetch-mock/Usage/quickstart.md +++ b/docs/docs/fetch-mock/Usage/quickstart.md @@ -1,9 +1,8 @@ --- - sidebar_position: 2 --- -# Quickstart +# Quickstart ## Setting up your mock diff --git a/docs/docs/fetch-mock/Usage/requirements.md b/docs/docs/fetch-mock/Usage/requirements.md index 35fb6d61..fec4d157 100644 --- a/docs/docs/fetch-mock/Usage/requirements.md +++ b/docs/docs/fetch-mock/Usage/requirements.md @@ -1,9 +1,8 @@ --- sidebar_position: 0.5 - --- -# Requirements +# Requirements fetch-mock requires the following to run: diff --git a/docs/docs/fetch-mock/Usage/versions.md b/docs/docs/fetch-mock/Usage/versions.md index 531a9421..d2096448 100644 --- a/docs/docs/fetch-mock/Usage/versions.md +++ b/docs/docs/fetch-mock/Usage/versions.md @@ -1,6 +1,7 @@ --- sidebar_position: 5 --- + # Versions ### Version 10 @@ -19,7 +20,7 @@ I intend to keep version 10 and above r4easonably clean, with as few workarounds ### Version 9 and below -v7, v8 & v9 are practically identical, only differing in their treatment of a few edge cases, or in compatibility with other libraries and environments. +v7, v8 & v9 are practically identical, only differing in their treatment of a few edge cases, or in compatibility with other libraries and environments. For previous versions follow the documentation below: From c742b39f20a8a13267db03b4d68607ff3ed06c9b Mon Sep 17 00:00:00 2001 From: Rhys Evans Date: Sat, 20 Jul 2024 13:44:49 +0100 Subject: [PATCH 10/10] docs: fix broken link --- docs/docs/@fetch-mock/core/configuration.md | 52 +++++++++++++++++++++ docs/docs/@fetch-mock/core/route/matcher.md | 2 +- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 docs/docs/@fetch-mock/core/configuration.md diff --git a/docs/docs/@fetch-mock/core/configuration.md b/docs/docs/@fetch-mock/core/configuration.md new file mode 100644 index 00000000..925c8e63 --- /dev/null +++ b/docs/docs/@fetch-mock/core/configuration.md @@ -0,0 +1,52 @@ +--- +sidebar_position: 6 +--- + +# Configuration + +On any `fetch-mock` instance, set configuration options directly on the `fetchMock.config` object. e.g. + +```js +const fetchMock = require('fetch-mock'); +fetchMock.config.sendAsJson = false; +``` + +## Available options + +Options marked with a `†` can also be overridden for individual calls to `.mock(matcher, response, options)` by setting as properties on the `options` parameter + +### sendAsJson + +`{Boolean}` default: `true` + +Always convert objects passed to `.mock()` to JSON strings before building reponses. Can be useful to set to `false` globally if e.g. dealing with a lot of `ArrayBuffer`s. When `true` the `Content-Type: application/json` header will also be set on each response. + +### includeContentLength + +`{Boolean}` default: `true` + +Sets a `Content-Length` header on each response. + +### matchPartialBody + +`{Boolean}` default: `false` + +Match calls that only partially match a specified body json. Uses the [is-subset](https://www.npmjs.com/package/is-subset) library under the hood, which implements behaviour the same as jest's [.objectContaining()](https://jestjs.io/docs/en/expect#expectobjectcontainingobject) method. + +### Custom fetch implementations + +`fetch`, `Headers`, `Request`, `Response` can all be set on the configuration object, allowing fetch-mock to mock any implementation of `fetch`, e.g. `node-fetch`. e.g. + +```js + +import { default as fetch, Headers, Request, Response } from 'node-fetch'; + +import fetchMock from 'fetch-mock'; + +fetchMock.config = Object.assign(fetchMock.config, { + Request, + Response, + Headers, + fetch, +}); +``` diff --git a/docs/docs/@fetch-mock/core/route/matcher.md b/docs/docs/@fetch-mock/core/route/matcher.md index 23626ce6..4f5c1b2f 100644 --- a/docs/docs/@fetch-mock/core/route/matcher.md +++ b/docs/docs/@fetch-mock/core/route/matcher.md @@ -126,7 +126,7 @@ When matching a body, this option ignores any properties not mentioned in the ma } ``` -This option can also be [set in the global configuration](/dummy) +This option can also be [set in the global configuration](/fetch-mock/docs/@fetch-mock/core/configuration) ## Function matchers