msw 0.20.5 → 0.21.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/README.md +1 -1
- package/lib/esm/fetch-deps.js +26 -23
- package/lib/esm/graphql.js +92 -79
- package/lib/esm/index.js +90 -44
- package/lib/esm/{matchRequest-deps.js → matchRequestUrl-deps.js} +29 -17
- package/lib/esm/mockServiceWorker.js +8 -1
- package/lib/esm/rest-deps.js +27 -18
- package/lib/esm/rest.js +1 -1
- package/lib/esm/xml-deps.js +3 -3
- package/lib/types/LiveStorage.d.ts +17 -0
- package/lib/types/context/body.d.ts +2 -2
- package/lib/types/context/errors.d.ts +3 -1
- package/lib/types/context/fetch.d.ts +2 -2
- package/lib/types/context/json.d.ts +5 -3
- package/lib/types/context/text.d.ts +2 -2
- package/lib/types/context/xml.d.ts +2 -2
- package/lib/types/graphql.d.ts +8 -10
- package/lib/types/index.d.ts +3 -3
- package/lib/types/native/index.d.ts +7 -1
- package/lib/types/node/createSetupServer.d.ts +29 -0
- package/lib/types/node/setupServer.d.ts +4 -24
- package/lib/types/response.d.ts +10 -7
- package/lib/types/rest.d.ts +158 -16
- package/lib/types/setupWorker/glossary.d.ts +14 -4
- package/lib/types/setupWorker/start/utils/getWorkerByRegistration.d.ts +2 -1
- package/lib/types/setupWorker/start/utils/getWorkerInstance.d.ts +2 -2
- package/lib/types/sharedOptions.d.ts +1 -1
- package/lib/types/utils/getResponse.d.ts +2 -2
- package/lib/types/utils/handlers/requestHandler.d.ts +74 -0
- package/lib/types/utils/{requestHandlerUtils.d.ts → handlers/requestHandlerUtils.d.ts} +2 -2
- package/lib/types/utils/{isNodeProcess.d.ts → internal/isNodeProcess.d.ts} +1 -0
- package/lib/types/utils/{isStringEqual.d.ts → internal/isStringEqual.d.ts} +0 -0
- package/lib/types/utils/{jsonParse.d.ts → internal/jsonParse.d.ts} +0 -0
- package/lib/types/utils/internal/mergeRight.d.ts +5 -0
- package/lib/types/utils/{logger → logging}/getStatusCodeColor.d.ts +0 -0
- package/lib/types/utils/{logger → logging}/getTimestamp.d.ts +0 -0
- package/lib/types/utils/{logger → logging}/prepareRequest.d.ts +3 -3
- package/lib/types/utils/{logger → logging}/prepareResponse.d.ts +2 -2
- package/lib/types/utils/matching/{matchRequest.d.ts → matchRequestUrl.d.ts} +0 -0
- package/lib/types/utils/request/getPublicUrlFromRequest.d.ts +6 -0
- package/lib/types/utils/request/getRequestCookies.d.ts +1 -1
- package/lib/types/{onUnhandledRequest.d.ts → utils/request/onUnhandledRequest.d.ts} +1 -1
- package/lib/types/utils/request/parseBody.d.ts +5 -0
- package/lib/types/utils/url/getAbsoluteUrl.d.ts +6 -0
- package/lib/types/utils/{getAbsoluteWorkerUrl.d.ts → url/getAbsoluteWorkerUrl.d.ts} +0 -0
- package/lib/types/utils/url/getUrlByMask.d.ts +5 -0
- package/lib/umd/index.js +696 -613
- package/lib/umd/mockServiceWorker.js +8 -1
- package/native/index.js +1508 -133
- package/node/context/delay.d.ts +11 -0
- package/node/context/fetch.d.ts +8 -0
- package/node/context/set.d.ts +2 -0
- package/node/context/status.d.ts +2 -0
- package/node/index.js +1507 -133
- package/node/node/createSetupServer.d.ts +29 -0
- package/node/node/index.d.ts +5 -0
- package/node/node/setupServer.d.ts +7 -0
- package/node/response.d.ts +25 -0
- package/node/utils/NetworkError.d.ts +3 -0
- package/node/utils/getResponse.d.ts +14 -0
- package/{lib/types → node/utils}/handlers/requestHandler.d.ts +13 -12
- package/node/utils/handlers/requestHandlerUtils.d.ts +4 -0
- package/node/utils/internal/compose.d.ts +5 -0
- package/node/utils/internal/isNodeProcess.d.ts +5 -0
- package/node/utils/internal/jsonParse.d.ts +5 -0
- package/node/utils/request/getPublicUrlFromRequest.d.ts +6 -0
- package/node/utils/request/onUnhandledRequest.d.ts +5 -0
- package/node/utils/request/parseBody.d.ts +5 -0
- package/package.json +34 -29
- package/lib/types/utils/getJsonBody.d.ts +0 -5
- package/lib/types/utils/request/parseRequestBody.d.ts +0 -2
- package/lib/types/utils/resolveMask.d.ts +0 -6
- package/lib/types/utils/resolveRelativeUrl.d.ts +0 -6
package/CHANGELOG.md
ADDED
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ Browser usage is what sets Mock Service Worker apart from other tools. Utilizing
|
|
|
61
61
|
### How is it different?
|
|
62
62
|
|
|
63
63
|
- Intercepts requests on the network level, not the application level.
|
|
64
|
-
- If
|
|
64
|
+
- If you think of your application as a box, Mock Service Worker lives in its own box next to yours, instead of opening and altering it for the purpose of mocking.
|
|
65
65
|
- Agnostic of request-issuing libraries, so you can use it with `fetch`, `axios`, `react-query`, you-name-it.
|
|
66
66
|
- The same mock definition can be reused for unit, integration, E2E testing, and debugging.
|
|
67
67
|
|
package/lib/esm/fetch-deps.js
CHANGED
|
@@ -82,11 +82,11 @@ var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof win
|
|
|
82
82
|
|
|
83
83
|
function createCommonjsModule(fn, basedir, module) {
|
|
84
84
|
return module = {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
path: basedir,
|
|
86
|
+
exports: {},
|
|
87
|
+
require: function (path, base) {
|
|
88
|
+
return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
|
|
89
|
+
}
|
|
90
90
|
}, fn(module, module.exports), module.exports;
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -350,16 +350,16 @@ function set(...args) {
|
|
|
350
350
|
|
|
351
351
|
/**
|
|
352
352
|
* Returns a boolean indicating if the current process is running in NodeJS environment.
|
|
353
|
+
* @see https://github.com/mswjs/msw/pull/255
|
|
353
354
|
*/
|
|
354
|
-
// Please see https://github.com/mswjs/msw/pull/255
|
|
355
355
|
function isNodeProcess() {
|
|
356
|
+
// Check browser environment.
|
|
356
357
|
if (typeof global !== 'object') {
|
|
357
|
-
// check browser environment
|
|
358
358
|
return false;
|
|
359
359
|
}
|
|
360
|
+
// Check nodejs or React Native environment.
|
|
360
361
|
if (Object.prototype.toString.call(global.process) === '[object process]' ||
|
|
361
362
|
navigator.product === 'ReactNative') {
|
|
362
|
-
// check nodejs or react native environment
|
|
363
363
|
return true;
|
|
364
364
|
}
|
|
365
365
|
}
|
|
@@ -388,9 +388,11 @@ const delay = (durationMs) => {
|
|
|
388
388
|
};
|
|
389
389
|
|
|
390
390
|
/**
|
|
391
|
-
* Sets the given
|
|
391
|
+
* Sets the given value as the JSON body of the response.
|
|
392
392
|
* @example
|
|
393
|
-
* res(json({
|
|
393
|
+
* res(json({ key: 'value' }))
|
|
394
|
+
* res(json('Some string'))
|
|
395
|
+
* res(json([1, '2', false, { ok: true }]))
|
|
394
396
|
*/
|
|
395
397
|
const json = (body) => {
|
|
396
398
|
return (res) => {
|
|
@@ -401,20 +403,21 @@ const json = (body) => {
|
|
|
401
403
|
};
|
|
402
404
|
|
|
403
405
|
const useFetch = isNodeProcess() ? require('node-fetch') : window.fetch;
|
|
404
|
-
const gracefully = (promise) => {
|
|
405
|
-
return promise.then((res) => {
|
|
406
|
-
var _a;
|
|
407
|
-
if ((_a = res.headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('json')) {
|
|
408
|
-
return res.json();
|
|
409
|
-
}
|
|
410
|
-
return res.text();
|
|
411
|
-
});
|
|
412
|
-
};
|
|
413
406
|
const augmentRequestInit = (requestInit) => {
|
|
414
407
|
const headers = new lib.Headers(requestInit.headers);
|
|
415
408
|
headers.set('x-msw-bypass', 'true');
|
|
416
409
|
return Object.assign(Object.assign({}, requestInit), { headers: headers.getAllHeaders() });
|
|
417
410
|
};
|
|
411
|
+
const createFetchRequestParameters = (input) => {
|
|
412
|
+
const { body, method } = input;
|
|
413
|
+
const requestParameters = Object.assign(Object.assign({}, input), { body: undefined });
|
|
414
|
+
if (['GET', 'HEAD'].includes(method)) {
|
|
415
|
+
return requestParameters;
|
|
416
|
+
}
|
|
417
|
+
requestParameters.body =
|
|
418
|
+
typeof body === 'object' ? JSON.stringify(body) : body;
|
|
419
|
+
return requestParameters;
|
|
420
|
+
};
|
|
418
421
|
/**
|
|
419
422
|
* Wrapper around the native `window.fetch()` function that performs
|
|
420
423
|
* a request bypassing MSW. Requests performed using
|
|
@@ -423,11 +426,11 @@ const augmentRequestInit = (requestInit) => {
|
|
|
423
426
|
const fetch = (input, requestInit = {}) => {
|
|
424
427
|
// Keep the default `window.fetch()` call signature
|
|
425
428
|
if (typeof input === 'string') {
|
|
426
|
-
return
|
|
429
|
+
return useFetch(input, augmentRequestInit(requestInit));
|
|
427
430
|
}
|
|
428
|
-
const
|
|
429
|
-
const
|
|
430
|
-
return
|
|
431
|
+
const requestParameters = createFetchRequestParameters(input);
|
|
432
|
+
const compliantRequest = augmentRequestInit(requestParameters);
|
|
433
|
+
return useFetch(input.url.href, compliantRequest);
|
|
431
434
|
};
|
|
432
435
|
|
|
433
436
|
export { set as a, commonjsGlobal as b, createCommonjsModule as c, delay as d, fetch as f, isNodeProcess as i, json as j, lib as l, status as s };
|
package/lib/esm/graphql.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as set, s as status, d as delay, f as fetch } from './fetch-deps.js';
|
|
2
2
|
import { d as data, e as errors } from './errors-deps.js';
|
|
3
|
-
import { j as jsonParse, m as matchRequestUrl,
|
|
3
|
+
import { j as jsonParse, m as matchRequestUrl, a as prepareRequest, b as prepareResponse, c as getTimestamp, d as getStatusCodeColor } from './matchRequestUrl-deps.js';
|
|
4
4
|
|
|
5
5
|
// istanbul ignore next (See: 'https://github.com/graphql/graphql-js/issues/2317')
|
|
6
6
|
var nodejsCustomInspectSymbol = typeof Symbol === 'function' && typeof Symbol.for === 'function' ? Symbol.for('nodejs.util.inspect.custom') : undefined;
|
|
@@ -3009,98 +3009,111 @@ const graphqlContext = {
|
|
|
3009
3009
|
function parseQuery(query, definitionOperation = 'query') {
|
|
3010
3010
|
var _a;
|
|
3011
3011
|
const ast = parse(query);
|
|
3012
|
-
const operationDef = ast.definitions.find((def) =>
|
|
3013
|
-
def.
|
|
3012
|
+
const operationDef = ast.definitions.find((def) => {
|
|
3013
|
+
return (def.kind === 'OperationDefinition' &&
|
|
3014
|
+
(definitionOperation === 'all' || def.operation === definitionOperation));
|
|
3015
|
+
});
|
|
3014
3016
|
return {
|
|
3017
|
+
operationType: operationDef === null || operationDef === void 0 ? void 0 : operationDef.operation,
|
|
3015
3018
|
operationName: (_a = operationDef === null || operationDef === void 0 ? void 0 : operationDef.name) === null || _a === void 0 ? void 0 : _a.value,
|
|
3016
3019
|
};
|
|
3017
3020
|
}
|
|
3018
|
-
|
|
3019
|
-
return
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
if (!query) {
|
|
3031
|
-
return null;
|
|
3032
|
-
}
|
|
3033
|
-
const variables = variablesString
|
|
3034
|
-
? jsonParse(variablesString)
|
|
3035
|
-
: {};
|
|
3036
|
-
const { operationName } = parseQuery(query, operationType);
|
|
3037
|
-
return {
|
|
3038
|
-
operationType,
|
|
3039
|
-
operationName,
|
|
3040
|
-
variables,
|
|
3041
|
-
};
|
|
3042
|
-
}
|
|
3043
|
-
case 'POST': {
|
|
3044
|
-
if (!((_a = req.body) === null || _a === void 0 ? void 0 : _a.query)) {
|
|
3045
|
-
return null;
|
|
3046
|
-
}
|
|
3047
|
-
const { query, variables } = req.body;
|
|
3048
|
-
const { operationName } = parseQuery(query, operationType);
|
|
3049
|
-
return {
|
|
3050
|
-
operationType,
|
|
3051
|
-
operationName,
|
|
3052
|
-
variables,
|
|
3053
|
-
};
|
|
3054
|
-
}
|
|
3055
|
-
default:
|
|
3021
|
+
function graphQLRequestHandler(expectedOperationType, expectedOperationName, mask, resolver) {
|
|
3022
|
+
return {
|
|
3023
|
+
resolver,
|
|
3024
|
+
parse(req) {
|
|
3025
|
+
var _a;
|
|
3026
|
+
// According to the GraphQL specification, a GraphQL request can be issued
|
|
3027
|
+
// using both "GET" and "POST" methods.
|
|
3028
|
+
switch (req.method) {
|
|
3029
|
+
case 'GET': {
|
|
3030
|
+
const query = req.url.searchParams.get('query');
|
|
3031
|
+
const variablesString = req.url.searchParams.get('variables') || '';
|
|
3032
|
+
if (!query) {
|
|
3056
3033
|
return null;
|
|
3034
|
+
}
|
|
3035
|
+
const variables = variablesString
|
|
3036
|
+
? jsonParse(variablesString)
|
|
3037
|
+
: {};
|
|
3038
|
+
const { operationType, operationName } = parseQuery(query, expectedOperationType);
|
|
3039
|
+
return {
|
|
3040
|
+
operationType,
|
|
3041
|
+
operationName,
|
|
3042
|
+
variables,
|
|
3043
|
+
};
|
|
3057
3044
|
}
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
return
|
|
3045
|
+
case 'POST': {
|
|
3046
|
+
if (!((_a = req.body) === null || _a === void 0 ? void 0 : _a.query)) {
|
|
3047
|
+
return null;
|
|
3048
|
+
}
|
|
3049
|
+
const { query, variables } = req.body;
|
|
3050
|
+
const { operationType, operationName } = parseQuery(query, expectedOperationType);
|
|
3051
|
+
return {
|
|
3052
|
+
operationType,
|
|
3053
|
+
operationName,
|
|
3054
|
+
variables,
|
|
3055
|
+
};
|
|
3065
3056
|
}
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
return
|
|
3076
|
-
}
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3057
|
+
default:
|
|
3058
|
+
return null;
|
|
3059
|
+
}
|
|
3060
|
+
},
|
|
3061
|
+
getPublicRequest(req, parsed) {
|
|
3062
|
+
return Object.assign(Object.assign({}, req), { variables: parsed.variables || {} });
|
|
3063
|
+
},
|
|
3064
|
+
predicate(req, parsed) {
|
|
3065
|
+
if (!parsed || !parsed.operationName) {
|
|
3066
|
+
return false;
|
|
3067
|
+
}
|
|
3068
|
+
// Match the request URL against a given mask,
|
|
3069
|
+
// in case of an endpoint-specific request handler.
|
|
3070
|
+
const hasMatchingMask = matchRequestUrl(req.url, mask);
|
|
3071
|
+
const isMatchingOperation = expectedOperationName instanceof RegExp
|
|
3072
|
+
? expectedOperationName.test(parsed.operationName)
|
|
3073
|
+
: expectedOperationName === parsed.operationName;
|
|
3074
|
+
return hasMatchingMask.matches && isMatchingOperation;
|
|
3075
|
+
},
|
|
3076
|
+
defineContext() {
|
|
3077
|
+
return graphqlContext;
|
|
3078
|
+
},
|
|
3079
|
+
log(req, res, handler, parsed) {
|
|
3080
|
+
const { operationType, operationName } = parsed;
|
|
3081
|
+
const loggedRequest = prepareRequest(req);
|
|
3082
|
+
const loggedResponse = prepareResponse(res);
|
|
3083
|
+
console.groupCollapsed('[MSW] %s %s (%c%s%c)', getTimestamp(), operationName, `color:${getStatusCodeColor(res.status)}`, res.status, 'color:inherit');
|
|
3084
|
+
console.log('Request:', loggedRequest);
|
|
3085
|
+
console.log('Handler:', {
|
|
3086
|
+
operationType,
|
|
3087
|
+
operationName: expectedOperationName,
|
|
3088
|
+
predicate: handler.predicate,
|
|
3089
|
+
});
|
|
3090
|
+
console.log('Response:', loggedResponse);
|
|
3091
|
+
console.groupEnd();
|
|
3092
|
+
},
|
|
3093
|
+
};
|
|
3094
|
+
}
|
|
3095
|
+
const createGraphQLScopedHandler = (expectedOperationType, mask) => {
|
|
3096
|
+
return (expectedOperationName, resolver) => {
|
|
3097
|
+
return graphQLRequestHandler(expectedOperationType, expectedOperationName, mask, resolver);
|
|
3098
|
+
};
|
|
3099
|
+
};
|
|
3100
|
+
const createGraphQLOperationHandler = (mask) => {
|
|
3101
|
+
return (resolver) => {
|
|
3102
|
+
return graphQLRequestHandler('all', new RegExp('.*'), mask, resolver);
|
|
3092
3103
|
};
|
|
3093
3104
|
};
|
|
3094
3105
|
const graphqlStandardHandlers = {
|
|
3095
|
-
|
|
3096
|
-
|
|
3106
|
+
operation: createGraphQLOperationHandler('*'),
|
|
3107
|
+
query: createGraphQLScopedHandler('query', '*'),
|
|
3108
|
+
mutation: createGraphQLScopedHandler('mutation', '*'),
|
|
3097
3109
|
};
|
|
3098
3110
|
function createGraphQLLink(uri) {
|
|
3099
3111
|
return {
|
|
3100
|
-
|
|
3101
|
-
|
|
3112
|
+
operation: createGraphQLOperationHandler(uri),
|
|
3113
|
+
query: createGraphQLScopedHandler('query', uri),
|
|
3114
|
+
mutation: createGraphQLScopedHandler('mutation', uri),
|
|
3102
3115
|
};
|
|
3103
3116
|
}
|
|
3104
3117
|
const graphql = Object.assign(Object.assign({}, graphqlStandardHandlers), { link: createGraphQLLink });
|
|
3105
3118
|
|
|
3106
|
-
export { graphql, graphqlContext
|
|
3119
|
+
export { graphql, graphqlContext };
|
package/lib/esm/index.js
CHANGED
|
@@ -2,25 +2,25 @@ import { c as createCommonjsModule, s as status, a as set, d as delay, f as fetc
|
|
|
2
2
|
import { p as parse_1 } from './xml-deps.js';
|
|
3
3
|
import './errors-deps.js';
|
|
4
4
|
export { i as context } from './index-deps.js';
|
|
5
|
-
import { g as
|
|
6
|
-
export { m as matchRequestUrl } from './matchRequest-deps.js';
|
|
7
|
-
import { i as isStringEqual } from './rest-deps.js';
|
|
5
|
+
import { g as getPublicUrlFromRequest, i as isStringEqual } from './rest-deps.js';
|
|
8
6
|
export { R as RESTMethods, r as rest, a as restContext } from './rest-deps.js';
|
|
7
|
+
import { p as parseBody } from './matchRequestUrl-deps.js';
|
|
8
|
+
export { m as matchRequestUrl } from './matchRequestUrl-deps.js';
|
|
9
9
|
export { graphql, graphqlContext } from './graphql.js';
|
|
10
10
|
|
|
11
11
|
/*! *****************************************************************************
|
|
12
|
-
Copyright (c) Microsoft Corporation.
|
|
13
|
-
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
14
|
-
this file except in compliance with the License. You may obtain a copy of the
|
|
15
|
-
License at http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
Copyright (c) Microsoft Corporation.
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
|
20
|
-
MERCHANTABLITY OR NON-INFRINGEMENT.
|
|
14
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
15
|
+
purpose with or without fee is hereby granted.
|
|
21
16
|
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
18
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
19
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
20
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
21
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
22
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
23
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
24
24
|
***************************************************************************** */
|
|
25
25
|
|
|
26
26
|
function __awaiter(thisArg, _arguments, P, generator) {
|
|
@@ -63,7 +63,7 @@ exports.until = until.until;
|
|
|
63
63
|
* Attempts to resolve a Service Worker instance from a given registration,
|
|
64
64
|
* regardless of its state (active, installing, waiting).
|
|
65
65
|
*/
|
|
66
|
-
const getWorkerByRegistration = (registration, absoluteWorkerUrl) => {
|
|
66
|
+
const getWorkerByRegistration = (registration, absoluteWorkerUrl, findWorker) => {
|
|
67
67
|
const allStates = [
|
|
68
68
|
registration.active,
|
|
69
69
|
registration.installing,
|
|
@@ -71,7 +71,7 @@ const getWorkerByRegistration = (registration, absoluteWorkerUrl) => {
|
|
|
71
71
|
];
|
|
72
72
|
const existingStates = allStates.filter(Boolean);
|
|
73
73
|
const mockWorker = existingStates.find((worker) => {
|
|
74
|
-
return worker.scriptURL
|
|
74
|
+
return findWorker(worker.scriptURL, absoluteWorkerUrl);
|
|
75
75
|
});
|
|
76
76
|
return mockWorker || null;
|
|
77
77
|
};
|
|
@@ -88,13 +88,13 @@ function getAbsoluteWorkerUrl(relativeUrl) {
|
|
|
88
88
|
* Returns an active Service Worker instance.
|
|
89
89
|
* When not found, registers a new Service Worker.
|
|
90
90
|
*/
|
|
91
|
-
const getWorkerInstance = (url, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
92
|
-
// Resolve the absolute Service Worker URL
|
|
91
|
+
const getWorkerInstance = (url, options = {}, findWorker) => __awaiter(void 0, void 0, void 0, function* () {
|
|
92
|
+
// Resolve the absolute Service Worker URL.
|
|
93
93
|
const absoluteWorkerUrl = getAbsoluteWorkerUrl(url);
|
|
94
94
|
const [, mockRegistrations] = yield lib.until(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
95
95
|
const registrations = yield navigator.serviceWorker.getRegistrations();
|
|
96
96
|
return registrations.filter((registration) => {
|
|
97
|
-
return getWorkerByRegistration(registration, absoluteWorkerUrl);
|
|
97
|
+
return getWorkerByRegistration(registration, absoluteWorkerUrl, findWorker);
|
|
98
98
|
});
|
|
99
99
|
}));
|
|
100
100
|
if (!navigator.serviceWorker.controller && mockRegistrations.length > 0) {
|
|
@@ -108,23 +108,25 @@ const getWorkerInstance = (url, options) => __awaiter(void 0, void 0, void 0, fu
|
|
|
108
108
|
}
|
|
109
109
|
const [existingRegistration] = mockRegistrations;
|
|
110
110
|
if (existingRegistration) {
|
|
111
|
-
//
|
|
111
|
+
// When the Service Worker is registered, update it and return the reference.
|
|
112
112
|
return existingRegistration.update().then(() => {
|
|
113
113
|
return [
|
|
114
|
-
getWorkerByRegistration(existingRegistration, absoluteWorkerUrl),
|
|
114
|
+
getWorkerByRegistration(existingRegistration, absoluteWorkerUrl, findWorker),
|
|
115
115
|
existingRegistration,
|
|
116
116
|
];
|
|
117
117
|
});
|
|
118
118
|
}
|
|
119
|
+
// When the Service Worker wasn't found, register it anew and return the reference.
|
|
119
120
|
const [error, instance] = yield lib.until(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
120
121
|
const registration = yield navigator.serviceWorker.register(url, options);
|
|
121
122
|
return [
|
|
122
123
|
// Compare existing worker registration by its worker URL,
|
|
123
124
|
// to prevent irrelevant workers to resolve here (such as Codesandbox worker).
|
|
124
|
-
getWorkerByRegistration(registration, absoluteWorkerUrl),
|
|
125
|
+
getWorkerByRegistration(registration, absoluteWorkerUrl, findWorker),
|
|
125
126
|
registration,
|
|
126
127
|
];
|
|
127
128
|
}));
|
|
129
|
+
// Handle Service Worker registration errors.
|
|
128
130
|
if (error) {
|
|
129
131
|
const isWorkerMissing = error.message.includes('(404)');
|
|
130
132
|
// Produce a custom error message when given a non-existing Service Worker url.
|
|
@@ -307,7 +309,14 @@ function onUnhandledRequest(request, onUnhandledRequest = 'bypass') {
|
|
|
307
309
|
onUnhandledRequest(request);
|
|
308
310
|
return;
|
|
309
311
|
}
|
|
310
|
-
const
|
|
312
|
+
const publicUrl = getPublicUrlFromRequest(request);
|
|
313
|
+
const message = `captured a ${request.method} ${request.url} request without a corresponding request handler.
|
|
314
|
+
|
|
315
|
+
If you wish to intercept this request, consider creating a request handler for it:
|
|
316
|
+
|
|
317
|
+
rest.${request.method.toLowerCase()}('${publicUrl}', (req, res, ctx) => {
|
|
318
|
+
return res(ctx.text('body'))
|
|
319
|
+
})`;
|
|
311
320
|
switch (onUnhandledRequest) {
|
|
312
321
|
case 'error': {
|
|
313
322
|
throw new Error(`[MSW] Error: ${message}`);
|
|
@@ -320,21 +329,6 @@ function onUnhandledRequest(request, onUnhandledRequest = 'bypass') {
|
|
|
320
329
|
}
|
|
321
330
|
}
|
|
322
331
|
|
|
323
|
-
function parseRequestBody(body, headers) {
|
|
324
|
-
var _a;
|
|
325
|
-
if (body) {
|
|
326
|
-
// If the intercepted request's body has a JSON Content-Type
|
|
327
|
-
// parse it into an object, otherwise leave as-is.
|
|
328
|
-
const hasJsonContent = (_a = headers === null || headers === void 0 ? void 0 : headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.includes('json');
|
|
329
|
-
if (hasJsonContent && typeof body !== 'object') {
|
|
330
|
-
return getJsonBody(body);
|
|
331
|
-
}
|
|
332
|
-
return body;
|
|
333
|
-
}
|
|
334
|
-
// Return whatever falsey body value is given.
|
|
335
|
-
return body;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
332
|
function getAllCookies() {
|
|
339
333
|
return parse_1(document.cookie);
|
|
340
334
|
}
|
|
@@ -389,7 +383,7 @@ const handleRequestWith = (context, options) => {
|
|
|
389
383
|
return null;
|
|
390
384
|
}
|
|
391
385
|
// Parse the request's body based on the "Content-Type" header.
|
|
392
|
-
req.body =
|
|
386
|
+
req.body = parseBody(req.body, req.headers);
|
|
393
387
|
// Set document cookies on the request.
|
|
394
388
|
req.cookies = getRequestCookies(req);
|
|
395
389
|
const { response, handler, publicRequest, parsedRequest, } = yield getResponse(req, context.requestHandlers);
|
|
@@ -452,8 +446,8 @@ function requestIntegrityCheck(context, serviceWorker) {
|
|
|
452
446
|
const { payload: actualChecksum } = yield context.events.once('INTEGRITY_CHECK_RESPONSE');
|
|
453
447
|
// Compare the response from the Service Worker and the
|
|
454
448
|
// global variable set by webpack upon build.
|
|
455
|
-
if (actualChecksum !== "
|
|
456
|
-
throw new Error(`Currently active Service Worker (${actualChecksum}) is behind the latest published one (${"
|
|
449
|
+
if (actualChecksum !== "d1e0e502f550d40a34bee90822e4bf98") {
|
|
450
|
+
throw new Error(`Currently active Service Worker (${actualChecksum}) is behind the latest published one (${"d1e0e502f550d40a34bee90822e4bf98"}).`);
|
|
457
451
|
}
|
|
458
452
|
return serviceWorker;
|
|
459
453
|
});
|
|
@@ -465,15 +459,17 @@ function requestIntegrityCheck(context, serviceWorker) {
|
|
|
465
459
|
* Must only be used in a browser.
|
|
466
460
|
*/
|
|
467
461
|
function deferNetworkRequestsUntil(predicatePromise) {
|
|
468
|
-
// Defer `XMLHttpRequest` until the Service Worker is ready.
|
|
462
|
+
// Defer any `XMLHttpRequest` requests until the Service Worker is ready.
|
|
469
463
|
const originalXhrSend = window.XMLHttpRequest.prototype.send;
|
|
470
464
|
window.XMLHttpRequest.prototype.send = function (...args) {
|
|
465
|
+
// Keep this function synchronous to comply with `XMLHttpRequest.prototype.send`,
|
|
466
|
+
// because that method is always synchronous.
|
|
471
467
|
lib.until(() => predicatePromise).then(() => {
|
|
472
468
|
window.XMLHttpRequest.prototype.send = originalXhrSend;
|
|
473
469
|
this.send(...args);
|
|
474
470
|
});
|
|
475
471
|
};
|
|
476
|
-
// Defer `fetch` requests until the Service Worker is ready.
|
|
472
|
+
// Defer any `fetch` requests until the Service Worker is ready.
|
|
477
473
|
const originalFetch = window.fetch;
|
|
478
474
|
window.fetch = (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
479
475
|
yield lib.until(() => predicatePromise);
|
|
@@ -482,6 +478,30 @@ function deferNetworkRequestsUntil(predicatePromise) {
|
|
|
482
478
|
});
|
|
483
479
|
}
|
|
484
480
|
|
|
481
|
+
function isObject(obj) {
|
|
482
|
+
return typeof obj === 'object';
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Deeply merges two given objects with the right one
|
|
486
|
+
* having a priority during property assignment.
|
|
487
|
+
*/
|
|
488
|
+
function mergeRight(a, b) {
|
|
489
|
+
const result = Object.assign({}, a);
|
|
490
|
+
Object.entries(b).forEach(([key, value]) => {
|
|
491
|
+
const existingValue = result[key];
|
|
492
|
+
if (Array.isArray(existingValue) && Array.isArray(value)) {
|
|
493
|
+
result[key] = existingValue.concat(value);
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
if (isObject(existingValue) && isObject(value)) {
|
|
497
|
+
result[key] = mergeRight(existingValue, value);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
result[key] = value;
|
|
501
|
+
});
|
|
502
|
+
return result;
|
|
503
|
+
}
|
|
504
|
+
|
|
485
505
|
const DEFAULT_START_OPTIONS = {
|
|
486
506
|
serviceWorker: {
|
|
487
507
|
url: '/mockServiceWorker.js',
|
|
@@ -490,13 +510,14 @@ const DEFAULT_START_OPTIONS = {
|
|
|
490
510
|
quiet: false,
|
|
491
511
|
waitUntilReady: true,
|
|
492
512
|
onUnhandledRequest: 'bypass',
|
|
513
|
+
findWorker: (scriptURL, mockServiceWorkerUrl) => scriptURL === mockServiceWorkerUrl,
|
|
493
514
|
};
|
|
494
515
|
const createStart = (context) => {
|
|
495
516
|
/**
|
|
496
517
|
* Registers and activates the mock Service Worker.
|
|
497
518
|
*/
|
|
498
519
|
return function start(options) {
|
|
499
|
-
const resolvedOptions =
|
|
520
|
+
const resolvedOptions = mergeRight(DEFAULT_START_OPTIONS, options || {});
|
|
500
521
|
const startWorkerInstance = () => __awaiter(this, void 0, void 0, function* () {
|
|
501
522
|
if (!('serviceWorker' in navigator)) {
|
|
502
523
|
console.error(`[MSW] Failed to register a Service Worker: this browser does not support Service Workers (see https://caniuse.com/serviceworkers), or your application is running on an insecure host (consider using HTTPS for custom hostnames).`);
|
|
@@ -507,12 +528,28 @@ const createStart = (context) => {
|
|
|
507
528
|
// of the application's code.
|
|
508
529
|
context.events.removeAllListeners();
|
|
509
530
|
context.events.addListener(navigator.serviceWorker, 'message', handleRequestWith(context, resolvedOptions));
|
|
510
|
-
const [, instance] = yield lib.until(() => getWorkerInstance(resolvedOptions.serviceWorker.url, resolvedOptions.serviceWorker.options));
|
|
531
|
+
const [, instance] = yield lib.until(() => getWorkerInstance(resolvedOptions.serviceWorker.url, resolvedOptions.serviceWorker.options, resolvedOptions.findWorker));
|
|
511
532
|
if (!instance) {
|
|
512
533
|
return null;
|
|
513
534
|
}
|
|
514
535
|
const [worker, registration] = instance;
|
|
515
536
|
if (!worker) {
|
|
537
|
+
if (options === null || options === void 0 ? void 0 : options.findWorker) {
|
|
538
|
+
console.error(`\
|
|
539
|
+
[MSW] Failed to locate the Service Worker registration using a custom "findWorker" predicate.
|
|
540
|
+
|
|
541
|
+
Please ensure that the custom predicate properly locates the Service Worker registration at "${resolvedOptions.serviceWorker.url}".
|
|
542
|
+
More details: https://mswjs.io/docs/api/setup-worker/start#findworker
|
|
543
|
+
`);
|
|
544
|
+
}
|
|
545
|
+
else {
|
|
546
|
+
console.error(`\
|
|
547
|
+
[MSW] Failed to locate the Service Worker registration.
|
|
548
|
+
|
|
549
|
+
This most likely means that the worker script URL "${resolvedOptions.serviceWorker.url}" cannot resolve against the actual public hostname (${location.host}). This may happen if your application runs behind a proxy, or has a dynamic hostname.
|
|
550
|
+
|
|
551
|
+
Please consider using a custom "serviceWorker.url" option to point to the actual worker script location, or a custom "findWorker" option to resolve the Service Worker registration manually. More details: https://mswjs.io/docs/api/setup-worker/start`);
|
|
552
|
+
}
|
|
516
553
|
return null;
|
|
517
554
|
}
|
|
518
555
|
context.worker = worker;
|
|
@@ -525,6 +562,9 @@ const createStart = (context) => {
|
|
|
525
562
|
// the Service Worker when there are no open clients.
|
|
526
563
|
worker.postMessage('CLIENT_CLOSED');
|
|
527
564
|
}
|
|
565
|
+
// Make sure we're always clearing the interval - there are reports that not doing this can
|
|
566
|
+
// cause memory leaks in headless browser environments.
|
|
567
|
+
window.clearInterval(context.keepAliveInterval);
|
|
528
568
|
});
|
|
529
569
|
// Check if the active Service Worker is the latest published one
|
|
530
570
|
const [integrityError] = yield lib.until(() => requestIntegrityCheck(context, worker));
|
|
@@ -546,6 +586,7 @@ If this message still persists after updating, please report an issue: https://g
|
|
|
546
586
|
console.error('Failed to enable mocking', activationError);
|
|
547
587
|
return null;
|
|
548
588
|
}
|
|
589
|
+
context.keepAliveInterval = window.setInterval(() => worker.postMessage('KEEPALIVE_REQUEST'), 5000);
|
|
549
590
|
return registration;
|
|
550
591
|
});
|
|
551
592
|
const workerRegistration = startWorkerInstance();
|
|
@@ -569,6 +610,7 @@ const createStop = (context) => {
|
|
|
569
610
|
var _a;
|
|
570
611
|
(_a = context.worker) === null || _a === void 0 ? void 0 : _a.postMessage('MOCK_DEACTIVATE');
|
|
571
612
|
context.events.removeAllListeners();
|
|
613
|
+
window.clearInterval(context.keepAliveInterval);
|
|
572
614
|
};
|
|
573
615
|
};
|
|
574
616
|
|
|
@@ -590,6 +632,10 @@ function resetHandlers(initialHandlers, ...nextHandlers) {
|
|
|
590
632
|
// so it persists between Fash refreshes of the application's code.
|
|
591
633
|
let listeners = [];
|
|
592
634
|
function setupWorker(...requestHandlers) {
|
|
635
|
+
requestHandlers.forEach((handler) => {
|
|
636
|
+
if (Array.isArray(handler))
|
|
637
|
+
throw new Error(`[MSW] Failed to call "setupWorker" given an Array of request handlers (setupWorker([a, b])), expected to receive each handler individually: setupWorker(a, b).`);
|
|
638
|
+
});
|
|
593
639
|
const context = {
|
|
594
640
|
worker: null,
|
|
595
641
|
registration: null,
|