diff --git a/.gitignore b/.gitignore index b4acbbf9..1bc2cf7a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -/node_modules/ +node_modules/ # tooling artefacts /docs/.sass-cache/ diff --git a/.husky/pre-commit b/.husky/pre-commit index 3867a0fe..30ee92f7 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1 @@ -npm run lint +npm run lint && npm run types:lint && npm run types:check diff --git a/docs/blog/2024-07-21-introducing-core.md b/docs/blog/2024-07-21-introducing-core.md index a28a5a7f..b49e3aa0 100644 --- a/docs/blog/2024-07-21-introducing-core.md +++ b/docs/blog/2024-07-21-introducing-core.md @@ -53,6 +53,14 @@ fetchMock.mock('http://my.site', 200); which keeps fetch-mock's methods much further away from any other library's workings. +## .getAny(), .postAny(), .putAny(), .deleteAny(), .headAny(), .patchAny(), .getAnyOnce(), .postAnyOnce(), .putAnyOnce(), .deleteAnyOnce(), .headAnyOnce(), .patchAnyOnce() + +While `.getOnce()` etc feel very useful, the `any` and `anyOnce` variants added a lot of repetition to the code and types, and don't actually add much value. + +`.___AnyOnce(response, options)` + +Creates a route that responds to any single request using a particular http method. + ### Gone, but back soon The following features will return in other libraries that wrap @fetch-mock/core for different environments. diff --git a/docs/docs/@fetch-mock/core/more-routing-methods.md b/docs/docs/@fetch-mock/core/more-routing-methods.md index 6aa2b42d..28b2ba27 100644 --- a/docs/docs/@fetch-mock/core/more-routing-methods.md +++ b/docs/docs/@fetch-mock/core/more-routing-methods.md @@ -61,18 +61,6 @@ fetchMock.purge = function (matcher, response, options) { Creates a route that only responds to a single request using a particular http method -## .getAny(), .postAny(), .putAny(), .deleteAny(), .headAny(), .patchAny() - -`.___Any(response, options)` - -Creates a route that responds to any requests using a particular http method. - -## .getAnyOnce(), .postAnyOnce(), .putAnyOnce(), .deleteAnyOnce(), .headAnyOnce(), .patchAnyOnce() - -`.___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 diff --git a/jsconfig.json b/jsconfig.json index 478664f7..3c975b3c 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -5,6 +5,8 @@ "dom", "dom.iterable" ], + "moduleResolution": "nodenext", + "module": "NodeNext", "allowJs": true, "checkJs": true, "strict": true, @@ -12,15 +14,23 @@ "noImplicitThis": true, "strictNullChecks": false, "strictFunctionTypes": true, - "types": [ ], - "noEmit": true, + "types": [ + ], "downlevelIteration": true, - "forceConsistentCasingInFileNames": true + "forceConsistentCasingInFileNames": true, + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "packages/core/types", + "skipLibCheck": true, + "noEmit": false, + "target": "es2021", + "removeComments": true }, "include": [ - "packages/core/src/*.js", + "./packages/core/src/*.js" ], "exclude": [ - "node_modules" + "node_modules", + "packages/**/src/__tests__" ] -} \ No newline at end of file +} diff --git a/mr b/mr deleted file mode 100644 index e69de29b..00000000 diff --git a/package-lock.json b/package-lock.json index 31e22578..c0d63b8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,8 @@ "@commitlint/config-conventional": "^19.2.2", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", + "@types/events": "^3.0.3", + "@types/globrex": "^0.1.4", "@types/node": "^20.14.10", "@vitest/browser": "^1.1.0", "@vitest/coverage-istanbul": "^1.1.0", @@ -36,7 +38,7 @@ "prettier": "^3.1.1", "rollup": "^4.9.1", "ts-to-jsdoc": "^2.1.0", - "typescript": "^3.9.10", + "typescript": "^5.5.3", "v8": "^0.1.0", "vitest": "^1.1.0", "webdriverio": "^8.27.0" @@ -2385,20 +2387,6 @@ "typescript": ">=4" } }, - "node_modules/@commitlint/load/node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", - "dev": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/@commitlint/message": { "version": "19.0.0", "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.0.0.tgz", @@ -5766,20 +5754,6 @@ } } }, - "node_modules/@svgr/core/node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", - "optional": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/@svgr/hast-util-to-babel-ast": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", @@ -5862,20 +5836,6 @@ } } }, - "node_modules/@svgr/plugin-svgo/node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", - "optional": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/@svgr/webpack": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", @@ -6090,6 +6050,12 @@ "@types/estree": "*" } }, + "node_modules/@types/events": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.3.tgz", + "integrity": "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==", + "dev": true + }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", @@ -6112,6 +6078,12 @@ "@types/send": "*" } }, + "node_modules/@types/globrex": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@types/globrex/-/globrex-0.1.4.tgz", + "integrity": "sha512-qm82zaOxfn8Us/GGjNrQQ1XfCBUDV86DxQgIQq/p1zGHlt0xnbUiabNjN9rZUhMNvvIE2gg8iTW+GMfw0TnnLg==", + "dev": true + }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -21079,20 +21051,6 @@ } } }, - "node_modules/postcss-loader/node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", - "optional": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/postcss-merge-idents": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-6.0.3.tgz", @@ -25092,15 +25050,15 @@ } }, "node_modules/typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/ufo": { @@ -26264,21 +26222,6 @@ "node": ">=8" } }, - "node_modules/webdriverio/node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/webdriverio/node_modules/ws": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", diff --git a/package.json b/package.json index 3f4c311e..63b08b2a 100644 --- a/package.json +++ b/package.json @@ -59,9 +59,11 @@ "prettier": "^3.1.1", "rollup": "^4.9.1", "ts-to-jsdoc": "^2.1.0", - "typescript": "^3.9.10", + "typescript": "^5.5.3", "v8": "^0.1.0", "vitest": "^1.1.0", + "@types/events": "^3.0.3", + "@types/globrex": "^0.1.4", "webdriverio": "^8.27.0" }, "volta": { diff --git a/packages/core/package.json b/packages/core/package.json index 1c19474b..c53ad0c8 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -4,6 +4,7 @@ "exports": "src/index.js", "version": "0.3.1", "main": "index.js", + "types": "types/index.d.ts", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, diff --git a/packages/core/src/CallHistory.js b/packages/core/src/CallHistory.js index 1b519b22..97169b86 100644 --- a/packages/core/src/CallHistory.js +++ b/packages/core/src/CallHistory.js @@ -65,6 +65,9 @@ class CallHistory { this.callLogs.push(callLog); } + /** + * @returns {void} + */ clear() { this.callLogs.forEach(({ route }) => route.reset()); this.callLogs = []; diff --git a/packages/core/src/FetchMock.js b/packages/core/src/FetchMock.js index fcd2bd4b..507aa966 100644 --- a/packages/core/src/FetchMock.js +++ b/packages/core/src/FetchMock.js @@ -11,6 +11,63 @@ import * as requestUtils from './RequestUtils.js'; /** @typedef {import('./CallHistory').CallLog} CallLog */ /** @typedef {import('./Route').RouteResponseFunction} RouteResponseFunction */ +/** + * + * @param {UserRouteConfig} shorthandOptions + */ +const defineShorthand = (shorthandOptions) => { + /** + * @overload + * @param {UserRouteConfig} matcher + * @this {FetchMock} + * @returns {FetchMock} + */ + + /** + * @overload + * @param {RouteMatcher } matcher + * @param {RouteResponse} response + * @param {UserRouteConfig | string} [options] + * @this {FetchMock} + * @returns {FetchMock} + */ + + /** + * @param {RouteMatcher | UserRouteConfig} matcher + * @param {RouteResponse} [response] + * @param {UserRouteConfig | string} [options] + * @this {FetchMock} + * @returns {FetchMock} + */ + return function (matcher, response, options) { + return this.route( + //@ts-ignore + matcher, + response, + Object.assign(options || {}, shorthandOptions), + ); + }; +}; +/** + * + * @param {UserRouteConfig} shorthandOptions + */ +const defineGreedyShorthand = (shorthandOptions) => { + /** + * @param {RouteResponse} response + * @param {UserRouteConfig | string} [options] + * @this {FetchMock} + * @returns {FetchMock} + */ + return function (response, options) { + return this.route( + '*', + response, + Object.assign(options || {}, shorthandOptions), + ); + }; +}; + /** * @typedef FetchMockConfig * @property {boolean} [sendAsJson] @@ -34,38 +91,28 @@ const defaultConfig = { Headers: globalThis.Headers, fetch: globalThis.fetch, }; -/** - * @typedef FetchMockCore - * @this {FetchMock} - * @property {FetchMockConfig} config - * @property {Router} router - * @property {CallHistory} callHistory - * @property {function():FetchMock} createInstance - * @property {function(string | Request, RequestInit): Promise} fetchHandler - * @property {function(any,any,any): FetchMock} route - * @property {function(RouteResponse=): FetchMock} catch - * @property {function(MatcherDefinition):void} defineMatcher - * @property {function(object): void} removeRoutes - * @property {function():void} clearHistory - */ -const defaultRouter = new Router(defaultConfig); - -/** @type {FetchMockCore} */ -const FetchMock = { - config: defaultConfig, - router: defaultRouter, - callHistory: new CallHistory(defaultConfig, defaultRouter), - createInstance() { - const instance = Object.create(FetchMock); - instance.config = { ...this.config }; - instance.router = new Router(instance.config, { - routes: [...this.router.routes], - fallbackRoute: this.router.fallbackRoute, +class FetchMock { + /** + * + * @param {FetchMockConfig} config + * @param {Router} [router] + */ + constructor(config, router) { + this.config = config; + this.router = new Router(this.config, { + routes: router ? [...router.routes] : [], + fallbackRoute: router ? router.fallbackRoute : null, }); - instance.callHistory = new CallHistory(instance.config, instance.router); - return instance; - }, + this.callHistory = new CallHistory(this.config, this.router); + } + /** + * + * @returns {FetchMock} + */ + createInstance() { + return new FetchMock({ ...this.config }, this.router); + } /** * * @param {string | Request} requestInput @@ -76,7 +123,8 @@ const FetchMock = { async fetchHandler(requestInput, requestInit) { // TODO move into router let callLog; - if (requestUtils.isRequest(requestInput, this.config.Request)) { + + if (requestInput instanceof this.config.Request) { callLog = await requestUtils.createCallLogFromRequest( requestInput, requestInit, @@ -92,23 +140,19 @@ const FetchMock = { const responsePromise = this.router.execute(callLog); callLog.pendingPromises.push(responsePromise); return responsePromise; - }, + } /** * @overload * @param {UserRouteConfig} matcher - * @this {FetchMock} * @returns {FetchMock} */ - /** * @overload * @param {RouteMatcher } matcher * @param {RouteResponse} response * @param {UserRouteConfig | string} [options] - * @this {FetchMock} * @returns {FetchMock} */ - /** * @param {RouteMatcher | UserRouteConfig} matcher * @param {RouteResponse} [response] @@ -119,109 +163,64 @@ const FetchMock = { route(matcher, response, options) { this.router.addRoute(matcher, response, options); return this; - }, - catch(response) { - this.router.setFallback(response); - return this; - }, - defineMatcher(matcher) { - Route.defineMatcher(matcher); - }, - removeRoutes(options) { - this.router.removeRoutes(options); - return this; - }, - clearHistory() { - this.callHistory.clear(); - return this; - }, -}; - -/** @typedef {'get' |'post' |'put' |'delete' |'head' |'patch' |'once' |'sticky' |'any' |'anyOnce' |'getOnce' |'postOnce' |'putOnce' |'deleteOnce' |'headOnce' |'patchOnce' |'getAny' |'postAny' |'putAny' |'deleteAny' |'headAny' |'patchAny' |'getAnyOnce' |'postAnyOnce' |'putAnyOnce' |'deleteAnyOnce' |'headAnyOnce' |'patchAnyOnce'} PresetRouteMethodName} */ -/** @typedef {Object.} PresetRoutes */ - -/** @type {PresetRoutes} */ -const PresetRoutes = {}; -/** - * - * @param {PresetRouteMethodName} methodName - * @param {string} underlyingMethod - * @param {UserRouteConfig} shorthandOptions - */ -const defineShorthand = (methodName, underlyingMethod, shorthandOptions) => { + } /** - * @overload - * @param {UserRouteConfig} matcher + * + * @param {RouteResponse} [response] * @this {FetchMock} * @returns {FetchMock} */ - + catch(response) { + this.router.setFallback(response); + return this; + } /** - * @overload - * @param {RouteMatcher } matcher - * @param {RouteResponse} response - * @param {UserRouteConfig | string} [options] - * @this {FetchMock} - * @returns {FetchMock} + * + * @param {MatcherDefinition} matcher */ - + //eslint-disable-next-line class-methods-use-this + defineMatcher(matcher) { + Route.defineMatcher(matcher); + } /** - * @param {RouteMatcher | UserRouteConfig} matcher - * @param {RouteResponse} [response] - * @param {UserRouteConfig | string} [options] + * + * @param {object} [options] + * @param {string[]} [options.names] + * @param {boolean} [options.includeSticky] + * @param {boolean} [options.includeFallback] * @this {FetchMock} * @returns {FetchMock} */ - PresetRoutes[methodName] = function (matcher, response, options) { - return this[underlyingMethod]( - matcher, - response, - Object.assign(options || {}, shorthandOptions), - ); - }; -}; -/** - * - * @param {PresetRouteMethodName} methodName - * @param {string} underlyingMethod - */ -const defineGreedyShorthand = (methodName, underlyingMethod) => { + removeRoutes(options) { + this.router.removeRoutes(options); + return this; + } /** - * @param {RouteResponse} response - * @param {UserRouteConfig | string} [options] - * @this {FetchMock} + * * @returns {FetchMock} */ - PresetRoutes[methodName] = function (response, options) { - return this[underlyingMethod]('*', response, options); - }; -}; - -defineShorthand('sticky', 'route', { sticky: true }); -defineShorthand('once', 'route', { repeat: 1 }); -defineGreedyShorthand('any', 'route'); -defineGreedyShorthand('anyOnce', 'once'); - -['get', 'post', 'put', 'delete', 'head', 'patch'].forEach((method) => { - defineShorthand(/** @type {PresetRouteMethodName} */ (method), 'route', { - method, - }); - defineShorthand( - /** @type {PresetRouteMethodName} */ (`${method}Once`), - 'once', - { method }, - ); - defineGreedyShorthand( - /** @type {PresetRouteMethodName} */ (`${method}Any`), - method, - ); - defineGreedyShorthand( - /** @type {PresetRouteMethodName} */ (`${method}AnyOnce`), - `${method}Once`, - ); -}); + clearHistory() { + this.callHistory.clear(); + return this; + } + sticky = defineShorthand({ sticky: true }); + once = defineShorthand({ repeat: 1 }); + any = defineGreedyShorthand({}); + anyOnce = defineGreedyShorthand({ repeat: 1 }); + get = defineShorthand({ method: 'get' }); + getOnce = defineShorthand({ method: 'get', repeat: 1 }); + post = defineShorthand({ method: 'post' }); + postOnce = defineShorthand({ method: 'post', repeat: 1 }); + put = defineShorthand({ method: 'put' }); + putOnce = defineShorthand({ method: 'put', repeat: 1 }); + delete = defineShorthand({ method: 'delete' }); + deleteOnce = defineShorthand({ method: 'delete', repeat: 1 }); + head = defineShorthand({ method: 'head' }); + headOnce = defineShorthand({ method: 'head', repeat: 1 }); + patch = defineShorthand({ method: 'patch' }); + patchOnce = defineShorthand({ method: 'patch', repeat: 1 }); +} -/** @typedef {FetchMockCore & PresetRoutes} FetchMock*/ -Object.assign(FetchMock, PresetRoutes); +const fetchMock = new FetchMock({ ...defaultConfig }).createInstance(); -export default FetchMock.createInstance(); +export default fetchMock; diff --git a/packages/core/src/Matchers.js b/packages/core/src/Matchers.js index 75ee1933..02e6615c 100644 --- a/packages/core/src/Matchers.js +++ b/packages/core/src/Matchers.js @@ -13,6 +13,19 @@ import { normalizeUrl, } from './RequestUtils.js'; +/** @typedef {string | RegExp | URL} RouteMatcherUrl */ +/** @typedef {function(string): RouteMatcherFunction} UrlMatcherGenerator */ +/** @typedef {function(CallLog): boolean} RouteMatcherFunction */ +/** @typedef {function(RouteConfig): RouteMatcherFunction} MatcherGenerator */ +/** @typedef {RouteMatcherUrl | RouteMatcherFunction} RouteMatcher */ + +/** + * @typedef MatcherDefinition + * @property {string} name + * @property {MatcherGenerator} matcher + * @property {boolean} [usesBody] + */ + /** * @param {RouteMatcher | RouteConfig} matcher * @returns {matcher is RouteMatcherUrl} @@ -29,19 +42,6 @@ export const isUrlMatcher = (matcher) => */ export const isFunctionMatcher = (matcher) => typeof matcher === 'function'; -/** @typedef {string | RegExp | URL} RouteMatcherUrl */ -/** @typedef {function(string): RouteMatcherFunction} UrlMatcherGenerator */ -/** @typedef {function(CallLog): boolean} RouteMatcherFunction */ -/** @typedef {function(RouteConfig): RouteMatcherFunction} MatcherGenerator */ -/** @typedef {RouteMatcherUrl | RouteMatcherFunction} RouteMatcher */ - -/** - * @typedef MatcherDefinition - * @property {string} name - * @property {MatcherGenerator} matcher - * @property {boolean} [usesBody] - */ - /** * @type {Object.} */ @@ -56,7 +56,7 @@ const stringMatchers = { url.substr(-targetString.length) === targetString, glob: (targetString) => { - const urlRX = glob(targetString); + const urlRX = /** @type {{regex: RegExp}} */ (glob(targetString)); return ({ url }) => urlRX.regex.test(url); }, express: (targetString) => { @@ -182,6 +182,12 @@ const getBodyMatcher = (route) => { ); }; }; + +/** + * @type {MatcherGenerator} + */ +const getFunctionMatcher = ({ matcherFunction }) => matcherFunction; + /** * * @param {RouteConfig} route @@ -207,10 +213,6 @@ const getFullUrlMatcher = (route, matcherUrl, query) => { }; }; -/** - * @type {MatcherGenerator} - */ -const getFunctionMatcher = ({ matcherFunction }) => matcherFunction; /** * @type {MatcherGenerator} */ diff --git a/packages/core/src/RequestUtils.js b/packages/core/src/RequestUtils.js index 78068ed0..136d0e32 100644 --- a/packages/core/src/RequestUtils.js +++ b/packages/core/src/RequestUtils.js @@ -31,14 +31,6 @@ export function normalizeUrl(url) { const u = new URL(url, 'http://dummy'); return u.pathname + u.search; } -/** - * - * @param {string|Request} urlOrRequest - * @param {typeof Request} Request - * @returns {urlOrRequest is Request} - */ -export const isRequest = (urlOrRequest, Request) => - Request.prototype.isPrototypeOf(urlOrRequest); /** * @@ -124,7 +116,7 @@ export function getQuery(url) { /** * - * @param {Headers | [string, string][] | Record < string, string > | Object.} headers + * @param {Headers | [string, string][] | Record < string, string > | Object. | HeadersInit} headers * @returns {Object.} */ export const normalizeHeaders = (headers) => { diff --git a/packages/core/src/Route.js b/packages/core/src/Route.js index d2fb3bc3..19e8bc14 100644 --- a/packages/core/src/Route.js +++ b/packages/core/src/Route.js @@ -111,7 +111,6 @@ class Route { /** * @returns {void} */ - // @ts-ignore #validate() { if (['matched', 'unmatched'].includes(this.config.name)) { throw new Error( @@ -130,7 +129,6 @@ class Route { /** * @returns {void} */ - // @ts-ignore #sanitize() { if (this.config.method) { this.config.method = this.config.method.toLowerCase(); @@ -139,7 +137,6 @@ class Route { /** * @returns {void} */ - // @ts-ignore #generateMatcher() { const activeMatchers = Route.registeredMatchers .filter(({ name }) => name in this.config) @@ -155,7 +152,6 @@ class Route { /** * @returns {void} */ - // @ts-ignore #limit() { if (!this.config.repeat) { return; @@ -176,7 +172,6 @@ class Route { /** * @returns {void} */ - // @ts-ignore #delayResponse() { if (this.config.delay) { const { response } = this.config; diff --git a/packages/core/src/Router.js b/packages/core/src/Router.js index 4bc8a0b3..08006b52 100644 --- a/packages/core/src/Router.js +++ b/packages/core/src/Router.js @@ -288,20 +288,6 @@ export default class Router { }); } - /** - * @overload - * @param {UserRouteConfig} matcher - * @returns {void} - */ - - /** - * @overload - * @param {RouteMatcher } matcher - * @param {RouteResponse} response - * @param {UserRouteConfig | string} [nameOrOptions] - * @returns {void} - */ - /** * @param {RouteMatcher | UserRouteConfig} matcher * @param {RouteResponse} [response] diff --git a/packages/core/src/__tests__/FetchMock/routing.test.js b/packages/core/src/__tests__/FetchMock/routing.test.js index 264ce127..17f7eb09 100644 --- a/packages/core/src/__tests__/FetchMock/routing.test.js +++ b/packages/core/src/__tests__/FetchMock/routing.test.js @@ -212,27 +212,6 @@ describe('Routing', () => { }); testChainableRoutingMethod(`${method}Once`); - - it(`has ${method}Any() shorthand`, () => { - fm[`${method}Any`]('a', { opt: 'b' }); - expect(fm.router.addRoute).toHaveBeenCalledWith('*', 'a', { - opt: 'b', - method, - }); - }); - - testChainableRoutingMethod(`${method}Any`); - - it(`has ${method}AnyOnce() shorthand`, () => { - fm[`${method}AnyOnce`]('a', { opt: 'b' }); - expect(fm.router.addRoute).toHaveBeenCalledWith('*', 'a', { - opt: 'b', - method, - repeat: 1, - }); - }); - - testChainableRoutingMethod(`${method}Any`); }); }); }); diff --git a/packages/core/src/index.js b/packages/core/src/index.js index e69de29b..75a25900 100644 --- a/packages/core/src/index.js +++ b/packages/core/src/index.js @@ -0,0 +1,2 @@ +import fetchMock from './FetchMock.js'; +export default fetchMock; diff --git a/packages/core/src/node_modules/is-subset/index.d.ts b/packages/core/src/node_modules/is-subset/index.d.ts new file mode 100644 index 00000000..1ad5b509 --- /dev/null +++ b/packages/core/src/node_modules/is-subset/index.d.ts @@ -0,0 +1 @@ +export default function (Object, Object): boolean \ No newline at end of file diff --git a/packages/core/types/CallHistory.d.ts b/packages/core/types/CallHistory.d.ts new file mode 100644 index 00000000..44b20021 --- /dev/null +++ b/packages/core/types/CallHistory.d.ts @@ -0,0 +1,40 @@ +export default CallHistory; +export type RouteConfig = import("./Route").RouteConfig; +export type RouteName = import("./Route").RouteName; +export type NormalizedRequestOptions = import("./RequestUtils").NormalizedRequestOptions; +export type RouteMatcher = import("./Matchers").RouteMatcher; +export type FetchMockConfig = import("./FetchMock").FetchMockConfig; +export type CallLog = { + arguments: any[]; + url: string; + options: NormalizedRequestOptions; + request?: Request; + signal?: AbortSignal; + route?: Route; + response?: Response; + expressParams?: { + [x: string]: string; + }; + queryParams?: { + [x: string]: string; + }; + pendingPromises: Promise[]; +}; +export type Matched = "matched"; +export type Unmatched = "unmatched"; +export type CallHistoryFilter = RouteName | Matched | Unmatched | boolean | RouteMatcher; +declare class CallHistory { + constructor(globalConfig: FetchMockConfig, router: Router); + callLogs: CallLog[]; + config: import("./FetchMock").FetchMockConfig; + router: Router; + recordCall(callLog: CallLog): void; + clear(): void; + flush(waitForResponseMethods?: boolean): Promise; + calls(filter: CallHistoryFilter, options: RouteConfig): CallLog[]; + called(filter: CallHistoryFilter, options: RouteConfig): boolean; + lastCall(filter: CallHistoryFilter, options: RouteConfig): CallLog; + done(routeNames?: RouteName | RouteName[]): boolean; +} +import Route from './Route.js'; +import Router from './Router.js'; diff --git a/packages/core/types/FetchHandler.d.ts b/packages/core/types/FetchHandler.d.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/core/types/FetchMock.d.ts b/packages/core/types/FetchMock.d.ts new file mode 100644 index 00000000..092d3102 --- /dev/null +++ b/packages/core/types/FetchMock.d.ts @@ -0,0 +1,97 @@ +export default fetchMock; +export type RouteMatcher = import("./Router").RouteMatcher; +export type RouteName = import("./Route").RouteName; +export type UserRouteConfig = import("./Route").UserRouteConfig; +export type RouteResponse = import("./Router").RouteResponse; +export type MatcherDefinition = import("./Matchers").MatcherDefinition; +export type CallLog = import("./CallHistory").CallLog; +export type RouteResponseFunction = import("./Route").RouteResponseFunction; +export type FetchMockConfig = { + sendAsJson?: boolean; + includeContentLength?: boolean; + warnOnFallback?: boolean; + matchPartialBody?: boolean; + fetch?: (arg0: string | Request, arg1: RequestInit) => Promise; + Headers?: typeof Headers; + Request?: typeof Request; + Response?: typeof Response; +}; +declare const fetchMock: FetchMock; +declare class FetchMock { + constructor(config: FetchMockConfig, router?: Router); + config: FetchMockConfig; + router: Router; + callHistory: CallHistory; + createInstance(): FetchMock; + fetchHandler(this: FetchMock, requestInput: string | Request, requestInit?: RequestInit): Promise; + route(matcher: UserRouteConfig): FetchMock; + route(matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + catch(this: FetchMock, response?: RouteResponse): FetchMock; + defineMatcher(matcher: MatcherDefinition): void; + removeRoutes(options?: { + names?: string[]; + includeSticky?: boolean; + includeFallback?: boolean; + }): FetchMock; + clearHistory(): FetchMock; + sticky: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; + once: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; + any: (this: FetchMock, response: RouteResponse, options?: UserRouteConfig | string) => FetchMock; + anyOnce: (this: FetchMock, response: RouteResponse, options?: UserRouteConfig | string) => FetchMock; + get: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; + getOnce: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; + post: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; + postOnce: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; + put: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; + putOnce: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; + delete: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; + deleteOnce: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; + head: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; + headOnce: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; + patch: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; + patchOnce: { + (this: FetchMock, matcher: UserRouteConfig): FetchMock; + (this: FetchMock, matcher: RouteMatcher, response: RouteResponse, options?: UserRouteConfig | string): FetchMock; + }; +} +import Router from './Router.js'; +import CallHistory from './CallHistory.js'; diff --git a/packages/core/types/Matchers.d.ts b/packages/core/types/Matchers.d.ts index acacfbac..10f7e149 100644 --- a/packages/core/types/Matchers.d.ts +++ b/packages/core/types/Matchers.d.ts @@ -1,38 +1,15 @@ - - -/** - * Mock matcher function - */ -type RouteMatcherUrl = string | RegExp | URL; - - - - -/** - * Mock matcher. Can be one of following: - * string: Either - * * an exact url to match e.g. 'http://www.site.com/page.html' - * * if the string begins with a `^`, the string following the `^` must - * begin the url e.g. '^http://www.site.com' would match - * 'http://www.site.com' or 'http://www.site.com/page.html' - * * '*' to match any url - * RegExp: A regular expression to test the url against - * Function(url, opts): A function (returning a Boolean) that is passed the - * url and opts fetch() is called with (or, if fetch() was called with one, - * the Request instance) - */ -type RouteMatcher = RouteMatcherUrl | RouteMatcherFunction; - -type UrlMatcher = (url: string) => boolean; - -type UrlMatcherGenerator = (pattern: string) => UrlMatcher; - -type RouteMatcherFunction = (url: string, opts: NormalizedRequestOptions, request: Request) => boolean; - -type MatcherGenerator = (route: RouteOptions) => RouteMatcherFunction; - -type MatcherDefinition = { +export function isUrlMatcher(matcher: RouteMatcher | RouteConfig): matcher is RouteMatcherUrl; +export function isFunctionMatcher(matcher: RouteMatcher | RouteConfig): matcher is RouteMatcherFunction; +export const builtInMatchers: MatcherDefinition[]; +export type RouteConfig = import("./Route").RouteConfig; +export type CallLog = import("./CallHistory").CallLog; +export type RouteMatcherUrl = string | RegExp | URL; +export type UrlMatcherGenerator = (arg0: string) => RouteMatcherFunction; +export type RouteMatcherFunction = (arg0: CallLog) => boolean; +export type MatcherGenerator = (arg0: RouteConfig) => RouteMatcherFunction; +export type RouteMatcher = RouteMatcherUrl | RouteMatcherFunction; +export type MatcherDefinition = { name: string; matcher: MatcherGenerator; usesBody?: boolean; -} \ No newline at end of file +}; diff --git a/packages/core/types/RequestUtils.d.ts b/packages/core/types/RequestUtils.d.ts index fdd66853..919c6b4e 100644 --- a/packages/core/types/RequestUtils.d.ts +++ b/packages/core/types/RequestUtils.d.ts @@ -1,12 +1,19 @@ -interface DerivedRequestOptions { +export function normalizeUrl(url: string | string | URL): string; +export function createCallLogFromUrlAndOptions(url: string | object, options: RequestInit): CallLog; +export function createCallLogFromRequest(request: Request, options: RequestInit): Promise; +export function getPath(url: string): string; +export function getQuery(url: string): string; +export function normalizeHeaders(headers: Headers | [string, string][] | Record | { + [x: string]: string | number; +} | HeadersInit): { + [x: string]: string; +}; +export type DerivedRequestOptions = { method: string; - body?: Promise; - headers?: { [key: string]: string | [string] } -} -type NormalizedRequestOptions = RequestInit | (RequestInit & DerivedRequestOptions) -interface NormalizedRequest { - url: string; - options: NormalizedRequestOptions; - request?: Request; - signal?: AbortSignal; -} \ No newline at end of file + body?: string; + headers?: { + [key: string]: string; + }; +}; +export type NormalizedRequestOptions = RequestInit | (RequestInit & DerivedRequestOptions); +export type CallLog = import("./CallHistory").CallLog; diff --git a/packages/core/types/Route.d.ts b/packages/core/types/Route.d.ts index ab351b1a..e3a79fc2 100644 --- a/packages/core/types/Route.d.ts +++ b/packages/core/types/Route.d.ts @@ -1,145 +1,71 @@ -declare class Route { - /** - * @param {MatcherDefinition} matcher - */ - static defineMatcher(matcher: any): void; - /** - * @overload - * @param {RouteOptions} matcher - * @param {undefined} response - * @param {undefined} options - * @param {FetchMockConfig} globalConfig - */ - /** - * @overload - * @param {RouteMatcher } matcher - * @param {RouteResponse} response - * @param {RouteOptions | string} options - * @param {FetchMockConfig} globalConfig - */ - /** - * @param {RouteMatcher | RouteOptions} matcher - * @param {RouteResponse} [response] - * @param {RouteOptions | string} [options] - * @param {FetchMockConfig} [globalConfig] - */ - constructor(matcher: any | any, response?: any, options?: any | string, globalConfig?: any); - originalInput: { - matcher: any; - response: any; - options: any; +export default Route; +export type RouteMatcher = import("./Matchers").RouteMatcher; +export type CallLog = import("./CallHistory").CallLog; +export type RouteMatcherFunction = import("./Matchers").RouteMatcherFunction; +export type RouteMatcherUrl = import("./Matchers").RouteMatcherUrl; +export type MatcherDefinition = import("./Matchers").MatcherDefinition; +export type FetchMockConfig = import("./FetchMock").FetchMockConfig; +export type RouteResponseConfig = { + body?: string | {}; + status?: number; + headers?: { + [key: string]: string; }; - routeOptions: RouteOptions; - reset: () => void; - response: () => Promise; - matcher: RouteMatcherFunction; - #private; -} -declare namespace Route { - export const registeredMatchers: any[]; -} - - - - -/** - * Mock options object - */ -interface RouteOptions { - /** - * A unique string naming the route. Used to subsequently retrieve - * references to the calls, grouped by name. - */ - name?: string; - - /** - * http method to match - */ + throws?: Error; + redirectUrl?: string; + options?: ResponseInit; +}; +export type ResponseInitUsingHeaders = { + status: number; + statusText: string; + headers: Headers; +}; +export type RouteResponseObjectData = RouteResponseConfig | object; +export type RouteResponseData = Response | number | string | RouteResponseObjectData; +export type RouteResponsePromise = Promise; +export type RouteResponseFunction = (arg0: CallLog) => (RouteResponseData | RouteResponsePromise); +export type RouteResponse = RouteResponseData | RouteResponsePromise | RouteResponseFunction; +export type RouteName = string; +export type UserRouteConfig = { + name?: RouteName; method?: string; - - /** - * key/value map of headers to match - */ - headers?: { [key: string]: string | number }; - - /** - * key/value map of query strings to match, in any order - */ - query?: { [key: string]: string }; - - /** - * key/value map of express style path params to match - */ - params?: { [key: string]: string }; - - /** - * JSON serialisable object literal. Allowing any object for now - * But in typescript 3.7 will change to JSON - */ + headers?: { + [key: string]: string | number; + }; + query?: { + [key: string]: string; + }; + params?: { + [key: string]: string; + }; body?: object; - - /** - * A function for arbitrary matching - */ - functionMatcher?: RouteMatcherFunction; - - /** - * as specified above - */ + matcherFunction?: RouteMatcherFunction; matcher?: RouteMatcher; - url?: RouteMatcherUrl; - - /** - * This option allows for existing routes in a mock to be overwritten. - * It’s also possible to define multiple routes with ‘the same’ matcher. - * Default behaviour is to error - */ - overwriteRoutes?: boolean; - - /** - * as specified above - */ response?: RouteResponse | RouteResponseFunction; - - /** - * integer, n, limiting the number of times the matcher can be used. - * If the route has already been called n times the route will be - * ignored and the call to fetch() will fall through to be handled by - * any other routes defined (which may eventually result in an error - * if nothing matches it). - */ repeat?: number; - - /** - * integer, n, delays responding for the number of milliseconds - * specified. - */ delay?: number; - - /** - * Convert objects into JSON before delivering as stub responses. Can - * be useful to set to false globally if e.g. dealing with a lot of - * array buffers. If true, will also add content-type: application/json - * header. - * @default true - */ sendAsJson?: boolean; - - /** - * Automatically sets a content-length header on each response. - * @default true - */ includeContentLength?: boolean; - - /** - * Match calls that only partially match a specified body json. - */ matchPartialBody?: 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 - */ sticky?: boolean; -} \ No newline at end of file + usesBody?: boolean; + isFallback?: boolean; +}; +export type RouteConfig = UserRouteConfig & FetchMockConfig; +declare class Route { + static defineMatcher(matcher: MatcherDefinition): void; + static registeredMatchers: MatcherDefinition[]; + constructor(config: RouteConfig); + config: RouteConfig; + matcher: RouteMatcherFunction | undefined; + reset(): void; + constructResponse(responseInput: RouteResponseConfig): { + response: Response; + responseOptions: ResponseInit; + responseInput: RouteResponseConfig; + }; + constructResponseOptions(responseInput: RouteResponseConfig): ResponseInitUsingHeaders; + constructResponseBody(responseInput: RouteResponseConfig, responseOptions: ResponseInitUsingHeaders): string | null; + #private; +} diff --git a/packages/core/types/Router.d.ts b/packages/core/types/Router.d.ts index 0ffb915d..20a798e2 100644 --- a/packages/core/types/Router.d.ts +++ b/packages/core/types/Router.d.ts @@ -1,219 +1,37 @@ - - -interface RouteOptionsMethodGet extends RouteOptions { - method?: 'GET'; -} - -interface RouteOptionsMethodPost extends RouteOptions { - method?: 'POST'; -} - -interface RouteOptionsMethodPut extends RouteOptions { - method?: 'PUT'; -} - -interface RouteOptionsMethodDelete extends RouteOptions { - method?: 'DELETE'; -} - -interface RouteOptionsMethodPatch extends RouteOptions { - method?: 'PATCH'; -} - -interface RouteOptionsMethodHead extends RouteOptions { - method?: 'HEAD'; -} - -interface Router { - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Calls to .mock() can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -route(matcher: RouteMatcher | RouteOptions, response: MockResponse | MockResponseFunction, options ?: RouteOptions): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Calls to .mock() can be chained. - * @param options The route to mock - */ -route(options: RouteOptions): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() which creates a route - * that persists even when restore(), reset() or resetbehavior() are called. - * Calls to .sticky() can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -sticky(matcher: RouteMatcher | RouteOptions, response: MockResponse | MockResponseFunction, options ?: RouteOptions): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() limited to being - * called one time only. Calls to .once() can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Optional additional properties defining the route to mock - */ -once(matcher: RouteMatcher | RouteOptions, response: MockResponse | MockResponseFunction, options ?: RouteOptions): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() restricted to the GET - * method. Calls to .get() can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -get(matcher: RouteMatcher | RouteOptionsMethodGet, response: MockResponse | MockResponseFunction, options ?: RouteOptionsMethodGet): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() restricted to the GET - * method and limited to being called one time only. Calls to .getOnce() - * can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -getOnce(matcher: RouteMatcher | RouteOptionsMethodGet, response: MockResponse | MockResponseFunction, options ?: RouteOptionsMethodGet): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() restricted to the POST - * method. Calls to .post() can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -post(matcher: RouteMatcher | RouteOptionsMethodPost, response: MockResponse | MockResponseFunction, options ?: RouteOptionsMethodPost): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() restricted to the POST - * method and limited to being called one time only. Calls to .postOnce() - * can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -postOnce(matcher: RouteMatcher | RouteOptionsMethodPost, response: MockResponse | MockResponseFunction, options ?: RouteOptionsMethodPost): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() restricted to the PUT - * method. Calls to .put() can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -put(matcher: RouteMatcher | RouteOptionsMethodPut, response: MockResponse | MockResponseFunction, options ?: RouteOptionsMethodPut): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() restricted to the PUT - * method and limited to being called one time only. Calls to .putOnce() - * can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -putOnce(matcher: RouteMatcher | RouteOptionsMethodPut, response: MockResponse | MockResponseFunction, options ?: RouteOptionsMethodPut): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() restricted to the - * DELETE method. Calls to .delete() can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -delete (matcher: RouteMatcher | RouteOptionsMethodDelete, response: MockResponse | MockResponseFunction, options ?: RouteOptionsMethodDelete): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() restricted to the - * DELETE method and limited to being called one time only. Calls to - * .deleteOnce() can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -deleteOnce(matcher: RouteMatcher | RouteOptionsMethodDelete, response: MockResponse | MockResponseFunction, options ?: RouteOptionsMethodDelete): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() restricted to the HEAD - * method. Calls to .head() can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -head(matcher: RouteMatcher | RouteOptionsMethodHead, response: MockResponse | MockResponseFunction, options ?: RouteOptionsMethodHead): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() restricted to the HEAD - * method and limited to being called one time only. Calls to .headOnce() - * can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -headOnce(matcher: RouteMatcher | RouteOptionsMethodHead, response: MockResponse | MockResponseFunction, options ?: RouteOptionsMethodHead): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() restricted to the PATCH - * method. Calls to .patch() can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -patch(matcher: RouteMatcher | RouteOptionsMethodPatch, response: MockResponse | MockResponseFunction, options ?: RouteOptionsMethodPatch): this; - -/** - * Replaces fetch() with a stub which records its calls, grouped by - * route, and optionally returns a mocked Response object or passes the - * call through to fetch(). Shorthand forroute() restricted to the PATCH - * method and limited to being called one time only. Calls to .patchOnce() - * can be chained. - * @param matcher Condition for selecting which requests to mock - * @param response Configures the http response returned by the mock - * @param [options] Additional properties defining the route to mock - */ -patchOnce(matcher: RouteMatcher | RouteOptionsMethodPatch, response: MockResponse | MockResponseFunction, options ?: RouteOptionsMethodPatch): this; - - /** - * Chainable method that defines how to respond to calls to fetch that - * don't match any of the defined mocks. It accepts the same types of - * response as a normal call to .mock(matcher, response). It can also - * take an arbitrary function to completely customise behaviour of - * unmatched calls. If .catch() is called without any parameters then - * every unmatched call will receive a 200 response. - * @param [response] Configures the http response returned by the mock - */ - catch (response?: MockResponse | MockResponseFunction): this; - +export default class Router { + constructor(fetchMockConfig: FetchMockConfig, { routes, fallbackRoute }?: { + routes?: Route[]; + fallbackRoute?: Route; + }); + routes: Route[]; + config: import("./FetchMock").FetchMockConfig; + fallbackRoute: Route; + needsToReadBody(request: Request): boolean; + execute(callLog: CallLog): Promise; + generateResponse(callLog: CallLog): Promise<{ + response: Response; + responseOptions: ResponseInit; + responseInput: RouteResponseConfig; + }>; + createObservableResponse(response: Response, responseConfig: ResponseInit, responseInput: RouteResponseConfig, responseUrl: string, pendingPromises: Promise[]): Response; + addRoute(matcher: RouteMatcher | UserRouteConfig, response?: RouteResponse, nameOrOptions?: UserRouteConfig | string): void; + setFallback(response?: RouteResponse): void; + removeRoutes({ names, includeSticky, includeFallback }?: { + names?: string[]; + includeSticky?: boolean; + includeFallback?: boolean; + }): void; } +export type UserRouteConfig = import("./Route").UserRouteConfig; +export type RouteConfig = import("./Route").RouteConfig; +export type RouteResponse = import("./Route").RouteResponse; +export type RouteResponseData = import("./Route").RouteResponseData; +export type RouteResponseObjectData = import("./Route").RouteResponseObjectData; +export type RouteResponseConfig = import("./Route").RouteResponseConfig; +export type RouteResponseFunction = import("./Route").RouteResponseFunction; +export type RouteMatcher = import("./Matchers").RouteMatcher; +export type FetchMockConfig = import("./FetchMock").FetchMockConfig; +export type FetchMock = typeof import("./FetchMock"); +export type CallLog = import("./CallHistory").CallLog; +export type ResponseConfigProp = "body" | "headers" | "throws" | "status" | "redirectUrl"; +import Route from './Route.js'; diff --git a/packages/core/types/StatusTextMap.d.ts b/packages/core/types/StatusTextMap.d.ts new file mode 100644 index 00000000..eb8c81cc --- /dev/null +++ b/packages/core/types/StatusTextMap.d.ts @@ -0,0 +1,4 @@ +export default statusTextMap; +declare const statusTextMap: { + [x: number]: string; +}; diff --git a/packages/core/types/index.d.ts b/packages/core/types/index.d.ts new file mode 100644 index 00000000..1ae74276 --- /dev/null +++ b/packages/core/types/index.d.ts @@ -0,0 +1,2 @@ +export default fetchMock; +import fetchMock from './FetchMock.js';