expect-webdriverio 1.2.0 → 1.4.1
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/README.md +4 -455
- package/lib/jasmineUtils.js +205 -0
- package/lib/matchers/element/toHaveChildren.js +9 -2
- package/lib/matchers/element/{toHaveClass.js → toHaveElementClass.js} +8 -3
- package/lib/matchers/element/toHaveElementClassContaining.js +20 -0
- package/lib/matchers/element/{toHaveProperty.js → toHaveElementProperty.js} +9 -4
- package/lib/matchers/element/toHaveValue.js +2 -2
- package/lib/matchers/mock/toBeRequested.js +12 -0
- package/lib/matchers/mock/toBeRequestedTimes.js +37 -0
- package/lib/matchers/mock/toBeRequestedWith.js +215 -0
- package/lib/matchers/mock/toBeRequestedWithResponse.js +13 -0
- package/lib/matchers.js +7 -3
- package/lib/options.js +2 -1
- package/lib/util/formatMessage.js +2 -1
- package/lib/utils.js +2 -1
- package/package.json +27 -17
- package/types/expect-webdriverio.d.ts +174 -85
- package/types/jest-global.d.ts +2 -2
- package/types/standalone-global.d.ts +2 -2
- package/types/standalone.d.ts +24 -2
- package/lib/matchers/element/toHaveClassContaining.js +0 -15
- package/lib/types/some-expect.js +0 -0
- package/types/jest-expect-clone/jest-expect.d.ts +0 -502
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://travis-ci.org/webdriverio/expect-webdriverio) [](https://codecov.io/gh/webdriverio/expect-webdriverio)
|
|
4
4
|
|
|
5
|
-
###### [TypeScript / JS Autocomplete](/docs/Types.md) | [Examples](docs/Examples.md) | [Extending Matchers](/docs/Extend.md)
|
|
5
|
+
###### [API](docs/API.md) | [TypeScript / JS Autocomplete](/docs/Types.md) | [Examples](docs/Examples.md) | [Extending Matchers](/docs/Extend.md)
|
|
6
6
|
|
|
7
7
|
> [WebdriverIO](https://webdriver.io/) Assertion library inspired by [expect](https://www.npmjs.com/package/expect)
|
|
8
8
|
|
|
@@ -24,7 +24,7 @@ NOTE: [WebdriverIO](https://github.com/webdriverio/webdriverio) `v5.16.11` or hi
|
|
|
24
24
|
|
|
25
25
|
In your `wdio.conf.js`
|
|
26
26
|
```js
|
|
27
|
-
|
|
27
|
+
before () { // not needed in WebdriverIO v6
|
|
28
28
|
require('expect-webdriverio')
|
|
29
29
|
},
|
|
30
30
|
```
|
|
@@ -39,458 +39,7 @@ See more [Examples](docs/Examples.md)
|
|
|
39
39
|
|
|
40
40
|
## API
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
Besides of the `expect-webdriverio` matchers you can use builtin Jest's [expect](https://jestjs.io/docs/en/expect) assertions or [expect/expectAsync](https://jasmine.github.io/api/3.5/global.html#expect) for Jasmine.
|
|
45
|
-
|
|
46
|
-
## Default Options
|
|
47
|
-
|
|
48
|
-
```js
|
|
49
|
-
{
|
|
50
|
-
wait: 2000, // ms to wait for expectation to succeed
|
|
51
|
-
interval: 100, // interval between attempts
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Set options like this:
|
|
56
|
-
```js
|
|
57
|
-
beforeSession () { // before hook works as well
|
|
58
|
-
require('expect-webdriverio').setOptions({ wait: 5000 })
|
|
59
|
-
},
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### Matcher Options
|
|
63
|
-
|
|
64
|
-
Every matcher can take several options that allows you to modify the assertion:
|
|
65
|
-
|
|
66
|
-
##### Command Options
|
|
67
|
-
|
|
68
|
-
| Name | Type | Details |
|
|
69
|
-
| ---- | ---- | ------- |
|
|
70
|
-
| <code><var>wait</var></code> | number | time in ms to wait for expectation to succeed. Default: `3000` |
|
|
71
|
-
| <code><var>interval</var></code> | number | interval between attempts. Default: `100` |
|
|
72
|
-
| <code><var>message</var></code> | string | user message to prepend before assertion error |
|
|
73
|
-
|
|
74
|
-
##### String Options
|
|
75
|
-
|
|
76
|
-
This options can be applied in addition to the command options when strings are being asserted.
|
|
77
|
-
|
|
78
|
-
| Name | Type | Details |
|
|
79
|
-
| ---- | ---- | ------- |
|
|
80
|
-
| <code><var>ignoreCase</var></code> | boolean | apply `toLowerCase` to both actual and expected values |
|
|
81
|
-
| <code><var>trim</var></code> | boolean | apply `trim` to actual value |
|
|
82
|
-
| <code><var>containing</var></code> | boolean | expect actual value to contain expected value, otherwise strict equal. |
|
|
83
|
-
| <code><var>asString</var></code> | boolean | might be helpful to force converting property value to string |
|
|
84
|
-
|
|
85
|
-
##### Number Options
|
|
86
|
-
|
|
87
|
-
This options can be applied in addition to the command options when numbers are being asserted.
|
|
88
|
-
|
|
89
|
-
| Name | Type | Details |
|
|
90
|
-
| ---- | ---- | ------- |
|
|
91
|
-
| <code><var>eq</var></code> | number | equals |
|
|
92
|
-
| <code><var>lte</var></code> | number | less then equals |
|
|
93
|
-
| <code><var>gte</var></code> | number | greater than or equals |
|
|
94
|
-
|
|
95
|
-
## Browser Matchers
|
|
96
|
-
|
|
97
|
-
### toHaveUrl
|
|
98
|
-
|
|
99
|
-
Checks if browser is on a specific page.
|
|
100
|
-
|
|
101
|
-
##### Usage
|
|
102
|
-
|
|
103
|
-
```js
|
|
104
|
-
browser.url('https://webdriver.io/')
|
|
105
|
-
expect(browser).toHaveUrl('https://webdriver.io')
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### toHaveUrlContaining
|
|
109
|
-
|
|
110
|
-
Checks if browser is on a specific page and contains the given value in URL.
|
|
111
|
-
|
|
112
|
-
##### Usage
|
|
113
|
-
|
|
114
|
-
```js
|
|
115
|
-
browser.url('https://webdriver.io/')
|
|
116
|
-
expect(browser).toHaveUrlContaining('webdriver.io')
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### toHaveTitle
|
|
120
|
-
|
|
121
|
-
Checks if website has a specific title.
|
|
122
|
-
|
|
123
|
-
##### Usage
|
|
124
|
-
|
|
125
|
-
```js
|
|
126
|
-
browser.url('https://webdriver.io/')
|
|
127
|
-
expect(browser).toHaveTitle('WebdriverIO · Next-gen browser and mobile automation test framework for Node.js')
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
### toHaveTitleContaining
|
|
131
|
-
|
|
132
|
-
Checks if website has a specific title that contains the given value.
|
|
133
|
-
|
|
134
|
-
##### Usage
|
|
135
|
-
|
|
136
|
-
```js
|
|
137
|
-
browser.url('https://webdriver.io/')
|
|
138
|
-
expect(browser).toHaveTitleContaining('Next-gen browser and mobile automation test framework')
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
## Element Matchers
|
|
142
|
-
|
|
143
|
-
### toBeDisplayed
|
|
144
|
-
|
|
145
|
-
Calls [`isDisplayed`](/docs/api/element/isDisplayed.html) on given element.
|
|
146
|
-
|
|
147
|
-
##### Usage
|
|
148
|
-
|
|
149
|
-
```js
|
|
150
|
-
const elem = $('#someElem')
|
|
151
|
-
expect(elem).toBeDisplayed()
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
### toBeVisible
|
|
155
|
-
|
|
156
|
-
Same as `toBeDisplayed`.
|
|
157
|
-
|
|
158
|
-
##### Usage
|
|
159
|
-
|
|
160
|
-
```js
|
|
161
|
-
const elem = $('#someElem')
|
|
162
|
-
expect(elem).toBeVisible()
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
### toExist
|
|
166
|
-
|
|
167
|
-
Calls [`isExisting`](/docs/api/element/isExisting.html) on given element.
|
|
168
|
-
|
|
169
|
-
##### Usage
|
|
170
|
-
|
|
171
|
-
```js
|
|
172
|
-
const elem = $('#someElem')
|
|
173
|
-
expect(elem).toExist()
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
### toBePresent
|
|
177
|
-
|
|
178
|
-
Same as `toExist`.
|
|
179
|
-
|
|
180
|
-
##### Usage
|
|
181
|
-
|
|
182
|
-
```js
|
|
183
|
-
const elem = $('#someElem')
|
|
184
|
-
expect(elem).toBePresent()
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
### toBeExisting
|
|
188
|
-
|
|
189
|
-
Same as `toExist`.
|
|
190
|
-
|
|
191
|
-
##### Usage
|
|
192
|
-
|
|
193
|
-
```js
|
|
194
|
-
const elem = $('#someElem')
|
|
195
|
-
expect(elem).toBeExisting()
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
### toBeFocused
|
|
199
|
-
|
|
200
|
-
Checks if element has focus. This assertion only works in a web context.
|
|
201
|
-
|
|
202
|
-
##### Usage
|
|
203
|
-
|
|
204
|
-
```js
|
|
205
|
-
const elem = $('#someElem')
|
|
206
|
-
expect(elem).toBeFocused()
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
### toHaveAttribute
|
|
210
|
-
|
|
211
|
-
Checks if an element has a certain attribute with a specific value.
|
|
212
|
-
|
|
213
|
-
##### Usage
|
|
214
|
-
|
|
215
|
-
```js
|
|
216
|
-
const myInput = $('input')
|
|
217
|
-
expect(myInput).toHaveAttribute('class', 'form-control')
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
### toHaveAttr
|
|
221
|
-
|
|
222
|
-
Same as `toHaveAttribute`.
|
|
223
|
-
|
|
224
|
-
##### Usage
|
|
225
|
-
|
|
226
|
-
```js
|
|
227
|
-
const myInput = $('input')
|
|
228
|
-
expect(myInput).toHaveAttr('class', 'form-control')
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### toHaveAttributeContaining
|
|
232
|
-
|
|
233
|
-
Checks if an element has a certain attribute that contains a value.
|
|
234
|
-
|
|
235
|
-
##### Usage
|
|
236
|
-
|
|
237
|
-
```js
|
|
238
|
-
const myInput = $('input')
|
|
239
|
-
expect(myInput).toHaveAttributeContaining('class', 'form')
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### toHaveAttrContaining
|
|
243
|
-
|
|
244
|
-
Same as `toHaveAttributeContaining`.
|
|
245
|
-
|
|
246
|
-
##### Usage
|
|
247
|
-
|
|
248
|
-
```js
|
|
249
|
-
const myInput = $('input')
|
|
250
|
-
expect(myInput).toHaveAttrContaining('class', 'form')
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
### toHaveClass
|
|
254
|
-
|
|
255
|
-
Checks if an element has a certain class name.
|
|
256
|
-
|
|
257
|
-
##### Usage
|
|
258
|
-
|
|
259
|
-
```js
|
|
260
|
-
const myInput = $('input')
|
|
261
|
-
expect(myInput).toHaveClass('form-control', { message: 'Not a form control!', })
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
### toHaveClassContaining
|
|
265
|
-
|
|
266
|
-
Checks if an element has a certain class name that contains provided value.
|
|
267
|
-
|
|
268
|
-
##### Usage
|
|
269
|
-
|
|
270
|
-
```js
|
|
271
|
-
const myInput = $('input')
|
|
272
|
-
expect(myInput).toHaveClassContaining('form')
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
### toHaveProperty
|
|
276
|
-
|
|
277
|
-
Checks if an element has a certain property.
|
|
278
|
-
|
|
279
|
-
##### Usage
|
|
280
|
-
|
|
281
|
-
```js
|
|
282
|
-
const elem = $('#elem')
|
|
283
|
-
expect(elem).toHaveProperty('height', 23)
|
|
284
|
-
expect(elem).not.toHaveProperty('height', 0)
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
### toHaveValue
|
|
288
|
-
|
|
289
|
-
Checks if an input element has a certain value.
|
|
290
|
-
|
|
291
|
-
##### Usage
|
|
292
|
-
|
|
293
|
-
```js
|
|
294
|
-
const myInput = $('input')
|
|
295
|
-
expect(myInput).toHaveValue('user', { ignoreCase: true })
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
### toHaveValueContaining
|
|
299
|
-
|
|
300
|
-
Checks if an input element contains a certain value.
|
|
301
|
-
|
|
302
|
-
##### Usage
|
|
303
|
-
|
|
304
|
-
```js
|
|
305
|
-
const myInput = $('input')
|
|
306
|
-
expect(myInput).toHaveValueContaining('us')
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
### toBeClickable
|
|
310
|
-
|
|
311
|
-
Checks if an element can be clicked by calling [`isClickable`](/docs/api/element/isClickable.html) on the element.
|
|
312
|
-
|
|
313
|
-
##### Usage
|
|
314
|
-
|
|
315
|
-
```js
|
|
316
|
-
const elem = $('#elem')
|
|
317
|
-
expect(elem).toBeClickable()
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
### toBeDisabled
|
|
321
|
-
|
|
322
|
-
Checks if an element is disabled by calling [`isEnabled`](/docs/api/element/isEnabled.html) on the element.
|
|
323
|
-
|
|
324
|
-
##### Usage
|
|
325
|
-
|
|
326
|
-
```js
|
|
327
|
-
const elem = $('#elem')
|
|
328
|
-
expect(elem).toBeDisabled()
|
|
329
|
-
// same as
|
|
330
|
-
expect(elem).not.toBeEnabled()
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
### toBeEnabled
|
|
334
|
-
|
|
335
|
-
Checks if an element is enabled by calling [`isEnabled`](/docs/api/element/isEnabled.html) on the element.
|
|
336
|
-
|
|
337
|
-
##### Usage
|
|
338
|
-
|
|
339
|
-
```js
|
|
340
|
-
const elem = $('#elem')
|
|
341
|
-
expect(elem).toBeEnabled()
|
|
342
|
-
// same as
|
|
343
|
-
expect(elem).not.toBeDisabled()
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
### toBeSelected
|
|
347
|
-
|
|
348
|
-
Checks if an element is enabled by calling [`isSelected`](/docs/api/element/isSelected.html) on the element.
|
|
349
|
-
|
|
350
|
-
##### Usage
|
|
351
|
-
|
|
352
|
-
```js
|
|
353
|
-
const elem = $('#elem')
|
|
354
|
-
expect(elem).toBeSelected()
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
### toBeChecked
|
|
358
|
-
|
|
359
|
-
Same as `toBeSelected`.
|
|
360
|
-
|
|
361
|
-
##### Usage
|
|
362
|
-
|
|
363
|
-
```js
|
|
364
|
-
const elem = $('#elem')
|
|
365
|
-
expect(elem).toBeChecked()
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
### toHaveHref
|
|
369
|
-
|
|
370
|
-
Checks if link element has a specifc link target.
|
|
371
|
-
|
|
372
|
-
##### Usage
|
|
373
|
-
|
|
374
|
-
```js
|
|
375
|
-
const link = $('a')
|
|
376
|
-
expect(link).toHaveHref('https://webdriver.io')
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
### toHaveLink
|
|
380
|
-
|
|
381
|
-
Same as `toHaveHref`.
|
|
382
|
-
|
|
383
|
-
##### Usage
|
|
384
|
-
|
|
385
|
-
```js
|
|
386
|
-
const link = $('a')
|
|
387
|
-
expect(link).toHaveLink('https://webdriver.io')
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
### toHaveHrefContaining
|
|
391
|
-
|
|
392
|
-
Checks if link element contains a specifc link target.
|
|
393
|
-
|
|
394
|
-
##### Usage
|
|
395
|
-
|
|
396
|
-
```js
|
|
397
|
-
const link = $('a')
|
|
398
|
-
expect(link).toHaveHrefContaining('webdriver.io')
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
### toHaveLinkContaining
|
|
402
|
-
|
|
403
|
-
Same as `toHaveHrefContaining`.
|
|
404
|
-
|
|
405
|
-
##### Usage
|
|
406
|
-
|
|
407
|
-
```js
|
|
408
|
-
const link = $('a')
|
|
409
|
-
expect(link).toHaveLinkContaining('webdriver.io')
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
### toHaveId
|
|
413
|
-
|
|
414
|
-
Checks if element has a specific `id` attribute.
|
|
415
|
-
|
|
416
|
-
##### Usage
|
|
417
|
-
|
|
418
|
-
```js
|
|
419
|
-
const elem = $('#elem')
|
|
420
|
-
expect(elem).toHaveId('elem')
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
### toHaveText
|
|
424
|
-
|
|
425
|
-
Checks if element has a specific text.
|
|
426
|
-
|
|
427
|
-
##### Usage
|
|
428
|
-
|
|
429
|
-
```js
|
|
430
|
-
browser.url('https://webdriver.io/')
|
|
431
|
-
const elem = $('.tagline')
|
|
432
|
-
expect(elem).toHaveText('Next-gen browser and mobile automation test framework for Node.js')
|
|
433
|
-
```
|
|
434
|
-
|
|
435
|
-
### toHaveTextContaining
|
|
436
|
-
|
|
437
|
-
Checks if element contains a specific text.
|
|
438
|
-
|
|
439
|
-
##### Usage
|
|
440
|
-
|
|
441
|
-
```js
|
|
442
|
-
browser.url('https://webdriver.io/')
|
|
443
|
-
const elem = $('.tagline')
|
|
444
|
-
expect(elem).toHaveTextContaining('browser and mobile automation test framework')
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
### toBeDisplayedInViewport
|
|
448
|
-
|
|
449
|
-
Checks if an element is within the viewport by calling [`isDisplayedInViewport`](/docs/api/element/isDisplayedInViewport.html) on the element.
|
|
450
|
-
|
|
451
|
-
##### Usage
|
|
452
|
-
|
|
453
|
-
```js
|
|
454
|
-
const elem = $('#elem')
|
|
455
|
-
expect(elem).toBeDisplayedInViewport()
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
### toBeVisibleInViewport
|
|
459
|
-
|
|
460
|
-
Same as `toBeDisplayedInViewport`.
|
|
461
|
-
|
|
462
|
-
##### Usage
|
|
463
|
-
|
|
464
|
-
```js
|
|
465
|
-
const elem = $('#elem')
|
|
466
|
-
expect(elem).toBeVisibleInViewport()
|
|
467
|
-
```
|
|
468
|
-
|
|
469
|
-
### toHaveChildren
|
|
470
|
-
|
|
471
|
-
Checks amount of fetched elements using [`$$`](/docs/api/browser/$$.html) command.
|
|
472
|
-
|
|
473
|
-
##### Usage
|
|
474
|
-
|
|
475
|
-
```js
|
|
476
|
-
const elems = $$('div')
|
|
477
|
-
expect(elems).toHaveChildren({ gte: 10 })
|
|
478
|
-
// same as
|
|
479
|
-
assert.ok(elems.length >= 10)
|
|
480
|
-
```
|
|
481
|
-
|
|
482
|
-
### toBeElementsArrayOfSize
|
|
483
|
-
|
|
484
|
-
Same as `toHaveChildren`.
|
|
485
|
-
|
|
486
|
-
##### Usage
|
|
487
|
-
|
|
488
|
-
```js
|
|
489
|
-
const elems = $$('div')
|
|
490
|
-
expect(elems).toBeElementsArrayOfSize({ gte: 10 })
|
|
491
|
-
// same as
|
|
492
|
-
assert.ok(elems.length >= 10)
|
|
493
|
-
```
|
|
42
|
+
Please see [API doc](docs/API.md)
|
|
494
43
|
|
|
495
44
|
## Error messages
|
|
496
45
|
|
|
@@ -501,7 +50,7 @@ Error messages are informative out of the box and contain:
|
|
|
501
50
|
- highlight the difference (texts assertions)
|
|
502
51
|
|
|
503
52
|

|
|
504
|
-

|
|
505
54
|

|
|
506
55
|
|
|
507
56
|
## What's next?
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isImmutableUnorderedSet = exports.isImmutableUnorderedKeyed = exports.hasProperty = exports.isUndefined = exports.fnNameFor = exports.isA = exports.equals = void 0;
|
|
4
|
+
function equals(a, b, customTesters, strictCheck) {
|
|
5
|
+
customTesters = customTesters || [];
|
|
6
|
+
return eq(a, b, [], [], customTesters, strictCheck ? hasKey : hasDefinedKey);
|
|
7
|
+
}
|
|
8
|
+
exports.equals = equals;
|
|
9
|
+
const functionToString = Function.prototype.toString;
|
|
10
|
+
function isAsymmetric(obj) {
|
|
11
|
+
return !!obj && isA('Function', obj.asymmetricMatch);
|
|
12
|
+
}
|
|
13
|
+
function asymmetricMatch(a, b) {
|
|
14
|
+
var asymmetricA = isAsymmetric(a), asymmetricB = isAsymmetric(b);
|
|
15
|
+
if (asymmetricA && asymmetricB) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
if (asymmetricA) {
|
|
19
|
+
return a.asymmetricMatch(b);
|
|
20
|
+
}
|
|
21
|
+
if (asymmetricB) {
|
|
22
|
+
return b.asymmetricMatch(a);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function eq(a, b, aStack, bStack, customTesters, hasKey) {
|
|
26
|
+
var result = true;
|
|
27
|
+
var asymmetricResult = asymmetricMatch(a, b);
|
|
28
|
+
if (asymmetricResult !== undefined) {
|
|
29
|
+
return asymmetricResult;
|
|
30
|
+
}
|
|
31
|
+
for (var i = 0; i < customTesters.length; i++) {
|
|
32
|
+
var customTesterResult = customTesters[i](a, b);
|
|
33
|
+
if (customTesterResult !== undefined) {
|
|
34
|
+
return customTesterResult;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (a instanceof Error && b instanceof Error) {
|
|
38
|
+
return a.message == b.message;
|
|
39
|
+
}
|
|
40
|
+
if (Object.is(a, b)) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
if (a === null || b === null) {
|
|
44
|
+
return a === b;
|
|
45
|
+
}
|
|
46
|
+
var className = Object.prototype.toString.call(a);
|
|
47
|
+
if (className != Object.prototype.toString.call(b)) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
switch (className) {
|
|
51
|
+
case '[object Boolean]':
|
|
52
|
+
case '[object String]':
|
|
53
|
+
case '[object Number]':
|
|
54
|
+
if (typeof a !== typeof b) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
else if (typeof a !== 'object' && typeof b !== 'object') {
|
|
58
|
+
return Object.is(a, b);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
return Object.is(a.valueOf(), b.valueOf());
|
|
62
|
+
}
|
|
63
|
+
case '[object Date]':
|
|
64
|
+
return +a == +b;
|
|
65
|
+
case '[object RegExp]':
|
|
66
|
+
return a.source === b.source && a.flags === b.flags;
|
|
67
|
+
}
|
|
68
|
+
if (typeof a !== 'object' || typeof b !== 'object') {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
if (isDomNode(a) && isDomNode(b)) {
|
|
72
|
+
return a.isEqualNode(b);
|
|
73
|
+
}
|
|
74
|
+
var length = aStack.length;
|
|
75
|
+
while (length--) {
|
|
76
|
+
if (aStack[length] === a) {
|
|
77
|
+
return bStack[length] === b;
|
|
78
|
+
}
|
|
79
|
+
else if (bStack[length] === b) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
aStack.push(a);
|
|
84
|
+
bStack.push(b);
|
|
85
|
+
var size = 0;
|
|
86
|
+
if (className == '[object Array]') {
|
|
87
|
+
size = a.length;
|
|
88
|
+
if (size !== b.length) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
while (size--) {
|
|
92
|
+
result = eq(a[size], b[size], aStack, bStack, customTesters, hasKey);
|
|
93
|
+
if (!result) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
var aKeys = keys(a, className == '[object Array]', hasKey), key;
|
|
99
|
+
size = aKeys.length;
|
|
100
|
+
if (keys(b, className == '[object Array]', hasKey).length !== size) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
while (size--) {
|
|
104
|
+
key = aKeys[size];
|
|
105
|
+
result =
|
|
106
|
+
hasKey(b, key) &&
|
|
107
|
+
eq(a[key], b[key], aStack, bStack, customTesters, hasKey);
|
|
108
|
+
if (!result) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
aStack.pop();
|
|
113
|
+
bStack.pop();
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
function keys(obj, isArray, hasKey) {
|
|
117
|
+
var allKeys = (function (o) {
|
|
118
|
+
var keys = [];
|
|
119
|
+
for (var key in o) {
|
|
120
|
+
if (hasKey(o, key)) {
|
|
121
|
+
keys.push(key);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return keys.concat(Object.getOwnPropertySymbols(o).filter(symbol => Object.getOwnPropertyDescriptor(o, symbol)
|
|
125
|
+
.enumerable));
|
|
126
|
+
})(obj);
|
|
127
|
+
if (!isArray) {
|
|
128
|
+
return allKeys;
|
|
129
|
+
}
|
|
130
|
+
var extraKeys = [];
|
|
131
|
+
if (allKeys.length === 0) {
|
|
132
|
+
return allKeys;
|
|
133
|
+
}
|
|
134
|
+
for (var x = 0; x < allKeys.length; x++) {
|
|
135
|
+
if (typeof allKeys[x] === 'symbol' || !allKeys[x].match(/^[0-9]+$/)) {
|
|
136
|
+
extraKeys.push(allKeys[x]);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return extraKeys;
|
|
140
|
+
}
|
|
141
|
+
function hasDefinedKey(obj, key) {
|
|
142
|
+
return hasKey(obj, key) && obj[key] !== undefined;
|
|
143
|
+
}
|
|
144
|
+
function hasKey(obj, key) {
|
|
145
|
+
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
146
|
+
}
|
|
147
|
+
function isA(typeName, value) {
|
|
148
|
+
return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
|
|
149
|
+
}
|
|
150
|
+
exports.isA = isA;
|
|
151
|
+
function isDomNode(obj) {
|
|
152
|
+
return (obj !== null &&
|
|
153
|
+
typeof obj === 'object' &&
|
|
154
|
+
typeof obj.nodeType === 'number' &&
|
|
155
|
+
typeof obj.nodeName === 'string' &&
|
|
156
|
+
typeof obj.isEqualNode === 'function');
|
|
157
|
+
}
|
|
158
|
+
function fnNameFor(func) {
|
|
159
|
+
if (func.name) {
|
|
160
|
+
return func.name;
|
|
161
|
+
}
|
|
162
|
+
const matches = functionToString
|
|
163
|
+
.call(func)
|
|
164
|
+
.match(/^(?:async)?\s*function\s*\*?\s*([\w$]+)\s*\(/);
|
|
165
|
+
return matches ? matches[1] : '<anonymous>';
|
|
166
|
+
}
|
|
167
|
+
exports.fnNameFor = fnNameFor;
|
|
168
|
+
function isUndefined(obj) {
|
|
169
|
+
return obj === void 0;
|
|
170
|
+
}
|
|
171
|
+
exports.isUndefined = isUndefined;
|
|
172
|
+
function getPrototype(obj) {
|
|
173
|
+
if (Object.getPrototypeOf) {
|
|
174
|
+
return Object.getPrototypeOf(obj);
|
|
175
|
+
}
|
|
176
|
+
if (obj.constructor.prototype == obj) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
return obj.constructor.prototype;
|
|
180
|
+
}
|
|
181
|
+
function hasProperty(obj, property) {
|
|
182
|
+
if (!obj) {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
if (Object.prototype.hasOwnProperty.call(obj, property)) {
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
return hasProperty(getPrototype(obj), property);
|
|
189
|
+
}
|
|
190
|
+
exports.hasProperty = hasProperty;
|
|
191
|
+
const IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@';
|
|
192
|
+
const IS_SET_SENTINEL = '@@__IMMUTABLE_SET__@@';
|
|
193
|
+
const IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@';
|
|
194
|
+
function isImmutableUnorderedKeyed(maybeKeyed) {
|
|
195
|
+
return !!(maybeKeyed &&
|
|
196
|
+
maybeKeyed[IS_KEYED_SENTINEL] &&
|
|
197
|
+
!maybeKeyed[IS_ORDERED_SENTINEL]);
|
|
198
|
+
}
|
|
199
|
+
exports.isImmutableUnorderedKeyed = isImmutableUnorderedKeyed;
|
|
200
|
+
function isImmutableUnorderedSet(maybeSet) {
|
|
201
|
+
return !!(maybeSet &&
|
|
202
|
+
maybeSet[IS_SET_SENTINEL] &&
|
|
203
|
+
!maybeSet[IS_ORDERED_SENTINEL]);
|
|
204
|
+
}
|
|
205
|
+
exports.isImmutableUnorderedSet = isImmutableUnorderedSet;
|
|
@@ -10,9 +10,15 @@ async function condition(el, gte, lte, eq) {
|
|
|
10
10
|
value: children.length
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
|
-
function toHaveChildrenFn(received, options = {}) {
|
|
13
|
+
function toHaveChildrenFn(received, size, options = {}) {
|
|
14
14
|
const isNot = this.isNot;
|
|
15
15
|
const { expectation = 'children', verb = 'have' } = this;
|
|
16
|
+
if (typeof size === 'number') {
|
|
17
|
+
options.eq = size;
|
|
18
|
+
}
|
|
19
|
+
else if (typeof size === 'object') {
|
|
20
|
+
options = { ...options, ...size };
|
|
21
|
+
}
|
|
16
22
|
const eq = options.eq;
|
|
17
23
|
const gte = options.gte || 1;
|
|
18
24
|
const lte = options.lte || 0;
|
|
@@ -27,7 +33,8 @@ function toHaveChildrenFn(received, options = {}) {
|
|
|
27
33
|
}, isNot, options);
|
|
28
34
|
utils_1.updateElementsArray(pass, received, el);
|
|
29
35
|
const error = utils_1.numberError(gte, lte, eq);
|
|
30
|
-
const
|
|
36
|
+
const expected = utils_1.wrapExpectedWithArray(el, children, error);
|
|
37
|
+
const message = utils_1.enhanceError(el, expected, children, this, verb, expectation, '', options);
|
|
31
38
|
return {
|
|
32
39
|
pass,
|
|
33
40
|
message: () => message
|