msw 0.39.0 → 0.40.0

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.
@@ -52,7 +52,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
52
52
 
53
53
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
54
54
 
55
- var lib$3 = {exports: {}};
55
+ var lib$4 = {exports: {}};
56
56
 
57
57
  (function (module, exports) {
58
58
  (function (global, factory) {
@@ -75,9 +75,9 @@ var lib$3 = {exports: {}};
75
75
  Object.defineProperty(exports, '__esModule', { value: true });
76
76
 
77
77
  })));
78
- }(lib$3, lib$3.exports));
78
+ }(lib$4, lib$4.exports));
79
79
 
80
- var lib$2 = {};
80
+ var lib$3 = {};
81
81
 
82
82
  var StrictEventEmitter$1 = {};
83
83
 
@@ -147,7 +147,7 @@ exports.__esModule = true;
147
147
  exports.StrictEventEmitter = void 0;
148
148
  var StrictEventEmitter_1 = StrictEventEmitter$1;
149
149
  __createBinding(exports, StrictEventEmitter_1, "StrictEventEmitter");
150
- }(lib$2));
150
+ }(lib$3));
151
151
 
152
152
  function use(currentHandlers, ...handlers) {
153
153
  currentHandlers.unshift(...handlers);
@@ -161,221 +161,7 @@ function resetHandlers(initialHandlers, ...nextHandlers) {
161
161
  return nextHandlers.length > 0 ? [...nextHandlers] : [...initialHandlers];
162
162
  }
163
163
 
164
- /*!
165
- * cookie
166
- * Copyright(c) 2012-2014 Roman Shtylman
167
- * Copyright(c) 2015 Douglas Christopher Wilson
168
- * MIT Licensed
169
- */
170
-
171
- /**
172
- * Module exports.
173
- * @public
174
- */
175
-
176
- var parse_1 = parse$2;
177
- var serialize_1 = serialize;
178
-
179
- /**
180
- * Module variables.
181
- * @private
182
- */
183
-
184
- var decode = decodeURIComponent;
185
- var encode = encodeURIComponent;
186
-
187
- /**
188
- * RegExp to match field-content in RFC 7230 sec 3.2
189
- *
190
- * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
191
- * field-vchar = VCHAR / obs-text
192
- * obs-text = %x80-FF
193
- */
194
-
195
- var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
196
-
197
- /**
198
- * Parse a cookie header.
199
- *
200
- * Parse the given cookie header string into an object
201
- * The object has the various cookies as keys(names) => values
202
- *
203
- * @param {string} str
204
- * @param {object} [options]
205
- * @return {object}
206
- * @public
207
- */
208
-
209
- function parse$2(str, options) {
210
- if (typeof str !== 'string') {
211
- throw new TypeError('argument str must be a string');
212
- }
213
-
214
- var obj = {};
215
- var opt = options || {};
216
- var pairs = str.split(';');
217
- var dec = opt.decode || decode;
218
-
219
- for (var i = 0; i < pairs.length; i++) {
220
- var pair = pairs[i];
221
- var index = pair.indexOf('=');
222
-
223
- // skip things that don't look like key=value
224
- if (index < 0) {
225
- continue;
226
- }
227
-
228
- var key = pair.substring(0, index).trim();
229
-
230
- // only assign once
231
- if (undefined == obj[key]) {
232
- var val = pair.substring(index + 1, pair.length).trim();
233
-
234
- // quoted values
235
- if (val[0] === '"') {
236
- val = val.slice(1, -1);
237
- }
238
-
239
- obj[key] = tryDecode(val, dec);
240
- }
241
- }
242
-
243
- return obj;
244
- }
245
-
246
- /**
247
- * Serialize data into a cookie header.
248
- *
249
- * Serialize the a name value pair into a cookie string suitable for
250
- * http headers. An optional options object specified cookie parameters.
251
- *
252
- * serialize('foo', 'bar', { httpOnly: true })
253
- * => "foo=bar; httpOnly"
254
- *
255
- * @param {string} name
256
- * @param {string} val
257
- * @param {object} [options]
258
- * @return {string}
259
- * @public
260
- */
261
-
262
- function serialize(name, val, options) {
263
- var opt = options || {};
264
- var enc = opt.encode || encode;
265
-
266
- if (typeof enc !== 'function') {
267
- throw new TypeError('option encode is invalid');
268
- }
269
-
270
- if (!fieldContentRegExp.test(name)) {
271
- throw new TypeError('argument name is invalid');
272
- }
273
-
274
- var value = enc(val);
275
-
276
- if (value && !fieldContentRegExp.test(value)) {
277
- throw new TypeError('argument val is invalid');
278
- }
279
-
280
- var str = name + '=' + value;
281
-
282
- if (null != opt.maxAge) {
283
- var maxAge = opt.maxAge - 0;
284
-
285
- if (isNaN(maxAge) || !isFinite(maxAge)) {
286
- throw new TypeError('option maxAge is invalid')
287
- }
288
-
289
- str += '; Max-Age=' + Math.floor(maxAge);
290
- }
291
-
292
- if (opt.domain) {
293
- if (!fieldContentRegExp.test(opt.domain)) {
294
- throw new TypeError('option domain is invalid');
295
- }
296
-
297
- str += '; Domain=' + opt.domain;
298
- }
299
-
300
- if (opt.path) {
301
- if (!fieldContentRegExp.test(opt.path)) {
302
- throw new TypeError('option path is invalid');
303
- }
304
-
305
- str += '; Path=' + opt.path;
306
- }
307
-
308
- if (opt.expires) {
309
- if (typeof opt.expires.toUTCString !== 'function') {
310
- throw new TypeError('option expires is invalid');
311
- }
312
-
313
- str += '; Expires=' + opt.expires.toUTCString();
314
- }
315
-
316
- if (opt.httpOnly) {
317
- str += '; HttpOnly';
318
- }
319
-
320
- if (opt.secure) {
321
- str += '; Secure';
322
- }
323
-
324
- if (opt.sameSite) {
325
- var sameSite = typeof opt.sameSite === 'string'
326
- ? opt.sameSite.toLowerCase() : opt.sameSite;
327
-
328
- switch (sameSite) {
329
- case true:
330
- str += '; SameSite=Strict';
331
- break;
332
- case 'lax':
333
- str += '; SameSite=Lax';
334
- break;
335
- case 'strict':
336
- str += '; SameSite=Strict';
337
- break;
338
- case 'none':
339
- str += '; SameSite=None';
340
- break;
341
- default:
342
- throw new TypeError('option sameSite is invalid');
343
- }
344
- }
345
-
346
- return str;
347
- }
348
-
349
- /**
350
- * Try decoding a string using a decoding function.
351
- *
352
- * @param {string} str
353
- * @param {function} decode
354
- * @private
355
- */
356
-
357
- function tryDecode(str, decode) {
358
- try {
359
- return decode(str);
360
- } catch (e) {
361
- return str;
362
- }
363
- }
364
-
365
- /**
366
- * Parses a given value into a JSON.
367
- * Does not throw an exception on an invalid JSON string.
368
- */
369
- function jsonParse(value) {
370
- try {
371
- return JSON.parse(value);
372
- }
373
- catch (error) {
374
- return undefined;
375
- }
376
- }
377
-
378
- var lib$1 = {};
164
+ var lib$2 = {};
379
165
 
380
166
  var Headers = {};
381
167
 
@@ -902,46 +688,457 @@ var flattenHeadersList_1 = flattenHeadersList$1;
902
688
  Object.defineProperty(exports, "flattenHeadersList", { enumerable: true, get: function () { return flattenHeadersList_1.flattenHeadersList; } });
903
689
  var flattenHeadersObject_1 = flattenHeadersObject$1;
904
690
  Object.defineProperty(exports, "flattenHeadersObject", { enumerable: true, get: function () { return flattenHeadersObject_1.flattenHeadersObject; } });
905
- }(lib$1));
691
+ }(lib$2));
906
692
 
907
- function parseContentHeaders(headersString) {
908
- var _a, _b;
909
- const headers = lib$1.stringToHeaders(headersString);
910
- const contentType = headers.get('content-type') || 'text/plain';
911
- const disposition = headers.get('content-disposition');
912
- if (!disposition) {
913
- throw new Error('"Content-Disposition" header is required.');
914
- }
915
- const directives = disposition.split(';').reduce((acc, chunk) => {
916
- const [name, ...rest] = chunk.trim().split('=');
917
- acc[name] = rest.join('=');
918
- return acc;
919
- }, {});
920
- const name = (_a = directives.name) === null || _a === void 0 ? void 0 : _a.slice(1, -1);
921
- const filename = (_b = directives.filename) === null || _b === void 0 ? void 0 : _b.slice(1, -1);
922
- return {
923
- name,
924
- filename,
925
- contentType,
926
- };
927
- }
928
693
  /**
929
- * Parses a given string as a multipart/form-data.
930
- * Does not throw an exception on an invalid multipart string.
694
+ * Composes a given list of functions into a new function that
695
+ * executes from right to left.
931
696
  */
