expect-webdriverio 0.1.1-beta.5 → 1.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/README.md +439 -94
- package/jasmine.d.ts +1 -0
- package/lib/addMatchers.js +44 -0
- package/lib/index.js +3 -57
- package/lib/matchers/element/toBeDisplayed.js +1 -3
- package/lib/matchers/element/toBeDisplayedInViewport.js +4 -1
- package/lib/matchers/element/toBeExisting.js +8 -2
- package/lib/matchers.js +3 -3
- package/lib/options.js +3 -3
- package/lib/utils.js +12 -1
- package/package.json +25 -17
- package/types/jest-global.d.ts +1 -2
- package/types/standalone-global.d.ts +9 -0
- package/types/standalone.d.ts +2 -0
package/README.md
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
# expect-webdriverio
|
|
2
2
|
|
|
3
|
+
[](https://travis-ci.org/webdriverio/expect-webdriverio) [](https://codecov.io/gh/webdriverio/expect-webdriverio)
|
|
4
|
+
|
|
5
|
+
###### [TypeScript / JS Autocomplete](/docs/Types.md) | [Examples](docs/Examples.md) | [Extending Matchers](/docs/Extend.md)
|
|
6
|
+
|
|
3
7
|
> [WebdriverIO](https://webdriver.io/) Assertion library inspired by [expect](https://www.npmjs.com/package/expect)
|
|
4
8
|
|
|
5
9
|
## Key Features
|
|
6
10
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
- add your own messages
|
|
11
|
+
- [waits](#default-options) for expectation to succeed
|
|
12
|
+
- detailed [error messages](#error-messages)
|
|
10
13
|
- works in Mocha, Cucumber, Jest, Jasmine
|
|
11
|
-
- builtin types for TypeScript and JS autocompletion
|
|
14
|
+
- builtin [types](docs/Types.md) for TypeScript and JS autocompletion
|
|
12
15
|
|
|
13
16
|
## Installation
|
|
14
17
|
|
|
@@ -22,84 +25,26 @@ NOTE: [WebdriverIO](https://github.com/webdriverio/webdriverio) `v5.16.11` or hi
|
|
|
22
25
|
In your `wdio.conf.js`
|
|
23
26
|
```js
|
|
24
27
|
beforeSession () { // before hook works as well
|
|
25
|
-
// with default options
|
|
26
28
|
require('expect-webdriverio')
|
|
27
|
-
// If you like to override default options
|
|
28
|
-
// require('expect-webdriverio').setOptions({ wait: 9000 })
|
|
29
29
|
},
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
In your test
|
|
33
33
|
```js
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
expect(browser).toHaveTitle('expect-webdriverio', { containing: true })
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('be visible', () => {
|
|
43
|
-
const notVisible = $('body').$$('div')[2].$("not-visible")
|
|
44
|
-
|
|
45
|
-
// wait for 2000ms for expectation to succeed by default
|
|
46
|
-
expect(notVisible).toExist()
|
|
47
|
-
|
|
48
|
-
// override default wait timeout
|
|
49
|
-
expect(notVisible).toBeVisible({ wait: 0 })
|
|
50
|
-
// fails with error
|
|
51
|
-
// Element "$(`body`).$$(`div`)[2].$(`not-visible`)" is not displayed.
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
it('find elements', () => {
|
|
55
|
-
const formInputs = $$('form input')
|
|
56
|
-
|
|
57
|
-
// make sure every form element is enabled
|
|
58
|
-
// waits automatically for formInputs to have at least one element
|
|
59
|
-
expect(formInputs).toBeEnabled({ wait: 5000 })
|
|
60
|
-
|
|
61
|
-
const selectOptions = $$('form select>option')
|
|
62
|
-
|
|
63
|
-
// make sure there is at least one option in select
|
|
64
|
-
expect(selectOptions).toBeElementsArrayOfSize({ gte: 1 })
|
|
65
|
-
// exact match
|
|
66
|
-
expect($$('button')).toBeElementsArrayOfSize(3)
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
it('advanced', () => {
|
|
70
|
-
const myInput = $('input')
|
|
71
|
-
|
|
72
|
-
expect(myInput).toHaveClass('form-control', { message: 'Not a form control!', })
|
|
73
|
-
expect(myInput).toHaveAttribute('class', 'form-control') // alias toHaveAttr
|
|
74
|
-
|
|
75
|
-
expect(myInput).toHaveValueContaining('USER')
|
|
76
|
-
// or pass `containing` as an option
|
|
77
|
-
expect(myInput).toHaveValue('value', 'user', { containing: true, ignoreCase: true })
|
|
78
|
-
|
|
79
|
-
// Simply invert assertions
|
|
80
|
-
expect(myInput).not.toHaveProperty('height', 0)
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it('async mode', async () => {
|
|
84
|
-
const el = await $('el')
|
|
85
|
-
await expect(el).toBePresent() // aliases toBeExisting or toExist
|
|
86
|
-
|
|
87
|
-
// or
|
|
88
|
-
await expect($('el')).toBePresent()
|
|
89
|
-
})
|
|
90
|
-
})
|
|
91
|
-
```
|
|
34
|
+
const $button = $('button')
|
|
35
|
+
expect($button).toBeDisplayed()
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
See more [Examples](docs/Examples.md)
|
|
92
39
|
|
|
93
40
|
## API
|
|
94
41
|
|
|
95
|
-
See available [Matchers](https://github.com/
|
|
42
|
+
See available [Matchers](https://github.com/webdriverio/expect-webdriverio/blob/master/types/expect-webdriverio.d.ts#L64)
|
|
96
43
|
|
|
97
|
-
Besides of `expect-webdriverio`
|
|
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.
|
|
98
45
|
|
|
99
46
|
## Default Options
|
|
100
47
|
|
|
101
|
-
Options will be extended soon to provide more flexibility!
|
|
102
|
-
|
|
103
48
|
```js
|
|
104
49
|
{
|
|
105
50
|
wait: 2000, // ms to wait for expectation to succeed
|
|
@@ -107,44 +52,444 @@ Options will be extended soon to provide more flexibility!
|
|
|
107
52
|
}
|
|
108
53
|
```
|
|
109
54
|
|
|
110
|
-
|
|
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 specifc page.
|
|
100
|
+
|
|
101
|
+
##### Usage
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
browser.url('https://webdriver.io/')
|
|
105
|
+
expect(browser).toHaveUrl('https://webdriver.io')
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### toHaveTitle
|
|
109
|
+
|
|
110
|
+
Checks if website has a specific title.
|
|
111
|
+
|
|
112
|
+
##### Usage
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
browser.url('https://webdriver.io/')
|
|
116
|
+
expect(browser).toHaveTitle('WebdriverIO · Next-gen WebDriver test framework for Node.js')
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Element Matchers
|
|
120
|
+
|
|
121
|
+
### toBeDisplayed
|
|
122
|
+
|
|
123
|
+
Calls [`isDisplayed`](/docs/api/element/isDisplayed.html) on given element.
|
|
124
|
+
|
|
125
|
+
##### Usage
|
|
126
|
+
|
|
127
|
+
```js
|
|
128
|
+
const elem = $('#someElem')
|
|
129
|
+
expect(elem).toBeDisplayed()
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### toBeVisible
|
|
133
|
+
|
|
134
|
+
Same as `toBeDisplayed`.
|
|
135
|
+
|
|
136
|
+
##### Usage
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
const elem = $('#someElem')
|
|
140
|
+
expect(elem).toBeVisible()
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### toExist
|
|
144
|
+
|
|
145
|
+
Calls [`isExisting`](/docs/api/element/isExisting.html) on given element.
|
|
146
|
+
|
|
147
|
+
##### Usage
|
|
148
|
+
|
|
149
|
+
```js
|
|
150
|
+
const elem = $('#someElem')
|
|
151
|
+
expect(elem).toExist()
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### toBePresent
|
|
155
|
+
|
|
156
|
+
Same as `toExist`.
|
|
157
|
+
|
|
158
|
+
##### Usage
|
|
159
|
+
|
|
160
|
+
```js
|
|
161
|
+
const elem = $('#someElem')
|
|
162
|
+
expect(elem).toBePresent()
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### toBeExisting
|
|
166
|
+
|
|
167
|
+
Same as `toExist`.
|
|
168
|
+
|
|
169
|
+
##### Usage
|
|
170
|
+
|
|
171
|
+
```js
|
|
172
|
+
const elem = $('#someElem')
|
|
173
|
+
expect(elem).toBeExisting()
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### toBeFocused
|
|
177
|
+
|
|
178
|
+
Checks if element has focus. This assertion only works in a web context.
|
|
179
|
+
|
|
180
|
+
##### Usage
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
const elem = $('#someElem')
|
|
184
|
+
expect(elem).toBeFocused()
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### toHaveAttribute
|
|
188
|
+
|
|
189
|
+
Checks if an element has a certain attribute with a specific value.
|
|
190
|
+
|
|
191
|
+
##### Usage
|
|
192
|
+
|
|
193
|
+
```js
|
|
194
|
+
const myInput = $('input')
|
|
195
|
+
expect(myInput).toHaveAttribute('class', 'form-control')
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### toHaveAttr
|
|
199
|
+
|
|
200
|
+
Same as `toHaveAttribute`.
|
|
201
|
+
|
|
202
|
+
##### Usage
|
|
203
|
+
|
|
204
|
+
```js
|
|
205
|
+
const myInput = $('input')
|
|
206
|
+
expect(myInput).toHaveAttr('class', 'form-control')
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### toHaveAttributeContaining
|
|
210
|
+
|
|
211
|
+
Checks if an element has a certain attribute that contains a value.
|
|
212
|
+
|
|
213
|
+
##### Usage
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
const myInput = $('input')
|
|
217
|
+
expect(myInput).toHaveAttributeContaining('class', 'form')
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### toHaveAttrContaining
|
|
221
|
+
|
|
222
|
+
Same as `toHaveAttributeContaining`.
|
|
223
|
+
|
|
224
|
+
##### Usage
|
|
225
|
+
|
|
226
|
+
```js
|
|
227
|
+
const myInput = $('input')
|
|
228
|
+
expect(myInput).toHaveAttrContaining('class', 'form')
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### toHaveClass
|
|
232
|
+
|
|
233
|
+
Checks if an element has a certain class name.
|
|
234
|
+
|
|
235
|
+
##### Usage
|
|
236
|
+
|
|
237
|
+
```js
|
|
238
|
+
const myInput = $('input')
|
|
239
|
+
expect(myInput).toHaveClass('form-control', { message: 'Not a form control!', })
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### toHaveClassContaining
|
|
243
|
+
|
|
244
|
+
Checks if an element has a certain class name that contains provided value.
|
|
245
|
+
|
|
246
|
+
##### Usage
|
|
247
|
+
|
|
248
|
+
```js
|
|
249
|
+
const myInput = $('input')
|
|
250
|
+
expect(myInput).toHaveClassContaining('form')
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### toHaveProperty
|
|
254
|
+
|
|
255
|
+
Checks if an element has a certain property.
|
|
256
|
+
|
|
257
|
+
##### Usage
|
|
258
|
+
|
|
259
|
+
```js
|
|
260
|
+
const elem = $('#elem')
|
|
261
|
+
expect(elem).toHaveProperty('height', 23)
|
|
262
|
+
expect(elem).not.toHaveProperty('height', 0)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### toHaveValue
|
|
111
266
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
267
|
+
Checks if an input element has a certain value.
|
|
268
|
+
|
|
269
|
+
##### Usage
|
|
270
|
+
|
|
271
|
+
```js
|
|
272
|
+
const myInput = $('input')
|
|
273
|
+
expect(myInput).toHaveValue('user', { ignoreCase: true })
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### toHaveValueContaining
|
|
277
|
+
|
|
278
|
+
Checks if an input element contains a certain value.
|
|
279
|
+
|
|
280
|
+
##### Usage
|
|
281
|
+
|
|
282
|
+
```js
|
|
283
|
+
const myInput = $('input')
|
|
284
|
+
expect(myInput).toHaveValue('us')
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### toBeClickable
|
|
288
|
+
|
|
289
|
+
Checks if an element can be clicked by calling [`isClickable`](/docs/api/element/isClickable.html) on the element.
|
|
290
|
+
|
|
291
|
+
##### Usage
|
|
292
|
+
|
|
293
|
+
```js
|
|
294
|
+
const elem = $('#elem')
|
|
295
|
+
expect(elem).toBeClickable()
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### toBeDisabled
|
|
299
|
+
|
|
300
|
+
Checks if an element is disabled by calling [`isEnabled`](/docs/api/element/isEnabled.html) on the element.
|
|
301
|
+
|
|
302
|
+
##### Usage
|
|
303
|
+
|
|
304
|
+
```js
|
|
305
|
+
const elem = $('#elem')
|
|
306
|
+
expect(elem).toBeDisabled()
|
|
307
|
+
// same as
|
|
308
|
+
expect(elem).not.toBeEnabled()
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### toBeEnabled
|
|
312
|
+
|
|
313
|
+
Checks if an element is enabled by calling [`isEnabled`](/docs/api/element/isEnabled.html) on the element.
|
|
314
|
+
|
|
315
|
+
##### Usage
|
|
316
|
+
|
|
317
|
+
```js
|
|
318
|
+
const elem = $('#elem')
|
|
319
|
+
expect(elem).toBeEnabled()
|
|
320
|
+
// same as
|
|
321
|
+
expect(elem).not.toBeDisabled()
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### toBeSelected
|
|
325
|
+
|
|
326
|
+
Checks if an element is enabled by calling [`isSelected`](/docs/api/element/isSelected.html) on the element.
|
|
327
|
+
|
|
328
|
+
##### Usage
|
|
329
|
+
|
|
330
|
+
```js
|
|
331
|
+
const elem = $('#elem')
|
|
332
|
+
expect(elem).toBeSelected()
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### toBeChecked
|
|
336
|
+
|
|
337
|
+
Same as `toBeSelected`.
|
|
338
|
+
|
|
339
|
+
##### Usage
|
|
340
|
+
|
|
341
|
+
```js
|
|
342
|
+
const elem = $('#elem')
|
|
343
|
+
expect(elem).toBeChecked()
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### toHaveHref
|
|
347
|
+
|
|
348
|
+
Checks if link element has a specifc link target.
|
|
349
|
+
|
|
350
|
+
##### Usage
|
|
351
|
+
|
|
352
|
+
```js
|
|
353
|
+
const link = $('a')
|
|
354
|
+
expect(link).toHaveHref('https://webdriver.io')
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### toHaveLink
|
|
358
|
+
|
|
359
|
+
Same as `toHaveHref`.
|
|
360
|
+
|
|
361
|
+
##### Usage
|
|
362
|
+
|
|
363
|
+
```js
|
|
364
|
+
const link = $('a')
|
|
365
|
+
expect(link).toHaveLink('https://webdriver.io')
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### toHaveHrefContaining
|
|
369
|
+
|
|
370
|
+
Checks if link element contains a specifc link target.
|
|
371
|
+
|
|
372
|
+
##### Usage
|
|
373
|
+
|
|
374
|
+
```js
|
|
375
|
+
const link = $('a')
|
|
376
|
+
expect(link).toHaveHrefContaining('webdriver.io')
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### toHaveLinkContaining
|
|
380
|
+
|
|
381
|
+
Same as `toHaveHrefContaining`.
|
|
382
|
+
|
|
383
|
+
##### Usage
|
|
384
|
+
|
|
385
|
+
```js
|
|
386
|
+
const link = $('a')
|
|
387
|
+
expect(link).toHaveLinkContaining('webdriver.io')
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### toHaveId
|
|
391
|
+
|
|
392
|
+
Checks if element has a specific `id` attribute.
|
|
393
|
+
|
|
394
|
+
##### Usage
|
|
395
|
+
|
|
396
|
+
```js
|
|
397
|
+
const elem = $('#elem')
|
|
398
|
+
expect(elem).toHaveId('elem')
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### toHaveText
|
|
402
|
+
|
|
403
|
+
Checks if element has a specific text.
|
|
404
|
+
|
|
405
|
+
##### Usage
|
|
406
|
+
|
|
407
|
+
```js
|
|
408
|
+
browser.url('https://webdriver.io/')
|
|
409
|
+
const elem = $('.tagline')
|
|
410
|
+
expect(elem).toHaveText('Next-gen WebDriver test framework for Node.js')
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### toHaveTextContaining
|
|
414
|
+
|
|
415
|
+
Checks if element contains a specific text.
|
|
416
|
+
|
|
417
|
+
##### Usage
|
|
418
|
+
|
|
419
|
+
```js
|
|
420
|
+
browser.url('https://webdriver.io/')
|
|
421
|
+
const elem = $('.tagline')
|
|
422
|
+
expect(elem).toHaveTextContaining('WebDriver test framework')
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### toBeDisplayedInViewport
|
|
426
|
+
|
|
427
|
+
Checks if an element is within the viewport by calling [`isDisplayedInViewport`](/docs/api/element/isDisplayedInViewport.html) on the element.
|
|
428
|
+
|
|
429
|
+
##### Usage
|
|
430
|
+
|
|
431
|
+
```js
|
|
432
|
+
const elem = $('#elem')
|
|
433
|
+
expect(elem).toBeDisplayedInViewport()
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### toBeVisibleInViewport
|
|
437
|
+
|
|
438
|
+
Same as `toBeDisplayedInViewport`.
|
|
439
|
+
|
|
440
|
+
##### Usage
|
|
441
|
+
|
|
442
|
+
```js
|
|
443
|
+
const elem = $('#elem')
|
|
444
|
+
expect(elem).toBeVisibleInViewport()
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### toHaveChildren
|
|
448
|
+
|
|
449
|
+
Checks amount of fetched elements using [`$$`](/docs/api/browser/$$.html) command.
|
|
450
|
+
|
|
451
|
+
##### Usage
|
|
452
|
+
|
|
453
|
+
```js
|
|
454
|
+
const elems = $$('div')
|
|
455
|
+
expect(elems).toHaveChildren({ gte: 10 })
|
|
456
|
+
// same as
|
|
457
|
+
assert.ok(elems.length >= 10)
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### toBeElementsArrayOfSize
|
|
461
|
+
|
|
462
|
+
Same as `toHaveChildren`.
|
|
463
|
+
|
|
464
|
+
##### Usage
|
|
465
|
+
|
|
466
|
+
```js
|
|
467
|
+
const elems = $$('div')
|
|
468
|
+
expect(elems).toBeElementsArrayOfSize({ gte: 10 })
|
|
469
|
+
// same as
|
|
470
|
+
assert.ok(elems.length >= 10)
|
|
471
|
+
```
|
|
116
472
|
|
|
117
473
|
## Error messages
|
|
118
474
|
|
|
119
475
|
Error messages are informative out of the box and contain:
|
|
120
476
|
|
|
121
|
-
- full element selector
|
|
122
|
-
- property type to be verified
|
|
477
|
+
- full element selector, like `$('form').$('input')`
|
|
123
478
|
- actual and expected values
|
|
124
479
|
- highlight the difference (texts assertions)
|
|
125
480
|
|
|
126
|
-
|
|
127
|
-

|
|
482
|
+

|
|
483
|
+

|
|
128
484
|
|
|
129
485
|
## What's next?
|
|
130
486
|
|
|
131
487
|
First of all, **feel free to raise an issue with your suggestions or help with PR!**
|
|
132
488
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
### Almost there
|
|
136
|
-
|
|
137
|
-
- boilerplate projects
|
|
138
|
-
|
|
139
|
-
### Coming soon...
|
|
140
|
-
|
|
141
|
-
- css
|
|
142
|
-
- size
|
|
143
|
-
- cookie / localStorage ?
|
|
144
|
-
- docs
|
|
145
|
-
|
|
146
|
-
### Also planned
|
|
489
|
+
### Planned
|
|
147
490
|
|
|
148
|
-
-
|
|
149
|
-
-
|
|
491
|
+
- css matcher
|
|
492
|
+
- size matcher
|
|
493
|
+
- cookie / localStorage matchers?
|
|
494
|
+
- text regex matchers
|
|
150
495
|
- multiremote support (if requested)
|
package/jasmine.d.ts
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
let expectLib;
|
|
4
|
+
exports.addMatchers = () => {
|
|
5
|
+
if (global.expect === undefined) {
|
|
6
|
+
if (!exports.loadExpect()) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
global.expect = expectLib;
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
expectLib = global.expect;
|
|
13
|
+
}
|
|
14
|
+
if (!global.expect.extend && !exports.isJasmine()) {
|
|
15
|
+
if (!exports.loadExpect()) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
global.expectWdio = expectLib;
|
|
19
|
+
console.warn('Warning! Unsupported expect lib is used.\n' +
|
|
20
|
+
"Only Jasmine >= 3.3.0 and Jest's expect are supported.\n" +
|
|
21
|
+
"expect-webdriverio is assigned to global.expectWdio");
|
|
22
|
+
}
|
|
23
|
+
require('./options').setDefaultOptions;
|
|
24
|
+
const matchers = require('./matchers').default;
|
|
25
|
+
if (expectLib.extend) {
|
|
26
|
+
return expectLib.extend({ ...matchers });
|
|
27
|
+
}
|
|
28
|
+
expectLib = global.jasmine;
|
|
29
|
+
return expectLib.getEnv().beforeAll(function addExpectWebdriverIOMatchers() {
|
|
30
|
+
expectLib.addMatchers({ ...matchers });
|
|
31
|
+
expectLib.addAsyncMatchers({ ...matchers });
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
exports.isJasmine = () => {
|
|
35
|
+
return global.jasmine && global.expect && global.expectAsync && global.jasmine.getEnv && global.jasmine.addMatchers && global.jasmine.addAsyncMatchers;
|
|
36
|
+
};
|
|
37
|
+
exports.loadExpect = () => {
|
|
38
|
+
try {
|
|
39
|
+
return expectLib = require('expect');
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
return console.error('Failed to load expect package. Make sure it has been installed: npm i expect');
|
|
43
|
+
}
|
|
44
|
+
};
|
package/lib/index.js
CHANGED
|
@@ -1,59 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if (global.expect === undefined) {
|
|
7
|
-
if (!loadExpect()) {
|
|
8
|
-
return;
|
|
9
|
-
}
|
|
10
|
-
global.expect = expectLib;
|
|
11
|
-
}
|
|
12
|
-
else {
|
|
13
|
-
expectLib = global.expect;
|
|
14
|
-
}
|
|
15
|
-
if (!global.expect.extend && !isJasmine()) {
|
|
16
|
-
if (!loadExpect()) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
global.ExpectWebdriverIO = expectLib;
|
|
20
|
-
console.warn('Warning! Unsupported expect lib is used.\n' +
|
|
21
|
-
"Only Jasmine >= 3.3.0 and Jest's expect are supported.\n" +
|
|
22
|
-
"expect-webdriverio is assigned to global.ExpectWebdriverIO");
|
|
23
|
-
}
|
|
24
|
-
setDefaultOptions = require('./options').setDefaultOptions;
|
|
25
|
-
const matchers = require('./matchers').default;
|
|
26
|
-
if (expectLib.extend) {
|
|
27
|
-
return expectLib.extend({ ...matchers });
|
|
28
|
-
}
|
|
29
|
-
expectLib = global.jasmine;
|
|
30
|
-
let addMatchersFn = 'addMatchers';
|
|
31
|
-
if (!isWdioSyncInstalled()) {
|
|
32
|
-
addMatchersFn = 'addAsyncMatchers';
|
|
33
|
-
}
|
|
34
|
-
return expectLib.getEnv().beforeAll(function addExpectWebdriverIOMatchers() {
|
|
35
|
-
expectLib[addMatchersFn]({ ...matchers });
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
const isJasmine = () => {
|
|
39
|
-
return global.jasmine && global.expect && global.expectAsync && global.jasmine.getEnv && global.jasmine.addMatchers && global.jasmine.addAsyncMatchers;
|
|
40
|
-
};
|
|
41
|
-
const loadExpect = () => {
|
|
42
|
-
try {
|
|
43
|
-
return expectLib = require('expect');
|
|
44
|
-
}
|
|
45
|
-
catch (err) {
|
|
46
|
-
return console.error('Failed to load expect package. Make sure it has been installed: npm i expect');
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
const isWdioSyncInstalled = () => {
|
|
50
|
-
try {
|
|
51
|
-
require('@wdio/sync/package.json').version;
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
catch (_a) {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
extend();
|
|
59
|
-
exports.setOptions = setDefaultOptions;
|
|
3
|
+
const addMatchers_1 = require("./addMatchers");
|
|
4
|
+
addMatchers_1.addMatchers();
|
|
5
|
+
exports.setOptions = require('./options').setDefaultOptions;
|
|
@@ -21,8 +21,6 @@ function toBeDisplayedFn(received, options = {}) {
|
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
function toBeVisible(el, options) {
|
|
24
|
-
|
|
25
|
-
context.expectation = 'visible';
|
|
26
|
-
return toBeDisplayed.call(context, el, options);
|
|
24
|
+
return utils_1.aliasFn.call(this, toBeDisplayed, { expectation: 'visible' }, el, options);
|
|
27
25
|
}
|
|
28
26
|
exports.toBeVisible = toBeVisible;
|
|
@@ -20,4 +20,7 @@ function toBeDisplayedInViewportFn(received, options = {}) {
|
|
|
20
20
|
return result;
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
function toBeVisibleInViewport(el, options) {
|
|
24
|
+
return utils_1.aliasFn.call(this, toBeDisplayedInViewport, { expectation: 'visible in viewport' }, el, options);
|
|
25
|
+
}
|
|
26
|
+
exports.toBeVisibleInViewport = toBeVisibleInViewport;
|
|
@@ -21,5 +21,11 @@ function toExistFn(received, options = {}) {
|
|
|
21
21
|
return result;
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
function toBeExisting(el, options) {
|
|
25
|
+
return utils_1.aliasFn.call(this, toExist, { verb: 'be', expectation: 'existing' }, el, options);
|
|
26
|
+
}
|
|
27
|
+
exports.toBeExisting = toBeExisting;
|
|
28
|
+
function toBePresent(el, options) {
|
|
29
|
+
return utils_1.aliasFn.call(this, toExist, { verb: 'be', expectation: 'present' }, el, options);
|
|
30
|
+
}
|
|
31
|
+
exports.toBePresent = toBePresent;
|
package/lib/matchers.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const matchers = {
|
|
4
|
+
...require('./matchers/browser/toHaveTitle'),
|
|
5
|
+
...require('./matchers/browser/toHaveUrl'),
|
|
6
|
+
...require('./matchers/elements/toBeElementsArrayOfSize'),
|
|
4
7
|
...require('./matchers/element/toBeClickable'),
|
|
5
8
|
...require('./matchers/element/toBeDisabled'),
|
|
6
9
|
...require('./matchers/element/toBeDisplayed'),
|
|
@@ -22,9 +25,6 @@ const matchers = {
|
|
|
22
25
|
...require('./matchers/element/toHaveTextContaining'),
|
|
23
26
|
...require('./matchers/element/toHaveValue'),
|
|
24
27
|
...require('./matchers/element/toHaveValueContaining'),
|
|
25
|
-
...require('./matchers/browser/toHaveTitle'),
|
|
26
|
-
...require('./matchers/browser/toHaveUrl'),
|
|
27
|
-
...require('./matchers/elements/toBeElementsArrayOfSize'),
|
|
28
28
|
};
|
|
29
29
|
Object.keys(matchers).forEach(key => {
|
|
30
30
|
if (key.endsWith('Fn')) {
|
package/lib/options.js
CHANGED
|
@@ -6,10 +6,10 @@ const DEFAULT_OPTIONS = {
|
|
|
6
6
|
};
|
|
7
7
|
let mode = 'jest';
|
|
8
8
|
let expectLib;
|
|
9
|
-
if (global.
|
|
10
|
-
expectLib = global.
|
|
9
|
+
if (global.expectWdio) {
|
|
10
|
+
expectLib = global.expectWdio;
|
|
11
11
|
}
|
|
12
|
-
else if (global.jasmine) {
|
|
12
|
+
else if (global.jasmine && !global.expect.extend) {
|
|
13
13
|
expectLib = global.jasmine;
|
|
14
14
|
mode = 'jasmine';
|
|
15
15
|
}
|
package/lib/utils.js
CHANGED
|
@@ -9,6 +9,7 @@ exports.updateElementsArray = elementsUtil_1.updateElementsArray;
|
|
|
9
9
|
const formatMessage_1 = require("./util/formatMessage");
|
|
10
10
|
exports.enhanceError = formatMessage_1.enhanceError;
|
|
11
11
|
exports.numberError = formatMessage_1.numberError;
|
|
12
|
+
const expectAdapter_1 = require("./util/expectAdapter");
|
|
12
13
|
const config = options_1.getConfig();
|
|
13
14
|
const { options: DEFAULT_OPTIONS } = config;
|
|
14
15
|
const waitUntil = async (condition, isNot = false, { wait = DEFAULT_OPTIONS.wait, interval = DEFAULT_OPTIONS.interval } = {}) => {
|
|
@@ -26,7 +27,10 @@ const waitUntil = async (condition, isNot = false, { wait = DEFAULT_OPTIONS.wait
|
|
|
26
27
|
error = err;
|
|
27
28
|
return false;
|
|
28
29
|
}
|
|
29
|
-
},
|
|
30
|
+
}, {
|
|
31
|
+
timeout: wait,
|
|
32
|
+
interval
|
|
33
|
+
});
|
|
30
34
|
if (error) {
|
|
31
35
|
throw error;
|
|
32
36
|
}
|
|
@@ -88,3 +92,10 @@ exports.compareText = (actual, expected, { ignoreCase = false, trim = false, con
|
|
|
88
92
|
result: actual === expected
|
|
89
93
|
};
|
|
90
94
|
};
|
|
95
|
+
function aliasFn(fn, { verb, expectation } = {}, ...args) {
|
|
96
|
+
const context = expectAdapter_1.getContext(this);
|
|
97
|
+
context.verb = verb;
|
|
98
|
+
context.expectation = expectation;
|
|
99
|
+
return fn.apply(context, args);
|
|
100
|
+
}
|
|
101
|
+
exports.aliasFn = aliasFn;
|
package/package.json
CHANGED
|
@@ -1,39 +1,46 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expect-webdriverio",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"
|
|
7
|
+
"build": "run-s clean compile",
|
|
8
8
|
"clean": "rimraf ./lib",
|
|
9
|
-
"compile": "tsc",
|
|
10
|
-
"
|
|
9
|
+
"compile": "tsc --build tsconfig.build.json",
|
|
10
|
+
"release": "npm run release:patch",
|
|
11
|
+
"release:patch": "np patch",
|
|
12
|
+
"release:minor": "np minor",
|
|
13
|
+
"release:major": "np major",
|
|
14
|
+
"test": "jest"
|
|
11
15
|
},
|
|
12
16
|
"repository": {
|
|
13
17
|
"type": "git",
|
|
14
|
-
"url": "git+https://github.com/
|
|
18
|
+
"url": "git+https://github.com/webdriverio/expect-webdriverio.git"
|
|
15
19
|
},
|
|
16
20
|
"keywords": [
|
|
21
|
+
"expect-webdriverio",
|
|
17
22
|
"expect",
|
|
18
23
|
"webdriverio",
|
|
19
24
|
"wdio"
|
|
20
25
|
],
|
|
21
26
|
"author": "Mykola Grybyk <mykola.grybyk@gmail.com>",
|
|
22
|
-
"license": "
|
|
27
|
+
"license": "MIT",
|
|
23
28
|
"bugs": {
|
|
24
|
-
"url": "https://github.com/
|
|
29
|
+
"url": "https://github.com/webdriverio/expect-webdriverio/issues"
|
|
25
30
|
},
|
|
26
|
-
"homepage": "https://github.com/
|
|
31
|
+
"homepage": "https://github.com/webdriverio/expect-webdriverio#readme",
|
|
27
32
|
"devDependencies": {
|
|
28
|
-
"@types/jest": "^
|
|
29
|
-
"@types/node": "^12.12.
|
|
30
|
-
"
|
|
31
|
-
"
|
|
33
|
+
"@types/jest": "^25.1.4",
|
|
34
|
+
"@types/node": "^12.12.31",
|
|
35
|
+
"codecov": "^3.6.5",
|
|
36
|
+
"husky": "^4.2.3",
|
|
37
|
+
"jest": "^25.2.2",
|
|
38
|
+
"np": "^6.2.0",
|
|
32
39
|
"npm-run-all": "^4.1.5",
|
|
33
|
-
"rimraf": "^3.0.
|
|
34
|
-
"ts-jest": "^
|
|
35
|
-
"typescript": "^3.
|
|
36
|
-
"webdriverio": "^
|
|
40
|
+
"rimraf": "^3.0.2",
|
|
41
|
+
"ts-jest": "^25.2.1",
|
|
42
|
+
"typescript": "^3.8.3",
|
|
43
|
+
"webdriverio": "^6.0.2"
|
|
37
44
|
},
|
|
38
45
|
"types": "types/jest-global.d.ts",
|
|
39
46
|
"husky": {
|
|
@@ -42,6 +49,7 @@
|
|
|
42
49
|
}
|
|
43
50
|
},
|
|
44
51
|
"dependencies": {
|
|
45
|
-
"
|
|
52
|
+
"expect": "^25.2.1",
|
|
53
|
+
"jest-matcher-utils": "^25.1.0"
|
|
46
54
|
}
|
|
47
55
|
}
|
package/types/jest-global.d.ts
CHANGED