wrapito 9.5.0 → 10.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Mercadona
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,30 +1,43 @@
1
1
  # 🌯 wrapito
2
- Wrap your tests so that you can test both behaviour and components with less effort.
2
+
3
+ Wrap you tests so that you can test both behaviour and components with less effort.
4
+
5
+ ## IMPORTANT
6
+
7
+ This version is only compatible with [vitest](https://vitest.dev/).
3
8
 
4
9
  ## 🎯 Motivation
5
- As we are more focused on user interactions than implementation details, it's better to test all the possible user interactions at a certain point in our app by rendering the higher-level components.
6
10
 
7
- ## 💡 The idea
8
- As we test our app we will be in two different scenarios where:
9
- - We will need to test that the user interactions cause the proper side effects such as making http calls or refreshing the UI.
10
- - In case we have a components library, we will need to test these by passing the needed props and checking that it returns (renders) the expected result.
11
+ As we are more focused on user interactions than implementation details. In order to test all the user interactions that
12
+ can be done at a certain point of our app, the upper the component we render in the test, the better.
11
13
 
12
- In general, if you want to test behaviour, you need to simulate external actions from users or from http responses.
14
+ ## 💡 The idea
13
15
 
14
- Most of the existing testing libraries give you control of the user actions and that's why we only require you to set the `render` function of your testing library in the config.
16
+ As we test our app we will be in two different scenarios where:
15
17
 
16
- Unfortunately, there aren't so many options when it comes to managing http requests and responses in tests.
18
+ - We will need to test that the user interactions cause the proper side effects such as making http calls or refreshing
19
+ the UI.
20
+ - In case we have a components library, we will need to test these by passing the needed props and checking that it
21
+ returns (renders) the expected result.
17
22
 
18
- To provide the mounted component with context, we use the builder pattern in our tests. This approach clarifies the current path where the app should be mounted, the props received by the component, the expected results of HTTP requests, and the mounting location for the portal. This makes our tests much more semantic and understandable.
23
+ In general, if you want to test behaviour, you need to simulate external actions from user or from http responses.
24
+ Most of the existing testing libraries give you control of the user actions and thats why we just ask you to set in the
25
+ config what is the `render` function of your testing library.
26
+ Unfortunately, there aren't so many options when it comes to manage http requests and responses in the tests.
27
+ To give the mounted component context about which path is the current path where the app should be mounted, what props
28
+ does the component receive, what http requests will respond with which results or where should the portal be mounted we
29
+ have used the builder pattern that makes tests much more semantic.
19
30
 
20
31
  ## 🔧 Installing
32
+
21
33
  Using npm:
22
34
 
23
35
  ```sh
24
- $ npm install -D wrapito
36
+ $ npm install wrapito
25
37
  ```
26
38
 
27
39
  ## 👩‍💻 Basic usage
40
+
28
41
  ```js
29
42
  const MyComponent = () => <span>Just a component</span>
30
43
 
@@ -32,7 +45,10 @@ const myWrappedComponent = wrap(MyComponent).mount()
32
45
  ```
33
46
 
34
47
  ## 👣 Initial setup
35
- Because 🌯 `wrapito` doesn't want to know anything about how the components are mounted in the project that uses it, we can specify how we will `mount` our components by passing the rendering/mounting function of our library of preference. This way we make `wrapito` a little bit more agnostic. For example `setup.wrapito.js`
48
+
49
+ Because 🌯 `wrapito` doesn't want to know anything about how the components are mounted in the project that uses it, we
50
+ can specify how we will `mount` our components by passing the rendering/mounting function of our library of preference.
51
+ This way we make `wrapito` a little bit more agnostic. For example `setup.wrapito.js`
36
52
 
37
53
  ```js
38
54
  import { render } from '@testing-library/react'
@@ -46,12 +62,15 @@ configure({
46
62
  and add the previous file in `jest.config.json`
47
63
 
48
64
  ```js
49
- "setupFiles": [
50
- "<rootDir>/config/jest/setup.wrapito.js"
51
- ],
65
+ "setupFiles"
66
+ :
67
+ [
68
+ "<rootDir>/config/jest/setup.wrapito.js"
69
+ ],
52
70
  ```
53
71
 
54
- If one or more of your components use a `react portal` in any way, you will need to specify the `id` of the node where it will be added:
72
+ If one or more of your components use a `react portal` in any way, you will need to specify the `id` of the node where
73
+ it will be added:
55
74
 
56
75
  ```js
57
76
  import { render } from '@testing-library/react'
@@ -67,10 +86,14 @@ configure({
67
86
 
68
87
  #### withMocks (Deprecated)
69
88
 
70
- It has the same API than the withNetwork builder. The main difference between them is that withMocks will fail if a given request, done by the production code, is not set up in the `responses object`.
89
+ It has the same API than the withNetwork builder. The main difference between them is that withMocks will fail if a
90
+ given request, done by the production code, is not set up in the `responses object`.
71
91
 
72
92
  #### withNetwork
73
- By using this feature you can configure the responses for your `http requests`. If your component is making a request that is not set up in the `responses object`, it will not be validated and it will return an empty response with code 200.
93
+
94
+ By using this feature you can configure the responses for your `http requests`. If your component is making a request
95
+ that is not set up in the `responses object`, it will not be validated and it will return an empty response with code
96
+ 200.
74
97
 
75
98
  ```js
76
99
  import { wrap } from 'wrapito'
@@ -91,13 +114,17 @@ wrap(MyComponent)
91
114
  ```
92
115
 
93
116
  You can specify the default `host` via configuration:
117
+
94
118
  ```js
95
119
  import { configure } from 'wrapito'
96
120
 
97
121
  const { API_HOST, API_VERSION } = process.env
98
- configure({ defaultHost: `${ API_HOST }${ API_VERSION }` })
122
+ configure({ defaultHost: `${API_HOST}${API_VERSION}` })
99
123
  ```
100
- In addition, `wrapito` defaults the `method` to `'get'` and `status` to `200`. This means one can use `withNetwork` like this:
124
+
125
+ In addition, `wrapito` defaults the `method` to `'get'` and `status` to `200`. This means one can use `withNetwork` like
126
+ this:
127
+
101
128
  ```js
102
129
  import { wrap } from 'wrapito'
103
130
 
@@ -110,7 +137,10 @@ wrap(MyComponent)
110
137
  .withNetwork(responses)
111
138
  .mount()
112
139
  ```
113
- Now, you might need to mock several `http responses` at the same time and that's why you can also pass an array of responses instead if you wish:
140
+
141
+ Now, you might need to mock several `http responses` at the same time and that's why you can also pass an array of
142
+ responses instead if you wish:
143
+
114
144
  ```js
115
145
  import { wrap } from 'wrapito'
116
146
 
@@ -133,7 +163,9 @@ wrap(MyComponent)
133
163
  .mount()
134
164
  ```
135
165
 
136
- There might be cases where one request is called several times and we want it to return different responses. An example of this could be an app that shows a list of products that may be updated over time and for this propose the app has a refresh button that will request the list again in order to update its content.
166
+ There might be cases where one request is called several times and we want it to return different responses. An example
167
+ of this could be an app that shows a list of products that may be updated over time and for this propose the app has a
168
+ refresh button that will request the list again in order to update its content.
137
169
 
138
170
  Well, it can be solved by specifying the response as multiple using `multipleResponse` as follows:
139
171
 
@@ -141,31 +173,38 @@ Well, it can be solved by specifying the response as multiple using `multipleRes
141
173
  const responses = {
142
174
  path: '/path/to/get/the/products/list/,
143
175
  multipleResponses: [
144
- {
145
- responseBody: [
146
- { id: 1, name: 'hummus' },
147
- { id: 2, name: 'guacamole' },
148
- ]
149
- },
150
- {
151
- responseBody: [
152
- { id: 1, name: 'hummus' },
153
- { id: 2, name: 'guacamole' },
154
- { id: 3, name: 'peanut butter' },
155
- ]
156
- },
176
+ {
177
+ responseBody: [
178
+ { id: 1, name: 'hummus' },
179
+ { id: 2, name: 'guacamole' },
180
+ ]
181
+ },
182
+ {
183
+ responseBody: [
184
+ { id: 1, name: 'hummus' },
185
+ { id: 2, name: 'guacamole' },
186
+ { id: 3, name: 'peanut butter' },
187
+ ]
188
+ },
157
189
  ],
158
190
  }
159
191
  ```
160
192
 
161
- `multipleResponses` receives an array of responses where one set the `responseBody`, `status` or `headers` for every response.
193
+ `multipleResponses` receives an array of responses where one set the `responseBody`, `status` or `headers` for every
194
+ response.
162
195
 
163
- When `multipleResponses` is present, 🌯 `wrapito` will ignore the `responseBody` at the root of the mock and will return one response per request made at the same time that sets the returned response as `hasBeenReturned`, which means it can be returned again, until all the array of responses is returned. In that case an exception will be raised.
196
+ When `multipleResponses` is present, 🌯 `wrapito` will ignore the `responseBody` at the root of the mock and will return
197
+ one response per request made at the same time that sets the returned response as `hasBeenReturned`, which means it can
198
+ be returned again, until all the array of responses is returned. In that case an exception will be raised.
164
199
 
165
- This behaviour differs from using a single response for a given request as single response for a given request will return the response no matter how many times the request is called.
200
+ This behaviour differs from using a single response for a given request as single response for a given request will
201
+ return the response no matter how many times the request is called.
166
202
 
167
203
  #### atPath
168
- When mounting the whole app, it will be done at the default route passing the default path. But a specific route might need to be mounted and for that reason a path to match that route should be pass here.
204
+
205
+ When mounting the whole app, it will be done at the default route passing the default path. But a specific route might
206
+ need to be mounted and for that reason a path to match that route should be pass here.
207
+
169
208
  ```js
170
209
  import { wrap } from 'wrapito'
171
210
 
@@ -174,7 +213,9 @@ wrap(MyComponent)
174
213
  .mount()
175
214
  ```
176
215
 
177
- By default it will use the native javascript history API, but you can provide a method to be called for change the app route with [`changeRoute`](#changeRoute):
216
+ By default it will use the native javascript history API, but you can provide a method to be called for change the app
217
+ route with [`changeRoute`](#changeRoute):
218
+
178
219
  ```js
179
220
  import { configure } from 'wrapito'
180
221
  import { history } from 'app.js'
@@ -186,19 +227,22 @@ configure({
186
227
  ```
187
228
 
188
229
  #### withProps
230
+
189
231
  Pass down the props to the wrapped component:
232
+
190
233
  ```js
191
234
  import { wrap } from 'wrapito'
192
235
 
193
236
  const props = { message: 'MyComponent will receive this as prop' }
194
237
 
195
- wrap(MyComponent)
196
- .withProps(props)
197
- .mount()
238
+ wrap(MyComponent).withProps(props).mount()
198
239
  ```
199
240
 
200
241
  #### composing
201
- As it is basically a builder, all the above functions can be used at the same time and these will be composed underneath:
242
+
243
+ As it is basically a builder, all the above functions can be used at the same time and these will be composed
244
+ underneath:
245
+
202
246
  ```js
203
247
  import { wrap } from 'wrapito'
204
248
 
@@ -216,25 +260,26 @@ wrap(PreparationContainer)
216
260
  ```
217
261
 
218
262
  ## ✨ Utils
263
+
219
264
  #### toHaveBeenFetched
220
- Some times checking only the visual side effects in the UI it's not enough. In the case that we want to check if a particular network side effect is happening, this assertion will come in handy.
265
+
266
+ Some times checking only the visual side effects in the UI it's not enough. In the case that we want to check if a
267
+ particular network side effect is happening, this assertion will come in handy.
221
268
 
222
269
  ```js
223
- wrap(MyComponentMakingHttpCalls)
224
- .withNetwork(responses)
225
- .mount()
270
+ wrap(MyComponentMakingHttpCalls).withNetwork(responses).mount()
226
271
 
227
- expect('/some/path').toHaveBeenFetched()
272
+ expect('/some/path').toHaveBeenFetched()
228
273
  ```
229
274
 
230
275
  #### toHaveBeenFetchedWith
276
+
231
277
  This assertion is an extension of `toHaveBeenFetched` but we will use it if we want to check the properties.
278
+
232
279
  ```js
233
280
  import { wrap, assertions } from 'wrapito'
234
281
 
235
- wrap(MyComponentMakingHttpCalls)
236
- .withNetwork(responses)
237
- .mount()
282
+ wrap(MyComponentMakingHttpCalls).withNetwork(responses).mount()
238
283
 
239
284
  expect('/some/path').toHaveBeenFetchedWith({
240
285
  method: 'POST',
@@ -243,19 +288,17 @@ expect('/some/path').toHaveBeenFetchedWith({
243
288
  ```
244
289
 
245
290
  #### toHaveBeenFetchedTimes
291
+
246
292
  This assertion is to check how many times an API url is called.
293
+
247
294
  ```js
248
295
  import { wrap, assertions } from 'wrapito'
249
296
 
250
297
  expect.extend(assertions)
251
298
 
252
- const responses = [
253
- { path: '/path/to/get/quantity/' },
254
- ]
299
+ const responses = [{ path: '/path/to/get/quantity/' }]
255
300
 
256
- wrap(MyComponentMakingHttpCalls)
257
- .withNetwork(responses)
258
- .mount()
301
+ wrap(MyComponentMakingHttpCalls).withNetwork(responses).mount()
259
302
 
260
303
  expect('/path/to/get/quantity/').toHaveBeenFetchedTimes(1)
261
304
  ```
@@ -264,6 +307,26 @@ expect('/path/to/get/quantity/').toHaveBeenFetchedTimes(1)
264
307
 
265
308
  In order to test the library in a project without releasing the library:
266
309
 
267
- - ```npm run build```
310
+ - `npm run build`
268
311
  - This will generate a local build in the `dist` folder
269
312
  - Copy the content of that folder in `node_modules/wrapito` in your project
313
+
314
+ ## Deploy new version in npm
315
+
316
+ You need to create a new tag for the project. E.g:
317
+
318
+ ```
319
+ git tag v1.0.5
320
+ git push origin v1.0.5
321
+ ```
322
+
323
+ This will run a workflow in github that will publish this version for you.
324
+
325
+ If you need to release beta versions to test things, you may do so with the -beta tag. E.g:
326
+
327
+ ```
328
+ git tag v1.0.5-beta1
329
+ git push origin v1.0.5-beta1
330
+ ```
331
+
332
+ This will run a workflow in github that will publish this version for you as a pre-release.
@@ -0,0 +1,93 @@
1
+ import React from 'react';
2
+ import { RenderResult as RenderResult$1 } from '@testing-library/react';
3
+
4
+ type HttpMethod = UpperCaseHttpMethod | Lowercase<UpperCaseHttpMethod>;
5
+ type UpperCaseHttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'CONNECT' | 'TRACE';
6
+ interface WrapRequest extends Partial<Request> {
7
+ _bodyInit?: string;
8
+ url: string;
9
+ }
10
+ interface RequestOptions {
11
+ host?: string;
12
+ body?: object | string;
13
+ method?: HttpMethod;
14
+ }
15
+ interface WrapResponse extends Partial<Response> {
16
+ /** The call's path we want to mock */
17
+ path: string;
18
+ /** To which host the call corresponds to */
19
+ host?: string;
20
+ /** The HTTP method we should intercept, defaults to GET */
21
+ method?: HttpMethod;
22
+ /** The response for this call */
23
+ responseBody?: object | string;
24
+ /** The request to match with the responseBody for this call */
25
+ requestBody?: object;
26
+ /** Allows to return multiple response for a call */
27
+ multipleResponses?: Array<Partial<WrapResponse>>;
28
+ catchParams?: boolean;
29
+ delay?: number;
30
+ hasBeenReturned?: boolean;
31
+ }
32
+ type NetworkResponses = WrapResponse | WrapResponse[];
33
+ interface Wrap {
34
+ withNetwork: (responses?: NetworkResponses) => Wrap;
35
+ atPath: (path: string, historyState?: object) => Wrap;
36
+ withProps: (props: object) => Wrap;
37
+ debugRequests: () => Wrap;
38
+ mount: () => RenderResult;
39
+ }
40
+ interface WrapOptions {
41
+ Component: unknown;
42
+ responses: WrapResponse[];
43
+ props: object;
44
+ path: string;
45
+ historyState?: object;
46
+ hasPath: boolean;
47
+ debug: boolean;
48
+ }
49
+ interface WrapExtensionAPI {
50
+ addResponses: (responses: Array<WrapResponse>) => unknown;
51
+ }
52
+ type Extension = <T>(extensionAPI: WrapExtensionAPI, args: T) => Wrap;
53
+ type Extensions = {
54
+ [key: string]: Extension;
55
+ };
56
+ type Component = React.ReactElement<any, any>;
57
+ type RenderResult = RenderResult$1 | HTMLDivElement;
58
+ type Mount = (component: Component) => RenderResult;
59
+ interface Config {
60
+ defaultHost: string;
61
+ mount: Mount;
62
+ extend: Extensions;
63
+ changeRoute: (path: string) => void;
64
+ history?: BrowserHistory;
65
+ portal?: string;
66
+ handleQueryParams?: boolean;
67
+ }
68
+ interface BrowserHistory extends History {
69
+ push: (path: string, historyState?: object) => void;
70
+ }
71
+
72
+ declare const wrap: (component: unknown) => Wrap;
73
+
74
+ declare const mount: (Component: Component) => RenderResult;
75
+ declare function configure(newConfig: Partial<Config>): void;
76
+ declare const getConfig: () => Config;
77
+
78
+ declare const matchers: {
79
+ toHaveBeenFetched: (path: string, options?: RequestOptions) => {
80
+ pass: boolean;
81
+ message: () => string;
82
+ };
83
+ toHaveBeenFetchedWith: (path: string, options?: RequestOptions) => {
84
+ pass: boolean;
85
+ message: () => string;
86
+ };
87
+ toHaveBeenFetchedTimes: (path: string, expectedLength: number, options?: RequestOptions) => {
88
+ pass: boolean;
89
+ message: () => string;
90
+ };
91
+ };
92
+
93
+ export { type BrowserHistory, type Component, type Config, type Extension, type Extensions, type HttpMethod, type Mount, type NetworkResponses, type RenderResult, type RequestOptions, type WrapResponse as Response, type Wrap, type WrapExtensionAPI, type WrapOptions, type WrapRequest, type WrapResponse, matchers as assertions, configure, getConfig, matchers, mount, wrap };
@@ -0,0 +1,93 @@
1
+ import React from 'react';
2
+ import { RenderResult as RenderResult$1 } from '@testing-library/react';
3
+
4
+ type HttpMethod = UpperCaseHttpMethod | Lowercase<UpperCaseHttpMethod>;
5
+ type UpperCaseHttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'CONNECT' | 'TRACE';
6
+ interface WrapRequest extends Partial<Request> {
7
+ _bodyInit?: string;
8
+ url: string;
9
+ }
10
+ interface RequestOptions {
11
+ host?: string;
12
+ body?: object | string;
13
+ method?: HttpMethod;
14
+ }
15
+ interface WrapResponse extends Partial<Response> {
16
+ /** The call's path we want to mock */
17
+ path: string;
18
+ /** To which host the call corresponds to */
19
+ host?: string;
20
+ /** The HTTP method we should intercept, defaults to GET */
21
+ method?: HttpMethod;
22
+ /** The response for this call */
23
+ responseBody?: object | string;
24
+ /** The request to match with the responseBody for this call */
25
+ requestBody?: object;
26
+ /** Allows to return multiple response for a call */
27
+ multipleResponses?: Array<Partial<WrapResponse>>;
28
+ catchParams?: boolean;
29
+ delay?: number;
30
+ hasBeenReturned?: boolean;
31
+ }
32
+ type NetworkResponses = WrapResponse | WrapResponse[];
33
+ interface Wrap {
34
+ withNetwork: (responses?: NetworkResponses) => Wrap;
35
+ atPath: (path: string, historyState?: object) => Wrap;
36
+ withProps: (props: object) => Wrap;
37
+ debugRequests: () => Wrap;
38
+ mount: () => RenderResult;
39
+ }
40
+ interface WrapOptions {
41
+ Component: unknown;
42
+ responses: WrapResponse[];
43
+ props: object;
44
+ path: string;
45
+ historyState?: object;
46
+ hasPath: boolean;
47
+ debug: boolean;
48
+ }
49
+ interface WrapExtensionAPI {
50
+ addResponses: (responses: Array<WrapResponse>) => unknown;
51
+ }
52
+ type Extension = <T>(extensionAPI: WrapExtensionAPI, args: T) => Wrap;
53
+ type Extensions = {
54
+ [key: string]: Extension;
55
+ };
56
+ type Component = React.ReactElement<any, any>;
57
+ type RenderResult = RenderResult$1 | HTMLDivElement;
58
+ type Mount = (component: Component) => RenderResult;
59
+ interface Config {
60
+ defaultHost: string;
61
+ mount: Mount;
62
+ extend: Extensions;
63
+ changeRoute: (path: string) => void;
64
+ history?: BrowserHistory;
65
+ portal?: string;
66
+ handleQueryParams?: boolean;
67
+ }
68
+ interface BrowserHistory extends History {
69
+ push: (path: string, historyState?: object) => void;
70
+ }
71
+
72
+ declare const wrap: (component: unknown) => Wrap;
73
+
74
+ declare const mount: (Component: Component) => RenderResult;
75
+ declare function configure(newConfig: Partial<Config>): void;
76
+ declare const getConfig: () => Config;
77
+
78
+ declare const matchers: {
79
+ toHaveBeenFetched: (path: string, options?: RequestOptions) => {
80
+ pass: boolean;
81
+ message: () => string;
82
+ };
83
+ toHaveBeenFetchedWith: (path: string, options?: RequestOptions) => {
84
+ pass: boolean;
85
+ message: () => string;
86
+ };
87
+ toHaveBeenFetchedTimes: (path: string, expectedLength: number, options?: RequestOptions) => {
88
+ pass: boolean;
89
+ message: () => string;
90
+ };
91
+ };
92
+
93
+ export { type BrowserHistory, type Component, type Config, type Extension, type Extensions, type HttpMethod, type Mount, type NetworkResponses, type RenderResult, type RequestOptions, type WrapResponse as Response, type Wrap, type WrapExtensionAPI, type WrapOptions, type WrapRequest, type WrapResponse, matchers as assertions, configure, getConfig, matchers, mount, wrap };
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ "use strict";var ce=Object.create;var E=Object.defineProperty;var pe=Object.getOwnPropertyDescriptor;var ue=Object.getOwnPropertyNames;var le=Object.getPrototypeOf,me=Object.prototype.hasOwnProperty;var de=(e,t)=>{for(var n in t)E(e,n,{get:t[n],enumerable:!0})},$=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ue(t))!me.call(e,o)&&o!==n&&E(e,o,{get:()=>t[o],enumerable:!(s=pe(t,o))||s.enumerable});return e};var M=(e,t,n)=>(n=e!=null?ce(le(e)):{},$(t||!e||!e.__esModule?E(n,"default",{value:e,enumerable:!0}):n,e)),he=e=>$(E({},"__esModule",{value:!0}),e);var Ve={};de(Ve,{assertions:()=>Ge,configure:()=>fe,getConfig:()=>d,matchers:()=>Ge,mount:()=>F,wrap:()=>Oe});module.exports=he(Ve);var Y=M(require("react"),1);var f=M(require("chalk"),1);var A=M(require("object-hash"),1);var D=require("react-dom"),F=e=>{let t=document.body.appendChild(document.createElement("div"));return(0,D.render)(e,t),t},v={defaultHost:"",extend:{},mount:F,changeRoute:e=>window.history.replaceState(null,"",e)};function fe(e){v={...v,...e}}var d=()=>({...v});var U=e=>t=>{let{method:n="GET",path:s,host:o=d().defaultHost,requestBody:r=void 0,catchParams:a}=t,l=o+s,p=!d().handleQueryParams||a,u=(0,A.default)({url:p?l:l.split("?")[0],method:n.toUpperCase(),requestBody:r}),i;return"_bodyInit"in e&&e._bodyInit!==void 0&&(i=JSON.parse(e._bodyInit)),(0,A.default)({url:p?e.url:e.url.split("?")[0],method:e.method,requestBody:i})===u};function P(e,t){if(!e)throw new Error(t)}function w(e,t){return typeof t===e}function ge(e){return e instanceof Promise}function B(e,t,n){Object.defineProperty(e,t,n)}function k(e,t,n){Object.defineProperty(e,t,{value:n})}var T=Symbol.for("tinyspy:spy"),ye=new Set,Re=e=>{e.called=!1,e.callCount=0,e.calls=[],e.results=[],e.next=[]},be=e=>(B(e,T,{value:{reset:()=>Re(e[T])}}),e[T]),I=e=>e[T]||be(e);function we(e){P(w("function",e)||w("undefined",e),"cannot spy on a non-function value");let t=function(...s){let o=I(t);o.called=!0,o.callCount++,o.calls.push(s);let r=o.next.shift();if(r){o.results.push(r);let[u,i]=r;if(u==="ok")return i;throw i}let a,l="ok";if(o.impl)try{new.target?a=Reflect.construct(o.impl,s,new.target):a=o.impl.apply(this,s),l="ok"}catch(u){throw a=u,l="error",o.results.push([l,u]),u}let p=[l,a];if(ge(a)){let u=a.then(i=>p[1]=i).catch(i=>{throw p[0]="error",p[1]=i,i});Object.assign(u,a),a=u}return o.results.push(p),a};k(t,"_isMockFunction",!0),k(t,"length",e?e.length:0),k(t,"name",e&&e.name||"spy");let n=I(t);return n.reset(),n.impl=e,t}var L=(e,t)=>Object.getOwnPropertyDescriptor(e,t),_=(e,t)=>{t!=null&&typeof t=="function"&&t.prototype!=null&&Object.setPrototypeOf(e.prototype,t.prototype)};function G(e,t,n){P(!w("undefined",e),"spyOn could not find an object to spy upon"),P(w("object",e)||w("function",e),"cannot spyOn on a primitive value");let[s,o]=(()=>{if(!w("object",t))return[t,"value"];if("getter"in t&&"setter"in t)throw new Error("cannot spy on both getter and setter");if("getter"in t)return[t.getter,"get"];if("setter"in t)return[t.setter,"set"];throw new Error("specify getter or setter to spy on")})(),r=L(e,s),a=Object.getPrototypeOf(e),l=a&&L(a,s),p=r||l;P(p||s in e,`${String(s)} does not exist`);let u=!1;o==="value"&&p&&!p.value&&p.get&&(o="get",u=!0,n=p.get());let i;p?i=p[o]:o!=="value"?i=()=>e[s]:i=e[s],n||(n=i);let m=we(n);o==="value"&&_(m,i);let c=b=>{let{value:W,...q}=p||{configurable:!0,writable:!0};o!=="value"&&delete q.writable,q[o]=b,B(e,s,q)},R=()=>p?B(e,s,p):c(i),h=m[T];return k(h,"restore",R),k(h,"getOriginal",()=>u?i():i),k(h,"willCall",b=>(h.impl=b,m)),c(u?()=>(_(m,n),m):m),ye.add(m),m}var xe=new Set,Te=0;function Ee(e){let t=e,n,s=[],o=[],r=I(e),a={get calls(){return r.calls},get instances(){return s},get invocationCallOrder(){return o},get results(){return r.results.map(([c,R])=>({type:c==="error"?"throw":"return",value:R}))},get lastCall(){return r.calls[r.calls.length-1]}},l=[],p=!1;function u(...c){return s.push(this),o.push(++Te),(p?n:l.shift()||n||r.getOriginal()||(()=>{})).apply(this,c)}let i=t.name;t.getMockName=()=>i||"vi.fn()",t.mockName=c=>(i=c,t),t.mockClear=()=>(r.reset(),s=[],o=[],t),t.mockReset=()=>(t.mockClear(),n=()=>{},l=[],t),t.mockRestore=()=>(t.mockReset(),r.restore(),n=void 0,t),t.getMockImplementation=()=>n,t.mockImplementation=c=>(n=c,r.willCall(u),t),t.mockImplementationOnce=c=>(l.push(c),t);function m(c,R){let h=n;n=c,r.willCall(u),p=!0;let b=()=>{n=h,p=!1},W=R();return W instanceof Promise?W.then(()=>(b(),t)):(b(),t)}return t.withImplementation=m,t.mockReturnThis=()=>t.mockImplementation(function(){return this}),t.mockReturnValue=c=>t.mockImplementation(()=>c),t.mockReturnValueOnce=c=>t.mockImplementationOnce(()=>c),t.mockResolvedValue=c=>t.mockImplementation(()=>Promise.resolve(c)),t.mockResolvedValueOnce=c=>t.mockImplementationOnce(()=>Promise.resolve(c)),t.mockRejectedValue=c=>t.mockImplementation(()=>Promise.reject(c)),t.mockRejectedValueOnce=c=>t.mockImplementationOnce(()=>Promise.reject(c)),Object.defineProperty(t,"mock",{get:()=>a}),r.willCall(u),xe.add(t),t}var O=e=>Ee(G({spy:e||(()=>{})},"spy"));beforeEach(()=>{global.window.fetch=O()});afterEach(()=>{global.window.fetch.mockReset()});var Me=async()=>{let e={json:()=>Promise.resolve(),status:200,ok:!0,headers:new Headers({"Content-Type":"application/json"})};return Promise.resolve(e)},V=async e=>{let{responseBody:t,status:n=200,headers:s={},delay:o}=e,r={json:()=>Promise.resolve(t),status:n,ok:n>=200&&n<=299,headers:new Headers({"Content-Type":"application/json",...s})};return o?new Promise(a=>setTimeout(()=>a(r),o)):Promise.resolve(r)},Pe=e=>console.warn(`
2
+ ${f.default.white.bold.bgRed("wrapito")} ${f.default.redBright.bold("cannot find any mock matching:")}
3
+ ${f.default.greenBright(`URL: ${e.url}`)}
4
+ ${f.default.greenBright(`METHOD: ${e.method?.toLowerCase()}`)}
5
+ ${f.default.greenBright(`REQUEST BODY: ${e._bodyInit}`)}
6
+ `),Q=async(e,t,n)=>{let s=e.find(U(t));if(!s)return n&&Pe(t),Me();let{multipleResponses:o}=s;if(!o)return V(s);let r=o.find(a=>!a.hasBeenReturned);if(!r){n&&Ie(s);return}return r.hasBeenReturned=!0,V(r)},J=(e=[],t=!1)=>{global.window.fetch.mockImplementation((s,o)=>{if(typeof s=="string"){let a=new Request(s,o);return Q(e,a,t)}return Q(e,s,t)})},Ie=e=>{let t=`\u{1F32F} Wrapito: Missing response in the multipleResponses array for path ${e.path} and method ${e.method}.`,n=f.default.greenBright(t);console.warn(n)};var j,g=e=>{j={...j,...e}},y=()=>({...j});beforeEach(()=>{global.fetch=O()});afterEach(()=>{global.fetch.mockReset()});var Oe=e=>(g({Component:e,responses:[],props:{},path:"",hasPath:!1,debug:process.env.npm_config_debugRequests==="true"}),x()),x=()=>{let e=ve();return{withProps:Ae,withNetwork:Be,atPath:je,debugRequests:He,mount:Se,...e}},Ce=e=>{let t=y(),n=[...t.responses,...e];g({...t,responses:n})},We=(e,t)=>(t({addResponses:Ce},e),x()),qe=(e,t)=>{let{extend:n}=d(),s=n[t];return{...e,[t]:(...o)=>We(o,s)}},ve=()=>{let{extend:e}=d();return Object.keys(e).reduce(qe,{})},Ae=e=>{let t=y();return g({...t,props:e}),x()},Be=(e=[])=>{let t=y(),n=Array.isArray(e)?e:[e];return g({...t,responses:[...t.responses,...n]}),x()},je=(e,t)=>{let n=y();return g({...n,historyState:t,path:e,hasPath:!0}),x()},He=()=>{let e=y();return g({...e,debug:!0}),x()},Se=()=>{let{portal:e,changeRoute:t,history:n,mount:s}=d(),{Component:o,props:r,responses:a,path:l,hasPath:p,debug:u,historyState:i}=y(),m=o;return e&&Ne(e),p&&n&&(console.warn("wrapito WARNING: history is DEPRECATED. Pass a changeRoute function to the config instead."),console.warn("Read about changeRoute in: https://github.com/mercadona/wrapito#changeRoute"),n.push(l,i)),p&&!n&&t(l),J(a,u),s(Y.createElement(m,{...r}))},Ne=e=>{if(document.getElementById(e))return;let t=document.createElement("div");t.setAttribute("id",e),document.body.appendChild(t)};var z=require("jest-diff"),H=(e,t)=>{let n=t?.host?`\u{1F32F} Wrapito: ${t?.host}${e} ain't got called`:`\u{1F32F} Wrapito: ${e} ain't got called`;return{pass:!1,message:()=>n}},K=(e,t,n)=>({pass:!1,message:()=>`\u{1F32F} Wrapito: ${e} is called ${n} times, you expected ${t} times`}),X=(e,t)=>({pass:!1,message:()=>`\u{1F32F} Wrapito: Fetch method does not match, expected ${e} received ${t??"none"}`}),Z=(e,t)=>{let n=t.map(s=>(0,z.diff)(e,s)).join(`
7
+
8
+ `);return{pass:!1,message:()=>`\u{1F32F} Wrapito: Fetch body does not match.
9
+ ${n}`}},ee=()=>({pass:!1,message:()=>"\u{1F32F} Wrapito: Unable to find body."}),S=()=>({pass:!0,message:()=>"Test passing"}),te=(e,t)=>{let n=t?.host?`\u{1F32F} Wrapito: ${t.host}${e} is called`:`\u{1F32F} Wrapito: ${e} is called`;return{pass:!0,message:()=>n}};var ne=M(require("deep-equal"),1);var $e=()=>{let e=d().defaultHost;return e?.includes("http")?e:"https://default.com"},De=(e="",t,n)=>t.includes(n)?t:e+t,N=e=>e instanceof Request,Fe=e=>N(e)?e.url:e,C=(e,t={method:"GET"})=>fetch.mock.calls.filter(([s])=>{let o=Fe(s),r=$e(),a=new URL(o,r),l=De(t?.host,e,r),p=t?.host||r,u=new URL(l,p),i=a.pathname===u.pathname,m=a.search===u.search,c=a.host===u.host;return u.search?i&&m:t?.host?i&&c:i}),se=e=>e.flat(1).filter(N).map(t=>t.method),oe=e=>e.flat(1).filter(N).map(t=>t._bodyInit?JSON.parse(t._bodyInit):{}),re=(e,t)=>e&&!t.includes(e),ae=(e,t)=>t.map(s=>(0,ne.default)(e,s)).every(s=>s===!1),ie=e=>e.length===0;var Ue=(e,t)=>{let n=C(e);if(ie(n))return H(e);let s=se(n),o=t?.method;if(re(o,s))return X(o,s);let r=oe(n),a=t?.body;return a?ae(a,r)?Z(a,r):S():ee()},Le=(e,t={method:"GET"})=>C(e,t).length?te(e,t):H(e,t),_e=(e,t,n={method:"GET"})=>{let s=C(e,n);return s.length!==t?K(e,t,s.length):S()},Ge={toHaveBeenFetched:Le,toHaveBeenFetchedWith:Ue,toHaveBeenFetchedTimes:_e};0&&(module.exports={assertions,configure,getConfig,matchers,mount,wrap});
package/dist/index.mjs ADDED
@@ -0,0 +1,9 @@
1
+ import*as _ from"react";import k from"chalk";import H from"object-hash";import{render as te}from"react-dom";var ne=e=>{let t=document.body.appendChild(document.createElement("div"));return te(e,t),t},W={defaultHost:"",extend:{},mount:ne,changeRoute:e=>window.history.replaceState(null,"",e)};function Be(e){W={...W,...e}}var d=()=>({...W});var S=e=>t=>{let{method:n="GET",path:s,host:o=d().defaultHost,requestBody:r=void 0,catchParams:a}=t,l=o+s,p=!d().handleQueryParams||a,u=H({url:p?l:l.split("?")[0],method:n.toUpperCase(),requestBody:r}),i;return"_bodyInit"in e&&e._bodyInit!==void 0&&(i=JSON.parse(e._bodyInit)),H({url:p?e.url:e.url.split("?")[0],method:e.method,requestBody:i})===u};function E(e,t){if(!e)throw new Error(t)}function b(e,t){return typeof t===e}function se(e){return e instanceof Promise}function q(e,t,n){Object.defineProperty(e,t,n)}function w(e,t,n){Object.defineProperty(e,t,{value:n})}var T=Symbol.for("tinyspy:spy"),oe=new Set,re=e=>{e.called=!1,e.callCount=0,e.calls=[],e.results=[],e.next=[]},ae=e=>(q(e,T,{value:{reset:()=>re(e[T])}}),e[T]),M=e=>e[T]||ae(e);function ie(e){E(b("function",e)||b("undefined",e),"cannot spy on a non-function value");let t=function(...s){let o=M(t);o.called=!0,o.callCount++,o.calls.push(s);let r=o.next.shift();if(r){o.results.push(r);let[u,i]=r;if(u==="ok")return i;throw i}let a,l="ok";if(o.impl)try{new.target?a=Reflect.construct(o.impl,s,new.target):a=o.impl.apply(this,s),l="ok"}catch(u){throw a=u,l="error",o.results.push([l,u]),u}let p=[l,a];if(se(a)){let u=a.then(i=>p[1]=i).catch(i=>{throw p[0]="error",p[1]=i,i});Object.assign(u,a),a=u}return o.results.push(p),a};w(t,"_isMockFunction",!0),w(t,"length",e?e.length:0),w(t,"name",e&&e.name||"spy");let n=M(t);return n.reset(),n.impl=e,t}var N=(e,t)=>Object.getOwnPropertyDescriptor(e,t),$=(e,t)=>{t!=null&&typeof t=="function"&&t.prototype!=null&&Object.setPrototypeOf(e.prototype,t.prototype)};function D(e,t,n){E(!b("undefined",e),"spyOn could not find an object to spy upon"),E(b("object",e)||b("function",e),"cannot spyOn on a primitive value");let[s,o]=(()=>{if(!b("object",t))return[t,"value"];if("getter"in t&&"setter"in t)throw new Error("cannot spy on both getter and setter");if("getter"in t)return[t.getter,"get"];if("setter"in t)return[t.setter,"set"];throw new Error("specify getter or setter to spy on")})(),r=N(e,s),a=Object.getPrototypeOf(e),l=a&&N(a,s),p=r||l;E(p||s in e,`${String(s)} does not exist`);let u=!1;o==="value"&&p&&!p.value&&p.get&&(o="get",u=!0,n=p.get());let i;p?i=p[o]:o!=="value"?i=()=>e[s]:i=e[s],n||(n=i);let m=ie(n);o==="value"&&$(m,i);let c=R=>{let{value:O,...C}=p||{configurable:!0,writable:!0};o!=="value"&&delete C.writable,C[o]=R,q(e,s,C)},y=()=>p?q(e,s,p):c(i),h=m[T];return w(h,"restore",y),w(h,"getOriginal",()=>u?i():i),w(h,"willCall",R=>(h.impl=R,m)),c(u?()=>($(m,n),m):m),oe.add(m),m}var pe=new Set,ue=0;function le(e){let t=e,n,s=[],o=[],r=M(e),a={get calls(){return r.calls},get instances(){return s},get invocationCallOrder(){return o},get results(){return r.results.map(([c,y])=>({type:c==="error"?"throw":"return",value:y}))},get lastCall(){return r.calls[r.calls.length-1]}},l=[],p=!1;function u(...c){return s.push(this),o.push(++ue),(p?n:l.shift()||n||r.getOriginal()||(()=>{})).apply(this,c)}let i=t.name;t.getMockName=()=>i||"vi.fn()",t.mockName=c=>(i=c,t),t.mockClear=()=>(r.reset(),s=[],o=[],t),t.mockReset=()=>(t.mockClear(),n=()=>{},l=[],t),t.mockRestore=()=>(t.mockReset(),r.restore(),n=void 0,t),t.getMockImplementation=()=>n,t.mockImplementation=c=>(n=c,r.willCall(u),t),t.mockImplementationOnce=c=>(l.push(c),t);function m(c,y){let h=n;n=c,r.willCall(u),p=!0;let R=()=>{n=h,p=!1},O=y();return O instanceof Promise?O.then(()=>(R(),t)):(R(),t)}return t.withImplementation=m,t.mockReturnThis=()=>t.mockImplementation(function(){return this}),t.mockReturnValue=c=>t.mockImplementation(()=>c),t.mockReturnValueOnce=c=>t.mockImplementationOnce(()=>c),t.mockResolvedValue=c=>t.mockImplementation(()=>Promise.resolve(c)),t.mockResolvedValueOnce=c=>t.mockImplementationOnce(()=>Promise.resolve(c)),t.mockRejectedValue=c=>t.mockImplementation(()=>Promise.reject(c)),t.mockRejectedValueOnce=c=>t.mockImplementationOnce(()=>Promise.reject(c)),Object.defineProperty(t,"mock",{get:()=>a}),r.willCall(u),pe.add(t),t}var P=e=>le(D({spy:e||(()=>{})},"spy"));beforeEach(()=>{global.window.fetch=P()});afterEach(()=>{global.window.fetch.mockReset()});var me=async()=>{let e={json:()=>Promise.resolve(),status:200,ok:!0,headers:new Headers({"Content-Type":"application/json"})};return Promise.resolve(e)},F=async e=>{let{responseBody:t,status:n=200,headers:s={},delay:o}=e,r={json:()=>Promise.resolve(t),status:n,ok:n>=200&&n<=299,headers:new Headers({"Content-Type":"application/json",...s})};return o?new Promise(a=>setTimeout(()=>a(r),o)):Promise.resolve(r)},de=e=>console.warn(`
2
+ ${k.white.bold.bgRed("wrapito")} ${k.redBright.bold("cannot find any mock matching:")}
3
+ ${k.greenBright(`URL: ${e.url}`)}
4
+ ${k.greenBright(`METHOD: ${e.method?.toLowerCase()}`)}
5
+ ${k.greenBright(`REQUEST BODY: ${e._bodyInit}`)}
6
+ `),U=async(e,t,n)=>{let s=e.find(S(t));if(!s)return n&&de(t),me();let{multipleResponses:o}=s;if(!o)return F(s);let r=o.find(a=>!a.hasBeenReturned);if(!r){n&&he(s);return}return r.hasBeenReturned=!0,F(r)},L=(e=[],t=!1)=>{global.window.fetch.mockImplementation((s,o)=>{if(typeof s=="string"){let a=new Request(s,o);return U(e,a,t)}return U(e,s,t)})},he=e=>{let t=`\u{1F32F} Wrapito: Missing response in the multipleResponses array for path ${e.path} and method ${e.method}.`,n=k.greenBright(t);console.warn(n)};var v,f=e=>{v={...v,...e}},g=()=>({...v});beforeEach(()=>{global.fetch=P()});afterEach(()=>{global.fetch.mockReset()});var Ye=e=>(f({Component:e,responses:[],props:{},path:"",hasPath:!1,debug:process.env.npm_config_debugRequests==="true"}),x()),x=()=>{let e=Re();return{withProps:be,withNetwork:we,atPath:ke,debugRequests:xe,mount:Te,...e}},fe=e=>{let t=g(),n=[...t.responses,...e];f({...t,responses:n})},ge=(e,t)=>(t({addResponses:fe},e),x()),ye=(e,t)=>{let{extend:n}=d(),s=n[t];return{...e,[t]:(...o)=>ge(o,s)}},Re=()=>{let{extend:e}=d();return Object.keys(e).reduce(ye,{})},be=e=>{let t=g();return f({...t,props:e}),x()},we=(e=[])=>{let t=g(),n=Array.isArray(e)?e:[e];return f({...t,responses:[...t.responses,...n]}),x()},ke=(e,t)=>{let n=g();return f({...n,historyState:t,path:e,hasPath:!0}),x()},xe=()=>{let e=g();return f({...e,debug:!0}),x()},Te=()=>{let{portal:e,changeRoute:t,history:n,mount:s}=d(),{Component:o,props:r,responses:a,path:l,hasPath:p,debug:u,historyState:i}=g(),m=o;return e&&Ee(e),p&&n&&(console.warn("wrapito WARNING: history is DEPRECATED. Pass a changeRoute function to the config instead."),console.warn("Read about changeRoute in: https://github.com/mercadona/wrapito#changeRoute"),n.push(l,i)),p&&!n&&t(l),L(a,u),s(_.createElement(m,{...r}))},Ee=e=>{if(document.getElementById(e))return;let t=document.createElement("div");t.setAttribute("id",e),document.body.appendChild(t)};import{diff as Me}from"jest-diff";var A=(e,t)=>{let n=t?.host?`\u{1F32F} Wrapito: ${t?.host}${e} ain't got called`:`\u{1F32F} Wrapito: ${e} ain't got called`;return{pass:!1,message:()=>n}},G=(e,t,n)=>({pass:!1,message:()=>`\u{1F32F} Wrapito: ${e} is called ${n} times, you expected ${t} times`}),V=(e,t)=>({pass:!1,message:()=>`\u{1F32F} Wrapito: Fetch method does not match, expected ${e} received ${t??"none"}`}),Q=(e,t)=>{let n=t.map(s=>Me(e,s)).join(`
7
+
8
+ `);return{pass:!1,message:()=>`\u{1F32F} Wrapito: Fetch body does not match.
9
+ ${n}`}},J=()=>({pass:!1,message:()=>"\u{1F32F} Wrapito: Unable to find body."}),B=()=>({pass:!0,message:()=>"Test passing"}),Y=(e,t)=>{let n=t?.host?`\u{1F32F} Wrapito: ${t.host}${e} is called`:`\u{1F32F} Wrapito: ${e} is called`;return{pass:!0,message:()=>n}};import Pe from"deep-equal";var Ie=()=>{let e=d().defaultHost;return e?.includes("http")?e:"https://default.com"},Oe=(e="",t,n)=>t.includes(n)?t:e+t,j=e=>e instanceof Request,Ce=e=>j(e)?e.url:e,I=(e,t={method:"GET"})=>fetch.mock.calls.filter(([s])=>{let o=Ce(s),r=Ie(),a=new URL(o,r),l=Oe(t?.host,e,r),p=t?.host||r,u=new URL(l,p),i=a.pathname===u.pathname,m=a.search===u.search,c=a.host===u.host;return u.search?i&&m:t?.host?i&&c:i}),z=e=>e.flat(1).filter(j).map(t=>t.method),K=e=>e.flat(1).filter(j).map(t=>t._bodyInit?JSON.parse(t._bodyInit):{}),X=(e,t)=>e&&!t.includes(e),Z=(e,t)=>t.map(s=>Pe(e,s)).every(s=>s===!1),ee=e=>e.length===0;var We=(e,t)=>{let n=I(e);if(ee(n))return A(e);let s=z(n),o=t?.method;if(X(o,s))return V(o,s);let r=K(n),a=t?.body;return a?Z(a,r)?Q(a,r):B():J()},qe=(e,t={method:"GET"})=>I(e,t).length?Y(e,t):A(e,t),ve=(e,t,n={method:"GET"})=>{let s=I(e,n);return s.length!==t?G(e,t,s.length):B()},ot={toHaveBeenFetched:qe,toHaveBeenFetchedWith:We,toHaveBeenFetchedTimes:ve};export{ot as assertions,Be as configure,d as getConfig,ot as matchers,ne as mount,Ye as wrap};