932
- function parseMultipartData(data, headers) {
933
- const contentType = headers === null || headers === void 0 ? void 0 : headers.get('content-type');
934
- if (!contentType) {
935
- return undefined;
936
- }
937
- const [, ...directives] = contentType.split(/; */);
938
- const boundary = directives
939
- .filter((d) => d.startsWith('boundary='))
940
- .map((s) => s.replace(/^boundary=/, ''))[0];
941
- if (!boundary) {
942
- return undefined;
943
- }
944
- const boundaryRegExp = new RegExp(`--+${boundary}`);
697
+ function compose(...fns) {
698
+ return (...args) => {
699
+ return fns.reduceRight((leftFn, rightFn) => {
700
+ return leftFn instanceof Promise
701
+ ? Promise.resolve(leftFn).then(rightFn)
702
+ : rightFn(leftFn);
703
+ }, args[0]);
704
+ };
705
+ }
706
+
707
+ class NetworkError extends Error {
708
+ constructor(message) {
709
+ super(message);
710
+ this.name = 'NetworkError';
711
+ }
712
+ }
713
+
714
+ const defaultResponse = {
715
+ status: 200,
716
+ statusText: 'OK',
717
+ body: null,
718
+ delay: 0,
719
+ once: false,
720
+ passthrough: false,
721
+ };
722
+ const defaultResponseTransformers = [];
723
+ function createResponseComposition(responseOverrides, defaultTransformers = defaultResponseTransformers) {
724
+ return (...transformers) => __awaiter(this, void 0, void 0, function* () {
725
+ const initialResponse = Object.assign({}, defaultResponse, {
726
+ headers: new lib$2.Headers({
727
+ 'x-powered-by': 'msw',
728
+ }),
729
+ }, responseOverrides);
730
+ const resolvedTransformers = [
731
+ ...defaultTransformers,
732
+ ...transformers,
733
+ ].filter(Boolean);
734
+ const resolvedResponse = resolvedTransformers.length > 0
735
+ ? compose(...resolvedTransformers)(initialResponse)
736
+ : initialResponse;
737
+ return resolvedResponse;
738
+ });
739
+ }
740
+ const response = Object.assign(createResponseComposition(), {
741
+ once: createResponseComposition({ once: true }),
742
+ networkError(message) {
743
+ throw new NetworkError(message);
744
+ },
745
+ });
746
+
747
+ const BUILD_FRAME = /(node_modules)?[\/\\]lib[\/\\](umd|esm|iief|cjs)[\/\\]|^[^\/\\]*$/;
748
+ /**
749
+ * Return the stack trace frame of a function's invocation.
750
+ */
751
+ function getCallFrame(error) {
752
+ // In <IE11, new Error may return an undefined stack
753
+ const stack = error.stack;
754
+ if (!stack) {
755
+ return;
756
+ }
757
+ const frames = stack.split('\n').slice(1);
758
+ // Get the first frame that doesn't reference the library's internal trace.
759
+ // Assume that frame is the invocation frame.
760
+ const declarationFrame = frames.find((frame) => {
761
+ return !BUILD_FRAME.test(frame);
762
+ });
763
+ if (!declarationFrame) {
764
+ return;
765
+ }
766
+ // Extract file reference from the stack frame.
767
+ const declarationPath = declarationFrame
768
+ .replace(/\s*at [^()]*\(([^)]+)\)/, '$1')
769
+ .replace(/^@/, '');
770
+ return declarationPath;
771
+ }
772
+
773
+ /**
774
+ * Determines if the given function is an iterator.
775
+ */
776
+ function isIterable(fn) {
777
+ if (!fn) {
778
+ return false;
779
+ }
780
+ return typeof fn[Symbol.iterator] == 'function';
781
+ }
782
+
783
+ var statuses = {
784
+ "100": "Continue",
785
+ "101": "Switching Protocols",
786
+ "102": "Processing",
787
+ "103": "Early Hints",
788
+ "200": "OK",
789
+ "201": "Created",
790
+ "202": "Accepted",
791
+ "203": "Non-Authoritative Information",
792
+ "204": "No Content",
793
+ "205": "Reset Content",
794
+ "206": "Partial Content",
795
+ "207": "Multi-Status",
796
+ "208": "Already Reported",
797
+ "226": "IM Used",
798
+ "300": "Multiple Choices",
799
+ "301": "Moved Permanently",
800
+ "302": "Found",
801
+ "303": "See Other",
802
+ "304": "Not Modified",
803
+ "305": "Use Proxy",
804
+ "307": "Temporary Redirect",
805
+ "308": "Permanent Redirect",
806
+ "400": "Bad Request",
807
+ "401": "Unauthorized",
808
+ "402": "Payment Required",
809
+ "403": "Forbidden",
810
+ "404": "Not Found",
811
+ "405": "Method Not Allowed",
812
+ "406": "Not Acceptable",
813
+ "407": "Proxy Authentication Required",
814
+ "408": "Request Timeout",
815
+ "409": "Conflict",
816
+ "410": "Gone",
817
+ "411": "Length Required",
818
+ "412": "Precondition Failed",
819
+ "413": "Payload Too Large",
820
+ "414": "URI Too Long",
821
+ "415": "Unsupported Media Type",
822
+ "416": "Range Not Satisfiable",
823
+ "417": "Expectation Failed",
824
+ "418": "I'm a Teapot",
825
+ "421": "Misdirected Request",
826
+ "422": "Unprocessable Entity",
827
+ "423": "Locked",
828
+ "424": "Failed Dependency",
829
+ "425": "Too Early",
830
+ "426": "Upgrade Required",
831
+ "428": "Precondition Required",
832
+ "429": "Too Many Requests",
833
+ "431": "Request Header Fields Too Large",
834
+ "451": "Unavailable For Legal Reasons",
835
+ "500": "Internal Server Error",
836
+ "501": "Not Implemented",
837
+ "502": "Bad Gateway",
838
+ "503": "Service Unavailable",
839
+ "504": "Gateway Timeout",
840
+ "505": "HTTP Version Not Supported",
841
+ "506": "Variant Also Negotiates",
842
+ "507": "Insufficient Storage",
843
+ "508": "Loop Detected",
844
+ "509": "Bandwidth Limit Exceeded",
845
+ "510": "Not Extended",
846
+ "511": "Network Authentication Required"
847
+ };
848
+
849
+ /**
850
+ * Sets a response status code and text.
851
+ * @example
852
+ * res(ctx.status(301))
853
+ * res(ctx.status(400, 'Custom status text'))
854
+ * @see {@link https://mswjs.io/docs/api/context/status `ctx.status()`}
855
+ */
856
+ const status = (statusCode, statusText) => {
857
+ return (res) => {
858
+ res.status = statusCode;
859
+ res.statusText =
860
+ statusText || statuses[String(statusCode)];
861
+ return res;
862
+ };
863
+ };
864
+
865
+ /**
866
+ * Sets one or multiple response headers.
867
+ * @example
868
+ * ctx.set('Content-Type', 'text/plain')
869
+ * ctx.set({
870
+ * 'Accept': 'application/javascript',
871
+ * 'Content-Type': "text/plain"
872
+ * })
873
+ * @see {@link https://mswjs.io/docs/api/context/set `ctx.set()`}
874
+ */
875
+ function set(...args) {
876
+ return (res) => {
877
+ const [name, value] = args;
878
+ if (typeof name === 'string') {
879
+ res.headers.append(name, value);
880
+ }
881
+ else {
882
+ const headers = lib$2.objectToHeaders(name);
883
+ headers.forEach((value, name) => {
884
+ res.headers.append(name, value);
885
+ });
886
+ }
887
+ return res;
888
+ };
889
+ }
890
+
891
+ const SET_TIMEOUT_MAX_ALLOWED_INT = 2147483647;
892
+ const MIN_SERVER_RESPONSE_TIME = 100;
893
+ const MAX_SERVER_RESPONSE_TIME = 400;
894
+ const NODE_SERVER_RESPONSE_TIME = 5;
895
+ const getRandomServerResponseTime = () => {
896
+ if (lib$4.exports.isNodeProcess()) {
897
+ return NODE_SERVER_RESPONSE_TIME;
898
+ }
899
+ return Math.floor(Math.random() * (MAX_SERVER_RESPONSE_TIME - MIN_SERVER_RESPONSE_TIME) +
900
+ MIN_SERVER_RESPONSE_TIME);
901
+ };
902
+ /**
903
+ * Delays the response by the given duration (ms).
904
+ * @example
905
+ * res(ctx.delay(1200)) // delay response by 1200ms
906
+ * res(ctx.delay()) // emulate realistic server response time
907
+ * res(ctx.delay('infinite')) // delay response infinitely
908
+ * @see {@link https://mswjs.io/docs/api/context/delay `ctx.delay()`}
909
+ */
910
+ const delay = (durationOrMode) => {
911
+ return (res) => {
912
+ let delayTime;
913
+ if (typeof durationOrMode === 'string') {
914
+ switch (durationOrMode) {
915
+ case 'infinite': {
916
+ // Using `Infinity` as a delay value executes the response timeout immediately.
917
+ // Instead, use the maximum allowed integer for `setTimeout`.
918
+ delayTime = SET_TIMEOUT_MAX_ALLOWED_INT;
919
+ break;
920
+ }
921
+ case 'real': {
922
+ delayTime = getRandomServerResponseTime();
923
+ break;
924
+ }
925
+ default: {
926
+ throw new Error(`Failed to delay a response: unknown delay mode "${durationOrMode}". Please make sure you provide one of the supported modes ("real", "infinite") or a number to "ctx.delay".`);
927
+ }
928
+ }
929
+ }
930
+ else if (typeof durationOrMode === 'undefined') {
931
+ // Use random realistic server response time when no explicit delay duration was provided.
932
+ delayTime = getRandomServerResponseTime();
933
+ }
934
+ else {
935
+ // Guard against passing values like `Infinity` or `Number.MAX_VALUE`
936
+ // as the response delay duration. They don't produce the result you may expect.
937
+ if (durationOrMode > SET_TIMEOUT_MAX_ALLOWED_INT) {
938
+ throw new Error(`Failed to delay a response: provided delay duration (${durationOrMode}) exceeds the maximum allowed duration for "setTimeout" (${SET_TIMEOUT_MAX_ALLOWED_INT}). This will cause the response to be returned immediately. Please use a number within the allowed range to delay the response by exact duration, or consider the "infinite" delay mode to delay the response indefinitely.`);
939
+ }
940
+ delayTime = durationOrMode;
941
+ }
942
+ res.delay = delayTime;
943
+ return res;
944
+ };
945
+ };
946
+
947
+ const useFetch = lib$4.exports.isNodeProcess() ? require('node-fetch') : window.fetch;
948
+ const augmentRequestInit = (requestInit) => {
949
+ const headers = new lib$2.Headers(requestInit.headers);
950
+ headers.set('x-msw-bypass', 'true');
951
+ return Object.assign(Object.assign({}, requestInit), { headers: headers.all() });
952
+ };
953
+ const createFetchRequestParameters = (input) => {
954
+ const { body, method } = input;
955
+ const requestParameters = Object.assign(Object.assign({}, input), { body: undefined });
956
+ if (['GET', 'HEAD'].includes(method)) {
957
+ return requestParameters;
958
+ }
959
+ if (typeof body === 'object' ||
960
+ typeof body === 'number' ||
961
+ typeof body === 'boolean') {
962
+ requestParameters.body = JSON.stringify(body);
963
+ }
964
+ else {
965
+ requestParameters.body = body;
966
+ }
967
+ return requestParameters;
968
+ };
969
+ /**
970
+ * Performs a bypassed request inside a request handler.
971
+ * @example
972
+ * const originalResponse = await ctx.fetch(req)
973
+ * @see {@link https://mswjs.io/docs/api/context/fetch `ctx.fetch()`}
974
+ */
975
+ const fetch = (input, requestInit = {}) => {
976
+ if (typeof input === 'string') {
977
+ return useFetch(input, augmentRequestInit(requestInit));
978
+ }
979
+ const requestParameters = createFetchRequestParameters(input);
980
+ const derivedRequestInit = augmentRequestInit(requestParameters);
981
+ return useFetch(input.url.href, derivedRequestInit);
982
+ };
983
+
984
+ const defaultContext = {
985
+ status,
986
+ set,
987
+ delay,
988
+ fetch,
989
+ };
990
+ class RequestHandler {
991
+ constructor(options) {
992
+ this.shouldSkip = false;
993
+ this.ctx = options.ctx || defaultContext;
994
+ this.resolver = options.resolver;
995
+ const callFrame = getCallFrame(new Error());
996
+ this.info = Object.assign(Object.assign({}, options.info), { callFrame });
997
+ }
998
+ /**
999
+ * Parse the captured request to extract additional information from it.
1000
+ * Parsed result is then exposed to other methods of this request handler.
1001
+ */
1002
+ parse(_request, _resolutionContext) {
1003
+ return null;
1004
+ }
1005
+ /**
1006
+ * Test if this handler matches the given request.
1007
+ */
1008
+ test(request, resolutionContext) {
1009
+ return this.predicate(request, this.parse(request, resolutionContext), resolutionContext);
1010
+ }
1011
+ /**
1012
+ * Derive the publicly exposed request (`req`) instance of the response resolver
1013
+ * from the captured request and its parsed result.
1014
+ */
1015
+ getPublicRequest(request, _parsedResult) {
1016
+ return request;
1017
+ }
1018
+ markAsSkipped(shouldSkip = true) {
1019
+ this.shouldSkip = shouldSkip;
1020
+ }
1021
+ /**
1022
+ * Execute this request handler and produce a mocked response
1023
+ * using the given resolver function.
1024
+ */
1025
+ run(request, resolutionContext) {
1026
+ return __awaiter(this, void 0, void 0, function* () {
1027
+ if (this.shouldSkip) {
1028
+ return null;
1029
+ }
1030
+ const parsedResult = this.parse(request, resolutionContext);
1031
+ const shouldIntercept = this.predicate(request, parsedResult, resolutionContext);
1032
+ if (!shouldIntercept) {
1033
+ return null;
1034
+ }
1035
+ const publicRequest = this.getPublicRequest(request, parsedResult);
1036
+ // Create a response extraction wrapper around the resolver
1037
+ // since it can be both an async function and a generator.
1038
+ const executeResolver = this.wrapResolver(this.resolver);
1039
+ const mockedResponse = yield executeResolver(publicRequest, response, this.ctx);
1040
+ return this.createExecutionResult(parsedResult, publicRequest, mockedResponse);
1041
+ });
1042
+ }
1043
+ wrapResolver(resolver) {
1044
+ return (req, res, ctx) => __awaiter(this, void 0, void 0, function* () {
1045
+ const result = this.resolverGenerator || (yield resolver(req, res, ctx));
1046
+ if (isIterable(result)) {
1047
+ const { value, done } = result[Symbol.iterator]().next();
1048
+ const nextResponse = yield value;
1049
+ // If the generator is done and there is no next value,
1050
+ // return the previous generator's value.
1051
+ if (!nextResponse && done) {
1052
+ return this.resolverGeneratorResult;
1053
+ }
1054
+ if (!this.resolverGenerator) {
1055
+ this.resolverGenerator = result;
1056
+ }
1057
+ this.resolverGeneratorResult = nextResponse;
1058
+ return nextResponse;
1059
+ }
1060
+ return result;
1061
+ });
1062
+ }
1063
+ createExecutionResult(parsedResult, request, response) {
1064
+ return {
1065
+ handler: this,
1066
+ parsedResult: parsedResult || null,
1067
+ request,
1068
+ response: response || null,
1069
+ };
1070
+ }
1071
+ }
1072
+ /**
1073
+ * Bypass this intercepted request.
1074
+ * This will make a call to the actual endpoint requested.
1075
+ */
1076
+ function passthrough() {
1077
+ // Constructing a dummy "101 Continue" mocked response
1078
+ // to keep the return type of the resolver consistent.
1079
+ return {
1080
+ status: 101,
1081
+ statusText: 'Continue',
1082
+ headers: new lib$2.Headers(),
1083
+ body: null,
1084
+ // Setting "passthrough" to true will signal the response pipeline
1085
+ // to perform this intercepted request as-is.
1086
+ passthrough: true,
1087
+ once: false,
1088
+ };
1089
+ }
1090
+
1091
+ /**
1092
+ * Parses a given value into a JSON.
1093
+ * Does not throw an exception on an invalid JSON string.
1094
+ */
1095
+ function jsonParse(value) {
1096
+ try {
1097
+ return JSON.parse(value);
1098
+ }
1099
+ catch (error) {
1100
+ return undefined;
1101
+ }
1102
+ }
1103
+
1104
+ function parseContentHeaders(headersString) {
1105
+ var _a, _b;
1106
+ const headers = lib$2.stringToHeaders(headersString);
1107
+ const contentType = headers.get('content-type') || 'text/plain';
1108
+ const disposition = headers.get('content-disposition');
1109
+ if (!disposition) {
1110
+ throw new Error('"Content-Disposition" header is required.');
1111
+ }
1112
+ const directives = disposition.split(';').reduce((acc, chunk) => {
1113
+ const [name, ...rest] = chunk.trim().split('=');
1114
+ acc[name] = rest.join('=');
1115
+ return acc;
1116
+ }, {});
1117
+ const name = (_a = directives.name) === null || _a === void 0 ? void 0 : _a.slice(1, -1);
1118
+ const filename = (_b = directives.filename) === null || _b === void 0 ? void 0 : _b.slice(1, -1);
1119
+ return {
1120
+ name,
1121
+ filename,
1122
+ contentType,
1123
+ };
1124
+ }
1125
+ /**
1126
+ * Parses a given string as a multipart/form-data.
1127
+ * Does not throw an exception on an invalid multipart string.
1128
+ */
1129
+ function parseMultipartData(data, headers) {
1130
+ const contentType = headers === null || headers === void 0 ? void 0 : headers.get('content-type');
1131
+ if (!contentType) {
1132
+ return undefined;
1133
+ }
1134
+ const [, ...directives] = contentType.split(/; */);
1135
+ const boundary = directives
1136
+ .filter((d) => d.startsWith('boundary='))
1137
+ .map((s) => s.replace(/^boundary=/, ''))[0];
1138
+ if (!boundary) {
1139
+ return undefined;
1140
+ }
1141
+ const boundaryRegExp = new RegExp(`--+${boundary}`);
945
1142
  const fields = data
946
1143
  .split(boundaryRegExp)
947
1144
  .filter((chunk) => chunk.startsWith('\r\n') && chunk.endsWith('\r\n'))
@@ -976,30 +1173,231 @@ function parseMultipartData(data, headers) {
976
1173
  }
977
1174
  }
978
1175
 
979
- /**
980
- * Parses a given request/response body based on the "Content-Type" header.
981
- */
982
- function parseBody(body, headers) {
983
- var _a;
984
- // Return whatever falsey body value is given.
985
- if (!body) {
986
- return body;
987
- }
988
- const contentType = ((_a = headers === null || headers === void 0 ? void 0 : headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
989
- // If the body has a Multipart Content-Type
990
- // parse it into an object.
991
- const hasMultipartContent = contentType.startsWith('multipart/form-data');
992
- if (hasMultipartContent && typeof body !== 'object') {
993
- return parseMultipartData(body.toString(), headers) || body;
994
- }
995
- // If the intercepted request's body has a JSON Content-Type
996
- // parse it into an object.
997
- const hasJsonContent = contentType.includes('json');
998
- if (hasJsonContent && typeof body !== 'object') {
999
- return jsonParse(body.toString()) || body;
1000
- }
1001
- // Otherwise leave as-is.
1002
- return body;
1176
+ /**
1177
+ * Parses a given request/response body based on the "Content-Type" header.
1178
+ */
1179
+ function parseBody(body, headers) {
1180
+ var _a;
1181
+ // Return whatever falsey body value is given.
1182
+ if (!body) {
1183
+ return body;
1184
+ }
1185
+ const contentType = ((_a = headers === null || headers === void 0 ? void 0 : headers.get('content-type')) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
1186
+ // If the body has a Multipart Content-Type
1187
+ // parse it into an object.
1188
+ const hasMultipartContent = contentType.startsWith('multipart/form-data');
1189
+ if (hasMultipartContent && typeof body !== 'object') {
1190
+ return parseMultipartData(body.toString(), headers) || body;
1191
+ }
1192
+ // If the intercepted request's body has a JSON Content-Type
1193
+ // parse it into an object.
1194
+ const hasJsonContent = contentType.includes('json');
1195
+ if (hasJsonContent && typeof body !== 'object') {
1196
+ return jsonParse(body.toString()) || body;
1197
+ }
1198
+ // Otherwise leave as-is.
1199
+ return body;
1200
+ }
1201
+
1202
+ /*!
1203
+ * cookie
1204
+ * Copyright(c) 2012-2014 Roman Shtylman
1205
+ * Copyright(c) 2015 Douglas Christopher Wilson
1206
+ * MIT Licensed
1207
+ */
1208
+
1209
+ /**
1210
+ * Module exports.
1211
+ * @public
1212
+ */
1213
+
1214
+ var parse_1 = parse$2;
1215
+ var serialize_1 = serialize;
1216
+
1217
+ /**
1218
+ * Module variables.
1219
+ * @private
1220
+ */
1221
+
1222
+ var decode = decodeURIComponent;
1223
+ var encode = encodeURIComponent;
1224
+
1225
+ /**
1226
+ * RegExp to match field-content in RFC 7230 sec 3.2
1227
+ *
1228
+ * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
1229
+ * field-vchar = VCHAR / obs-text
1230
+ * obs-text = %x80-FF
1231
+ */
1232
+
1233
+ var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
1234
+
1235
+ /**
1236
+ * Parse a cookie header.
1237
+ *
1238
+ * Parse the given cookie header string into an object
1239
+ * The object has the various cookies as keys(names) => values
1240
+ *
1241
+ * @param {string} str
1242
+ * @param {object} [options]
1243
+ * @return {object}
1244
+ * @public
1245
+ */
1246
+
1247
+ function parse$2(str, options) {
1248
+ if (typeof str !== 'string') {
1249
+ throw new TypeError('argument str must be a string');
1250
+ }
1251
+
1252
+ var obj = {};
1253
+ var opt = options || {};
1254
+ var pairs = str.split(';');
1255
+ var dec = opt.decode || decode;
1256
+
1257
+ for (var i = 0; i < pairs.length; i++) {
1258
+ var pair = pairs[i];
1259
+ var index = pair.indexOf('=');
1260
+
1261
+ // skip things that don't look like key=value
1262
+ if (index < 0) {
1263
+ continue;
1264
+ }
1265
+
1266
+ var key = pair.substring(0, index).trim();
1267
+
1268
+ // only assign once
1269
+ if (undefined == obj[key]) {
1270
+ var val = pair.substring(index + 1, pair.length).trim();
1271
+
1272
+ // quoted values
1273
+ if (val[0] === '"') {
1274
+ val = val.slice(1, -1);
1275
+ }
1276
+
1277
+ obj[key] = tryDecode(val, dec);
1278
+ }
1279
+ }
1280
+
1281
+ return obj;
1282
+ }
1283
+
1284
+ /**
1285
+ * Serialize data into a cookie header.
1286
+ *
1287
+ * Serialize the a name value pair into a cookie string suitable for
1288
+ * http headers. An optional options object specified cookie parameters.
1289
+ *
1290
+ * serialize('foo', 'bar', { httpOnly: true })
1291
+ * => "foo=bar; httpOnly"
1292
+ *
1293
+ * @param {string} name
1294
+ * @param {string} val
1295
+ * @param {object} [options]
1296
+ * @return {string}
1297
+ * @public
1298
+ */
1299
+
1300
+ function serialize(name, val, options) {
1301
+ var opt = options || {};
1302
+ var enc = opt.encode || encode;
1303
+
1304
+ if (typeof enc !== 'function') {
1305
+ throw new TypeError('option encode is invalid');
1306
+ }
1307
+
1308
+ if (!fieldContentRegExp.test(name)) {
1309
+ throw new TypeError('argument name is invalid');
1310
+ }
1311
+
1312
+ var value = enc(val);
1313
+
1314
+ if (value && !fieldContentRegExp.test(value)) {
1315
+ throw new TypeError('argument val is invalid');
1316
+ }
1317
+
1318
+ var str = name + '=' + value;
1319
+
1320
+ if (null != opt.maxAge) {
1321
+ var maxAge = opt.maxAge - 0;
1322
+
1323
+ if (isNaN(maxAge) || !isFinite(maxAge)) {
1324
+ throw new TypeError('option maxAge is invalid')
1325
+ }
1326
+
1327
+ str += '; Max-Age=' + Math.floor(maxAge);
1328
+ }
1329
+
1330
+ if (opt.domain) {
1331
+ if (!fieldContentRegExp.test(opt.domain)) {
1332
+ throw new TypeError('option domain is invalid');
1333
+ }
1334
+
1335
+ str += '; Domain=' + opt.domain;
1336
+ }
1337
+
1338
+ if (opt.path) {
1339
+ if (!fieldContentRegExp.test(opt.path)) {
1340
+ throw new TypeError('option path is invalid');
1341
+ }
1342
+
1343
+ str += '; Path=' + opt.path;
1344
+ }
1345
+
1346
+ if (opt.expires) {
1347
+ if (typeof opt.expires.toUTCString !== 'function') {
1348
+ throw new TypeError('option expires is invalid');
1349
+ }
1350
+
1351
+ str += '; Expires=' + opt.expires.toUTCString();
1352
+ }
1353
+
1354
+ if (opt.httpOnly) {
1355
+ str += '; HttpOnly';
1356
+ }
1357
+
1358
+ if (opt.secure) {
1359
+ str += '; Secure';
1360
+ }
1361
+
1362
+ if (opt.sameSite) {
1363
+ var sameSite = typeof opt.sameSite === 'string'
1364
+ ? opt.sameSite.toLowerCase() : opt.sameSite;
1365
+
1366
+ switch (sameSite) {
1367
+ case true:
1368
+ str += '; SameSite=Strict';
1369
+ break;
1370
+ case 'lax':
1371
+ str += '; SameSite=Lax';
1372
+ break;
1373
+ case 'strict':
1374
+ str += '; SameSite=Strict';
1375
+ break;
1376
+ case 'none':
1377
+ str += '; SameSite=None';
1378
+ break;
1379
+ default:
1380
+ throw new TypeError('option sameSite is invalid');
1381
+ }
1382
+ }
1383
+
1384
+ return str;
1385
+ }
1386
+
1387
+ /**
1388
+ * Try decoding a string using a decoding function.
1389
+ *
1390
+ * @param {string} str
1391
+ * @param {function} decode
1392
+ * @private
1393
+ */
1394
+
1395
+ function tryDecode(str, decode) {
1396
+ try {
1397
+ return decode(str);
1398
+ } catch (e) {
1399
+ return str;
1400
+ }
1003
1401
  }
1004
1402
 
1005
1403
  function getAllCookies() {
@@ -1031,13 +1429,36 @@ function getRequestCookies(request) {
1031
1429
  }
1032
1430
  }
1033
1431
 
1432
+ /**
1433
+ * Sets relevant cookies on the request.
1434
+ * Request cookies are taken from the following sources:
1435
+ * - Immediate (own) request cookies (those in the "Cookie" request header);
1436
+ * - From the `document.cookie` based on the request's `credentials` value;
1437
+ * - From the internal cookie store that persists/hydrates cookies in Node.js
1438
+ */
1034
1439
  function setRequestCookies(request) {
1035
1440
  var _a;
1441
+ // Set mocked request cookies from the `cookie` header of the original request.
1442
+ // No need to take `credentials` into account, because in Node.js requests are intercepted
1443
+ // _after_ they happen. Request issuer should have already taken care of sending relevant cookies.
1444
+ // Unlike browser, where interception is on the worker level, _before_ the request happens.
1445
+ const requestCookiesString = request.headers.get('cookie');
1036
1446
  cookies.store.hydrate();
1037
- request.cookies = Object.assign(Object.assign({}, getRequestCookies(request)), Array.from((_a = cookies.store.get(Object.assign(Object.assign({}, request), { url: request.url.toString() }))) === null || _a === void 0 ? void 0 : _a.entries()).reduce((cookies, [name, { value }]) => Object.assign(cookies, { [name]: value }), {}));
1038
- request.headers.set('cookie', Object.entries(request.cookies)
1039
- .map(([name, value]) => `${name}=${value}`)
1040
- .join('; '));
1447
+ const cookiesFromStore = Array.from((_a = cookies.store.get(Object.assign(Object.assign({}, request), { url: request.url.toString() }))) === null || _a === void 0 ? void 0 : _a.entries()).reduce((cookies, [name, { value }]) => {
1448
+ return Object.assign(cookies, { [name.trim()]: value });
1449
+ }, {});
1450
+ const cookiesFromDocument = getRequestCookies(request);
1451
+ const forwardedCookies = Object.assign(Object.assign({}, cookiesFromDocument), cookiesFromStore);
1452
+ // Ensure the persisted (document) cookies are propagated to the request.
1453
+ // Propagated the cookies persisted in the Cookuie Store to the request headers.
1454
+ // This forwards relevant request cookies based on the request's credentials.
1455
+ for (const [name, value] of Object.entries(forwardedCookies)) {
1456
+ request.headers.append('cookie', `${name}=${value}`);
1457
+ }
1458
+ const ownCookies = requestCookiesString
1459
+ ? parse_1(requestCookiesString)
1460
+ : {};
1461
+ request.cookies = Object.assign(Object.assign(Object.assign({}, request.cookies), forwardedCookies), ownCookies);
1041
1462
  }
1042
1463
 
1043
1464
  /**
@@ -1049,6 +1470,7 @@ function parseIsomorphicRequest(request) {
1049
1470
  url: request.url,
1050
1471
  method: request.method,
1051
1472
  body: parseBody(request.body, request.headers),
1473
+ credentials: request.credentials || 'same-origin',
1052
1474
  headers: request.headers,
1053
1475
  cookies: {},
1054
1476
  redirect: 'manual',
@@ -1060,24 +1482,39 @@ function parseIsomorphicRequest(request) {
1060
1482
  integrity: '',
1061
1483
  destination: 'document',
1062
1484
  bodyUsed: false,
1063
- credentials: 'same-origin',
1485
+ passthrough,
1064
1486
  };
1065
- // Set mocked request cookies from the `cookie` header of the original request.
1066
- // No need to take `credentials` into account, because in Node.js requests are intercepted
1067
- // _after_ they happen. Request issuer should have already taken care of sending relevant cookies.
1068
- // Unlike browser, where interception is on the worker level, _before_ the request happens.
1069
- const requestCookiesString = request.headers.get('cookie');
1070
1487
  // Attach all the cookies from the virtual cookie store.
1071
1488
  setRequestCookies(mockedRequest);
1072
- const requestCookies = requestCookiesString
1073
- ? parse_1(requestCookiesString)
1074
- : {};
1075
- // Merge both direct request cookies and the cookies inherited
1076
- // from other same-origin requests in the cookie store.
1077
- mockedRequest.cookies = Object.assign(Object.assign({}, mockedRequest.cookies), requestCookies);
1078
1489
  return mockedRequest;
1079
1490
  }
1080
1491
 
1492
+ var lib$1 = {};
1493
+
1494
+ var until$1 = {};
1495
+
1496
+ Object.defineProperty(until$1, "__esModule", { value: true });
1497
+ /**
1498
+ * Gracefully handles a given Promise factory.
1499
+ * @example
1500
+ * cosnt [error, data] = await until(() => asyncAction())
1501
+ */
1502
+ until$1.until = async (promise) => {
1503
+ try {
1504
+ const data = await promise().catch((error) => {
1505
+ throw error;
1506
+ });
1507
+ return [null, data];
1508
+ }
1509
+ catch (error) {
1510
+ return [error, null];
1511
+ }
1512
+ };
1513
+
1514
+ Object.defineProperty(lib$1, "__esModule", { value: true });
1515
+ var until_1 = until$1;
1516
+ var until = lib$1.until = until_1.until;
1517
+
1081
1518
  /**
1082
1519
  * Returns a mocked response for a given request using following request handlers.
1083
1520
  */
@@ -4816,114 +5253,6 @@ function isStringEqual(actual, expected) {
4816
5253
  return actual.toLowerCase() === expected.toLowerCase();
4817
5254
  }
4818
5255
 
4819
- var statuses = {
4820
- "100": "Continue",
4821
- "101": "Switching Protocols",
4822
- "102": "Processing",
4823
- "103": "Early Hints",
4824
- "200": "OK",
4825
- "201": "Created",
4826
- "202": "Accepted",
4827
- "203": "Non-Authoritative Information",
4828
- "204": "No Content",
4829
- "205": "Reset Content",
4830
- "206": "Partial Content",
4831
- "207": "Multi-Status",
4832
- "208": "Already Reported",
4833
- "226": "IM Used",
4834
- "300": "Multiple Choices",
4835
- "301": "Moved Permanently",
4836
- "302": "Found",
4837
- "303": "See Other",
4838
- "304": "Not Modified",
4839
- "305": "Use Proxy",
4840
- "307": "Temporary Redirect",
4841
- "308": "Permanent Redirect",
4842
- "400": "Bad Request",
4843
- "401": "Unauthorized",
4844
- "402": "Payment Required",
4845
- "403": "Forbidden",
4846
- "404": "Not Found",
4847
- "405": "Method Not Allowed",
4848
- "406": "Not Acceptable",
4849
- "407": "Proxy Authentication Required",
4850
- "408": "Request Timeout",
4851
- "409": "Conflict",
4852
- "410": "Gone",
4853
- "411": "Length Required",
4854
- "412": "Precondition Failed",
4855
- "413": "Payload Too Large",
4856
- "414": "URI Too Long",
4857
- "415": "Unsupported Media Type",
4858
- "416": "Range Not Satisfiable",
4859
- "417": "Expectation Failed",
4860
- "418": "I'm a Teapot",
4861
- "421": "Misdirected Request",
4862
- "422": "Unprocessable Entity",
4863
- "423": "Locked",
4864
- "424": "Failed Dependency",
4865
- "425": "Too Early",
4866
- "426": "Upgrade Required",
4867
- "428": "Precondition Required",
4868
- "429": "Too Many Requests",
4869
- "431": "Request Header Fields Too Large",
4870
- "451": "Unavailable For Legal Reasons",
4871
- "500": "Internal Server Error",
4872
- "501": "Not Implemented",
4873
- "502": "Bad Gateway",
4874
- "503": "Service Unavailable",
4875
- "504": "Gateway Timeout",
4876
- "505": "HTTP Version Not Supported",
4877
- "506": "Variant Also Negotiates",
4878
- "507": "Insufficient Storage",
4879
- "508": "Loop Detected",
4880
- "509": "Bandwidth Limit Exceeded",
4881
- "510": "Not Extended",
4882
- "511": "Network Authentication Required"
4883
- };
4884
-
4885
- /**
4886
- * Sets a response status code and text.
4887
- * @example
4888
- * res(ctx.status(301))
4889
- * res(ctx.status(400, 'Custom status text'))
4890
- * @see {@link https://mswjs.io/docs/api/context/status `ctx.status()`}
4891
- */
4892
- const status = (statusCode, statusText) => {
4893
- return (res) => {
4894
- res.status = statusCode;
4895
- res.statusText =
4896
- statusText || statuses[String(statusCode)];
4897
- return res;
4898
- };
4899
- };
4900
-
4901
- /**
4902
- * Sets one or multiple response headers.
4903
- * @example
4904
- * ctx.set('Content-Type', 'text/plain')
4905
- * ctx.set({
4906
- * 'Accept': 'application/javascript',
4907
- * 'Content-Type': "text/plain"
4908
- * })
4909
- * @see {@link https://mswjs.io/docs/api/context/set `ctx.set()`}
4910
- */
4911
- function set(...args) {
4912
- return (res) => {
4913
- const [name, value] = args;
4914
- if (typeof name === 'string') {
4915
- res.headers.append(name, value);
4916
- }
4917
- else {
4918
- const headers = lib$1.objectToHeaders(name);
4919
- headers.forEach((value, name) => {
4920
- res.headers.append(name, value);
4921
- });
4922
- }
4923
- return res;
4924
- };
4925
- }
4926
-
4927
5256
  /**
4928
5257
  * Sets a given cookie on the mocked response.
4929
5258
  * @example res(ctx.cookie('name', 'value'))
@@ -4993,95 +5322,39 @@ function mergeRight(left, right) {
4993
5322
  const json = (body) => {
4994
5323
  return (res) => {
4995
5324
  res.headers.set('Content-Type', 'application/json');
4996
- res.body = JSON.stringify(body);
4997
- return res;
4998
- };
4999
- };
5000
-
5001
- /**
5002
- * Sets a given payload as a GraphQL response body.
5003
- * @example
5004
- * res(ctx.data({ user: { firstName: 'John' }}))
5005
- * @see {@link https://mswjs.io/docs/api/context/data `ctx.data()`}
5006
- */
5007
- const data = (payload) => {
5008
- return (res) => {
5009
- const prevBody = jsonParse(res.body) || {};
5010
- const nextBody = mergeRight(prevBody, { data: payload });
5011
- return json(nextBody)(res);
5012
- };
5013
- };
5014
-
5015
- /**
5016
- * Sets the GraphQL extensions on a given response.
5017
- * @example
5018
- * res(ctx.extensions({ tracing: { version: 1 }}))
5019
- * @see {@link https://mswjs.io/docs/api/context/extensions `ctx.extensions()`}
5020
- */
5021
- const extensions = (payload) => {
5022
- return (res) => {
5023
- const prevBody = jsonParse(res.body) || {};
5024
- const nextBody = mergeRight(prevBody, { extensions: payload });
5025
- return json(nextBody)(res);
5026
- };
5027
- };
5028
-
5029
- const SET_TIMEOUT_MAX_ALLOWED_INT = 2147483647;
5030
- const MIN_SERVER_RESPONSE_TIME = 100;
5031
- const MAX_SERVER_RESPONSE_TIME = 400;
5032
- const NODE_SERVER_RESPONSE_TIME = 5;
5033
- const getRandomServerResponseTime = () => {
5034
- if (lib$3.exports.isNodeProcess()) {
5035
- return NODE_SERVER_RESPONSE_TIME;
5036
- }
5037
- return Math.floor(Math.random() * (MAX_SERVER_RESPONSE_TIME - MIN_SERVER_RESPONSE_TIME) +
5038
- MIN_SERVER_RESPONSE_TIME);
5039
- };
5040
- /**
5041
- * Delays the response by the given duration (ms).
5042
- * @example
5043
- * res(ctx.delay(1200)) // delay response by 1200ms
5044
- * res(ctx.delay()) // emulate realistic server response time
5045
- * res(ctx.delay('infinite')) // delay response infinitely
5046
- * @see {@link https://mswjs.io/docs/api/context/delay `ctx.delay()`}
5047
- */
5048
- const delay = (durationOrMode) => {
5049
- return (res) => {
5050
- let delayTime;
5051
- if (typeof durationOrMode === 'string') {
5052
- switch (durationOrMode) {
5053
- case 'infinite': {
5054
- // Using `Infinity` as a delay value executes the response timeout immediately.
5055
- // Instead, use the maximum allowed integer for `setTimeout`.
5056
- delayTime = SET_TIMEOUT_MAX_ALLOWED_INT;
5057
- break;
5058
- }
5059
- case 'real': {
5060
- delayTime = getRandomServerResponseTime();
5061
- break;
5062
- }
5063
- default: {
5064
- throw new Error(`Failed to delay a response: unknown delay mode "${durationOrMode}". Please make sure you provide one of the supported modes ("real", "infinite") or a number to "ctx.delay".`);
5065
- }
5066
- }
5067
- }
5068
- else if (typeof durationOrMode === 'undefined') {
5069
- // Use random realistic server response time when no explicit delay duration was provided.
5070
- delayTime = getRandomServerResponseTime();
5071
- }
5072
- else {
5073
- // Guard against passing values like `Infinity` or `Number.MAX_VALUE`
5074
- // as the response delay duration. They don't produce the result you may expect.
5075
- if (durationOrMode > SET_TIMEOUT_MAX_ALLOWED_INT) {
5076
- throw new Error(`Failed to delay a response: provided delay duration (${durationOrMode}) exceeds the maximum allowed duration for "setTimeout" (${SET_TIMEOUT_MAX_ALLOWED_INT}). This will cause the response to be returned immediately. Please use a number within the allowed range to delay the response by exact duration, or consider the "infinite" delay mode to delay the response indefinitely.`);
5077
- }
5078
- delayTime = durationOrMode;
5079
- }
5080
- res.delay = delayTime;
5325
+ res.body = JSON.stringify(body);
5081
5326
  return res;
5082
5327
  };
5083
5328
  };
5084
5329
 
5330
+ /**
5331
+ * Sets a given payload as a GraphQL response body.
5332
+ * @example
5333
+ * res(ctx.data({ user: { firstName: 'John' }}))
5334
+ * @see {@link https://mswjs.io/docs/api/context/data `ctx.data()`}
5335
+ */
5336
+ const data = (payload) => {
5337
+ return (res) => {
5338
+ const prevBody = jsonParse(res.body) || {};
5339
+ const nextBody = mergeRight(prevBody, { data: payload });
5340
+ return json(nextBody)(res);
5341
+ };
5342
+ };
5343
+
5344
+ /**
5345
+ * Sets the GraphQL extensions on a given response.
5346
+ * @example
5347
+ * res(ctx.extensions({ tracing: { version: 1 }}))
5348
+ * @see {@link https://mswjs.io/docs/api/context/extensions `ctx.extensions()`}
5349
+ */
5350
+ const extensions = (payload) => {
5351
+ return (res) => {
5352
+ const prevBody = jsonParse(res.body) || {};
5353
+ const nextBody = mergeRight(prevBody, { extensions: payload });
5354
+ return json(nextBody)(res);
5355
+ };
5356
+ };
5357
+
5085
5358
  /**
5086
5359
  * Sets a given list of GraphQL errors on the mocked response.
5087
5360
  * @example res(ctx.errors([{ message: 'Unauthorized' }]))
@@ -5098,43 +5371,6 @@ const errors = (errorsList) => {
5098
5371
  };
5099
5372
  };
5100
5373
 
5101
- const useFetch = lib$3.exports.isNodeProcess() ? require('node-fetch') : window.fetch;
5102
- const augmentRequestInit = (requestInit) => {
5103
- const headers = new lib$1.Headers(requestInit.headers);
5104
- headers.set('x-msw-bypass', 'true');
5105
- return Object.assign(Object.assign({}, requestInit), { headers: headers.all() });
5106
- };
5107
- const createFetchRequestParameters = (input) => {
5108
- const { body, method } = input;
5109
- const requestParameters = Object.assign(Object.assign({}, input), { body: undefined });
5110
- if (['GET', 'HEAD'].includes(method)) {
5111
- return requestParameters;
5112
- }
5113
- if (typeof body === 'object' ||
5114
- typeof body === 'number' ||
5115
- typeof body === 'boolean') {
5116
- requestParameters.body = JSON.stringify(body);
5117
- }
5118
- else {
5119
- requestParameters.body = body;
5120
- }
5121
- return requestParameters;
5122
- };
5123
- /**
5124
- * Performs a bypassed request inside a request handler.
5125
- * @example
5126
- * const originalResponse = await ctx.fetch(req)
5127
- * @see {@link https://mswjs.io/docs/api/context/fetch `ctx.fetch()`}
5128
- */
5129
- const fetch = (input, requestInit = {}) => {
5130
- if (typeof input === 'string') {
5131
- return useFetch(input, augmentRequestInit(requestInit));
5132
- }
5133
- const requestParameters = createFetchRequestParameters(input);
5134
- const derivedRequestInit = augmentRequestInit(requestParameters);
5135
- return useFetch(input.url.href, derivedRequestInit);
5136
- };
5137
-
5138
5374
  /**
5139
5375
  * Sets a textual response body. Appends a `Content-Type: text/plain`
5140
5376
  * header on the mocked response.
@@ -5206,7 +5442,7 @@ function prepareRequest(request) {
5206
5442
  * Formats a mocked response for introspection in the browser's console.
5207
5443
  */
5208
5444
  function prepareResponse(res) {
5209
- const responseHeaders = lib$1.objectToHeaders(res.headers);
5445
+ const responseHeaders = lib$2.objectToHeaders(res.headers);
5210
5446
  return Object.assign(Object.assign({}, res), {
5211
5447
  // Parse a response JSON body for preview in the logs
5212
5448
  body: parseBody(res.body, responseHeaders) });
@@ -5650,184 +5886,6 @@ function matchRequestUrl(url, path, baseUrl) {
5650
5886
  };
5651
5887
  }
5652
5888
 
5653
- /**
5654
- * Composes a given list of functions into a new function that
5655
- * executes from right to left.
5656
- */
5657
- function compose(...fns) {
5658
- return (...args) => {
5659
- return fns.reduceRight((leftFn, rightFn) => {
5660
- return leftFn instanceof Promise
5661
- ? Promise.resolve(leftFn).then(rightFn)
5662
- : rightFn(leftFn);
5663
- }, args[0]);
5664
- };
5665
- }
5666
-
5667
- class NetworkError extends Error {
5668
- constructor(message) {
5669
- super(message);
5670
- this.name = 'NetworkError';
5671
- }
5672
- }
5673
-
5674
- const defaultResponse = {
5675
- status: 200,
5676
- statusText: 'OK',
5677
- body: null,
5678
- delay: 0,
5679
- once: false,
5680
- };
5681
- const defaultResponseTransformers = [];
5682
- function createResponseComposition(responseOverrides, defaultTransformers = defaultResponseTransformers) {
5683
- return (...transformers) => __awaiter(this, void 0, void 0, function* () {
5684
- const initialResponse = Object.assign({}, defaultResponse, {
5685
- headers: new lib$1.Headers({
5686
- 'x-powered-by': 'msw',
5687
- }),
5688
- }, responseOverrides);
5689
- const resolvedTransformers = [
5690
- ...defaultTransformers,
5691
- ...transformers,
5692
- ].filter(Boolean);
5693
- const resolvedResponse = resolvedTransformers.length > 0
5694
- ? compose(...resolvedTransformers)(initialResponse)
5695
- : initialResponse;
5696
- return resolvedResponse;
5697
- });
5698
- }
5699
- const response = Object.assign(createResponseComposition(), {
5700
- once: createResponseComposition({ once: true }),
5701
- networkError(message) {
5702
- throw new NetworkError(message);
5703
- },
5704
- });
5705
-
5706
- const BUILD_FRAME = /(node_modules)?[\/\\]lib[\/\\](umd|esm|iief|cjs)[\/\\]|^[^\/\\]*$/;
5707
- /**
5708
- * Return the stack trace frame of a function's invocation.
5709
- */
5710
- function getCallFrame(error) {
5711
- // In <IE11, new Error may return an undefined stack
5712
- const stack = error.stack;
5713
- if (!stack) {
5714
- return;
5715
- }
5716
- const frames = stack.split('\n').slice(1);
5717
- // Get the first frame that doesn't reference the library's internal trace.
5718
- // Assume that frame is the invocation frame.
5719
- const declarationFrame = frames.find((frame) => {
5720
- return !BUILD_FRAME.test(frame);
5721
- });
5722
- if (!declarationFrame) {
5723
- return;
5724
- }
5725
- // Extract file reference from the stack frame.
5726
- const declarationPath = declarationFrame
5727
- .replace(/\s*at [^()]*\(([^)]+)\)/, '$1')
5728
- .replace(/^@/, '');
5729
- return declarationPath;
5730
- }
5731
-
5732
- /**
5733
- * Determines if the given function is an iterator.
5734
- */
5735
- function isIterable(fn) {
5736
- if (!fn) {
5737
- return false;
5738
- }
5739
- return typeof fn[Symbol.iterator] == 'function';
5740
- }
5741
-
5742
- const defaultContext = {
5743
- status,
5744
- set,
5745
- delay,
5746
- fetch,
5747
- };
5748
- class RequestHandler {
5749
- constructor(options) {
5750
- this.shouldSkip = false;
5751
- this.ctx = options.ctx || defaultContext;
5752
- this.resolver = options.resolver;
5753
- const callFrame = getCallFrame(new Error());
5754
- this.info = Object.assign(Object.assign({}, options.info), { callFrame });
5755
- }
5756
- /**
5757
- * Parse the captured request to extract additional information from it.
5758
- * Parsed result is then exposed to other methods of this request handler.
5759
- */
5760
- parse(_request, _resolutionContext) {
5761
- return null;
5762
- }
5763
- /**
5764
- * Test if this handler matches the given request.
5765
- */
5766
- test(request, resolutionContext) {
5767
- return this.predicate(request, this.parse(request, resolutionContext), resolutionContext);
5768
- }
5769
- /**
5770
- * Derive the publicly exposed request (`req`) instance of the response resolver
5771
- * from the captured request and its parsed result.
5772
- */
5773
- getPublicRequest(request, _parsedResult) {
5774
- return request;
5775
- }
5776
- markAsSkipped(shouldSkip = true) {
5777
- this.shouldSkip = shouldSkip;
5778
- }
5779
- /**
5780
- * Execute this request handler and produce a mocked response
5781
- * using the given resolver function.
5782
- */
5783
- run(request, resolutionContext) {
5784
- return __awaiter(this, void 0, void 0, function* () {
5785
- if (this.shouldSkip) {
5786
- return null;
5787
- }
5788
- const parsedResult = this.parse(request, resolutionContext);
5789
- const shouldIntercept = this.predicate(request, parsedResult, resolutionContext);
5790
- if (!shouldIntercept) {
5791
- return null;
5792
- }
5793
- const publicRequest = this.getPublicRequest(request, parsedResult);
5794
- // Create a response extraction wrapper around the resolver
5795
- // since it can be both an async function and a generator.
5796
- const executeResolver = this.wrapResolver(this.resolver);
5797
- const mockedResponse = yield executeResolver(publicRequest, response, this.ctx);
5798
- return this.createExecutionResult(parsedResult, publicRequest, mockedResponse);
5799
- });
5800
- }
5801
- wrapResolver(resolver) {
5802
- return (req, res, ctx) => __awaiter(this, void 0, void 0, function* () {
5803
- const result = this.resolverGenerator || (yield resolver(req, res, ctx));
5804
- if (isIterable(result)) {
5805
- const { value, done } = result[Symbol.iterator]().next();
5806
- const nextResponse = yield value;
5807
- // If the generator is done and there is no next value,
5808
- // return the previous generator's value.
5809
- if (!nextResponse && done) {
5810
- return this.resolverGeneratorResult;
5811
- }
5812
- if (!this.resolverGenerator) {
5813
- this.resolverGenerator = result;
5814
- }
5815
- this.resolverGeneratorResult = nextResponse;
5816
- return nextResponse;
5817
- }
5818
- return result;
5819
- });
5820
- }
5821
- createExecutionResult(parsedResult, request, response) {
5822
- return {
5823
- handler: this,
5824
- parsedResult: parsedResult || null,
5825
- request,
5826
- response: response || null,
5827
- };
5828
- }
5829
- }
5830
-
5831
5889
  var RESTMethods;
5832
5890
  (function (RESTMethods) {
5833
5891
  RESTMethods["HEAD"] = "HEAD";
@@ -5838,17 +5896,11 @@ var RESTMethods;
5838
5896
  RESTMethods["OPTIONS"] = "OPTIONS";
5839
5897
  RESTMethods["DELETE"] = "DELETE";
5840
5898
  })(RESTMethods || (RESTMethods = {}));
5841
- const restContext = {
5842
- set,
5843
- status,
5844
- cookie,
5899
+ const restContext = Object.assign(Object.assign({}, defaultContext), { cookie,
5845
5900
  body,
5846
5901
  text,
5847
5902
  json,
5848
- xml,
5849
- delay,
5850
- fetch,
5851
- };
5903
+ xml });
5852
5904
  /**
5853
5905
  * Request handler for REST API requests.
5854
5906
  * Provides request matching based on method and URL.
@@ -5919,16 +5971,10 @@ function tryCatch(fn, onException) {
5919
5971
  }
5920
5972
  }
5921
5973
 
5922
- const graphqlContext = {
5923
- set,
5924
- status,
5925
- delay,
5926
- fetch,
5927
- data,
5974
+ const graphqlContext = Object.assign(Object.assign({}, defaultContext), { data,
5928
5975
  extensions,
5929
5976
  errors,
5930
- cookie,
5931
- };
5977
+ cookie });
5932
5978
  function isDocumentNode(value) {
5933
5979
  if (value == null) {
5934
5980
  return false;
@@ -6148,17 +6194,24 @@ function readResponseCookies(request, response) {
6148
6194
  }
6149
6195
 
6150
6196
  function handleRequest(request, handlers, options, emitter, handleRequestOptions) {
6151
- var _a, _b, _c;
6197
+ var _a, _b, _c, _d;
6152
6198
  return __awaiter(this, void 0, void 0, function* () {
6153
6199
  emitter.emit('request:start', request);
6154
6200
  // Perform bypassed requests (i.e. issued via "ctx.fetch") as-is.
6155
6201
  if (request.headers.get('x-msw-bypass') === 'true') {
6156
6202
  emitter.emit('request:end', request);
6157
- (_a = handleRequestOptions === null || handleRequestOptions === void 0 ? void 0 : handleRequestOptions.onBypassResponse) === null || _a === void 0 ? void 0 : _a.call(handleRequestOptions, request);
6203
+ (_a = handleRequestOptions === null || handleRequestOptions === void 0 ? void 0 : handleRequestOptions.onPassthroughResponse) === null || _a === void 0 ? void 0 : _a.call(handleRequestOptions, request);
6158
6204
  return;
6159
6205
  }
6160
6206
  // Resolve a mocked response from the list of request handlers.
6161
- const lookupResult = yield getResponse(request, handlers, handleRequestOptions === null || handleRequestOptions === void 0 ? void 0 : handleRequestOptions.resolutionContext);
6207
+ const [lookupError, lookupResult] = yield until(() => {
6208
+ return getResponse(request, handlers, handleRequestOptions === null || handleRequestOptions === void 0 ? void 0 : handleRequestOptions.resolutionContext);
6209
+ });
6210
+ if (lookupError) {
6211
+ // Allow developers to react to unhandled exceptions in request handlers.
6212
+ emitter.emit('unhandledException', lookupError, request);
6213
+ throw lookupError;
6214
+ }
6162
6215
  const { handler, response } = lookupResult;
6163
6216
  // When there's no handler for the request, consider it unhandled.
6164
6217
  // Allow the developer to react to such cases.
@@ -6166,7 +6219,7 @@ function handleRequest(request, handlers, options, emitter, handleRequestOptions
6166
6219
  onUnhandledRequest(request, handlers, options.onUnhandledRequest);
6167
6220
  emitter.emit('request:unhandled', request);
6168
6221
  emitter.emit('request:end', request);
6169
- (_b = handleRequestOptions === null || handleRequestOptions === void 0 ? void 0 : handleRequestOptions.onBypassResponse) === null || _b === void 0 ? void 0 : _b.call(handleRequestOptions, request);
6222
+ (_b = handleRequestOptions === null || handleRequestOptions === void 0 ? void 0 : handleRequestOptions.onPassthroughResponse) === null || _b === void 0 ? void 0 : _b.call(handleRequestOptions, request);
6170
6223
  return;
6171
6224
  }
6172
6225
  // When the handled request returned no mocked response, warn the developer,
@@ -6179,7 +6232,14 @@ Expected response resolver to return a mocked response Object, but got %s. The o
6179
6232
  %s\
6180
6233
  `, response, handler.info.header, handler.info.callFrame);
6181
6234
  emitter.emit('request:end', request);
6182
- (_c = handleRequestOptions === null || handleRequestOptions === void 0 ? void 0 : handleRequestOptions.onBypassResponse) === null || _c === void 0 ? void 0 : _c.call(handleRequestOptions, request);
6235
+ (_c = handleRequestOptions === null || handleRequestOptions === void 0 ? void 0 : handleRequestOptions.onPassthroughResponse) === null || _c === void 0 ? void 0 : _c.call(handleRequestOptions, request);
6236
+ return;
6237
+ }
6238
+ // When the developer explicitly returned "req.passthrough()" do not warn them.
6239
+ // Perform the request as-is.
6240
+ if (response.passthrough) {
6241
+ emitter.emit('request:end', request);
6242
+ (_d = handleRequestOptions === null || handleRequestOptions === void 0 ? void 0 : handleRequestOptions.onPassthroughResponse) === null || _d === void 0 ? void 0 : _d.call(handleRequestOptions, request);
6183
6243
  return;
6184
6244
  }
6185
6245
  // Store all the received response cookies in the virtual cookie store.
@@ -6226,8 +6286,8 @@ const DEFAULT_LISTEN_OPTIONS = {
6226
6286
  * Useful to generate identical API using different patches to request issuing modules.
6227
6287
  */
6228
6288
  function createSetupServer(...interceptors$1) {
6229
- const emitter = new lib$2.StrictEventEmitter();
6230
- const publicEmitter = new lib$2.StrictEventEmitter();
6289
+ const emitter = new lib$3.StrictEventEmitter();
6290
+ const publicEmitter = new lib$3.StrictEventEmitter();
6231
6291
  pipeEvents(emitter, publicEmitter);
6232
6292
  return function setupServer(...requestHandlers) {
6233
6293
  requestHandlers.forEach((handler) => {
@@ -6238,7 +6298,7 @@ function createSetupServer(...interceptors$1) {
6238
6298
  // so it could be modified at a runtime.
6239
6299
  let currentHandlers = [...requestHandlers];
6240
6300
  // Error when attempting to run this function in a browser environment.
6241
- if (!lib$3.exports.isNodeProcess()) {
6301
+ if (!lib$4.exports.isNodeProcess()) {
6242
6302
  throw new Error(devUtils.formatMessage('Failed to execute `setupServer` in the environment that is not Node.js (i.e. a browser). Consider using `setupWorker` instead.'));
6243
6303
  }
6244
6304
  let resolvedOptions = {};