expect-webdriverio 6.0.4 → 6.0.6
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 +25 -22
- package/lib/matchers/asymmetrics/oneOf.js +6 -0
- package/lib/matchers/element/toHaveAttribute.js +2 -2
- package/lib/matchers/element/toHaveElementProperty.js +2 -2
- package/lib/matchers/modifiers/some.js +1 -1
- package/lib/utils.js +3 -3
- package/package.json +3 -3
- package/types/expect-webdriverio.d.ts +4 -1
package/README.md
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
# expect-webdriverio [](https://github.com/webdriverio/expect-webdriverio/actions/workflows/test.yml)
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
###### [API](docs/API.md) | [TypeScript / JS Autocomplete](docs/Types.md) | [Examples](docs/Examples.md) | [Extending Matchers](docs/CustomMatchers.md)
|
|
5
4
|
|
|
6
|
-
> [WebdriverIO](https://webdriver.io/)
|
|
5
|
+
> [WebdriverIO](https://webdriver.io/) assertion library inspired by [expect](https://www.npmjs.com/package/expect)
|
|
7
6
|
|
|
8
7
|
## Key Features
|
|
9
8
|
|
|
10
|
-
- [Waits](#default-options) for
|
|
11
|
-
-
|
|
9
|
+
- [Waits](#default-options) for expectations to succeed
|
|
10
|
+
- Supports single element `$()` & multiple elements `$$()`
|
|
12
11
|
- Detailed [error messages](#error-messages)
|
|
13
|
-
- Works in Mocha, Cucumber, Jest, Jasmine
|
|
14
|
-
-
|
|
12
|
+
- Works in Mocha, Cucumber, Jest, and Jasmine
|
|
13
|
+
- Built-in [types](docs/Types.md) for TypeScript and JS autocompletion
|
|
15
14
|
|
|
16
15
|
## Installation
|
|
17
16
|
|
|
@@ -22,24 +21,28 @@
|
|
|
22
21
|
- **Cucumber**: `npm install @wdio/cucumber-framework`
|
|
23
22
|
- **Jest**: No adapter needed — see [Jest Framework section](docs/Framework.md#jest)
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
**Note:** [WebdriverIO](https://github.com/webdriverio/webdriverio) `v9.0.0` or higher is required!
|
|
26
25
|
|
|
27
26
|
## Usage
|
|
28
27
|
|
|
29
28
|
### Using WebdriverIO Testrunner
|
|
30
29
|
|
|
31
|
-
If you run your tests through the [WDIO testrunner](https://webdriver.io/docs/clioptions) no additional setup is needed. WebdriverIO
|
|
30
|
+
If you run your tests through the [WDIO testrunner](https://webdriver.io/docs/clioptions), no additional setup is needed. WebdriverIO initializes `expect-webdriverio` and makes `expect` available in the global scope so you can use it directly in your tests:
|
|
32
31
|
|
|
33
32
|
```js
|
|
34
|
-
|
|
35
|
-
await expect(
|
|
33
|
+
await expect($('button')).toBeDisplayed()
|
|
34
|
+
await expect($$('buttons')).toBeDisplayed()
|
|
36
35
|
```
|
|
37
36
|
|
|
38
|
-
See more [Examples](docs/Examples.md)
|
|
37
|
+
See more [Examples](docs/Examples.md).
|
|
38
|
+
|
|
39
|
+
#### Local & Browser Runners
|
|
40
|
+
- **Local Runner**: Fully compatible. You can leverage your test framework adapter as mentioned above.
|
|
41
|
+
- **Browser Runner**: Designed for component frameworks like React, Preact, Vue.js, Svelte, and SolidJS, with a few known limitations. For details, see the [Browser Runner Framework section](docs/Framework.md#browser-runner).
|
|
39
42
|
|
|
40
|
-
### Using in
|
|
43
|
+
### Using in Standalone Mode
|
|
41
44
|
|
|
42
|
-
If you
|
|
45
|
+
If you use WebdriverIO in standalone mode (without `@wdio/globals`), make sure you import `expect-webdriverio` before using it anywhere.
|
|
43
46
|
|
|
44
47
|
```js
|
|
45
48
|
import { remote } from 'webdriverio'
|
|
@@ -63,24 +66,24 @@ import { expect } from 'expect-webdriverio'
|
|
|
63
66
|
|
|
64
67
|
## API
|
|
65
68
|
|
|
66
|
-
Please see [API
|
|
69
|
+
Please see the [API documentation](docs/API.md).
|
|
67
70
|
|
|
68
|
-
## Error
|
|
71
|
+
## Error Messages
|
|
69
72
|
|
|
70
73
|
Error messages are informative out of the box and contain:
|
|
71
74
|
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
+
- Full element selector, like `$('form')`
|
|
76
|
+
- Actual and expected values
|
|
77
|
+
- Highlighted differences (text assertions)
|
|
75
78
|
|
|
76
79
|

|
|
77
80
|

|
|
78
81
|
|
|
79
|
-
## What's
|
|
82
|
+
## What's Next?
|
|
80
83
|
|
|
81
|
-
First of all, **feel free to raise an issue with your suggestions or help with
|
|
84
|
+
First of all, **feel free to raise an issue with your suggestions or help with PRs!**
|
|
82
85
|
|
|
83
86
|
### Planned
|
|
84
87
|
|
|
85
|
-
-
|
|
86
|
-
-
|
|
88
|
+
- Cookie matchers
|
|
89
|
+
- Multiremote support (in progress)
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { compareTextWithArray } from '../../utils.js';
|
|
2
2
|
import { WdioAsymmetricMatchers } from './asymmetricsUtils.js';
|
|
3
|
+
const ONE_OF_TAG = 'expect-webdriverio.oneOf';
|
|
4
|
+
const ONE_OF_SYMBOL = Symbol.for(ONE_OF_TAG);
|
|
3
5
|
export class OneOfMatcher extends WdioAsymmetricMatchers {
|
|
6
|
+
[ONE_OF_SYMBOL] = true;
|
|
4
7
|
options = {};
|
|
5
8
|
constructor(...sample) {
|
|
6
9
|
super(sample);
|
|
@@ -49,3 +52,6 @@ export class OneOfMatcher extends WdioAsymmetricMatchers {
|
|
|
49
52
|
export function oneOf(...sample) {
|
|
50
53
|
return new OneOfMatcher(...sample);
|
|
51
54
|
}
|
|
55
|
+
export function isOneOfMatcher(oneOfMatcher) {
|
|
56
|
+
return oneOfMatcher instanceof OneOfMatcher || oneOfMatcher?.[ONE_OF_SYMBOL] === true;
|
|
57
|
+
}
|
|
@@ -3,7 +3,7 @@ import { executeCommandWithStrategy } from '../../util/executeCommand.js';
|
|
|
3
3
|
import { compareText, enhanceError, isAsymmetricMatcher, waitUntil, wrapExpectedWithArray } from '../../utils.js';
|
|
4
4
|
import { expect as wdioExpect } from '../../index.js';
|
|
5
5
|
import { buildWdioAsymmetricMatchersWithOptions } from '../asymmetrics/asymmetricsUtils.js';
|
|
6
|
-
import {
|
|
6
|
+
import { isOneOfMatcher } from '../asymmetrics/oneOf.js';
|
|
7
7
|
async function conditionAttributeValueMatchWithExpected(el, attribute, expectedValue, options) {
|
|
8
8
|
const attributeValue = await el.getAttribute(attribute);
|
|
9
9
|
if (typeof attributeValue !== 'string' || expectedValue === undefined || expectedValue === null) {
|
|
@@ -12,7 +12,7 @@ async function conditionAttributeValueMatchWithExpected(el, attribute, expectedV
|
|
|
12
12
|
}
|
|
13
13
|
return { success: attributeValue === expectedValue, actual: attributeValue };
|
|
14
14
|
}
|
|
15
|
-
else if (expectedValue
|
|
15
|
+
else if (isOneOfMatcher(expectedValue)) {
|
|
16
16
|
return { success: expectedValue.asymmetricMatch(attributeValue), actual: attributeValue };
|
|
17
17
|
}
|
|
18
18
|
return compareText(attributeValue, expectedValue, options);
|
|
@@ -3,7 +3,7 @@ import { executeCommandWithStrategy } from '../../util/executeCommand.js';
|
|
|
3
3
|
import { expect as wdioExpect } from '../../index.js';
|
|
4
4
|
import { compareText, enhanceError, isAsymmetricMatcher, waitUntil, wrapExpectedWithArray } from '../../utils.js';
|
|
5
5
|
import { buildWdioAsymmetricMatchersWithOptions } from '../asymmetrics/asymmetricsUtils.js';
|
|
6
|
-
import {
|
|
6
|
+
import { isOneOfMatcher } from '../asymmetrics/oneOf.js';
|
|
7
7
|
async function condition(el, property, expectedValue, options = DEFAULT_OPTIONS) {
|
|
8
8
|
const { asString = false } = options;
|
|
9
9
|
const propertyValue = await el.getProperty(property);
|
|
@@ -13,7 +13,7 @@ async function condition(el, property, expectedValue, options = DEFAULT_OPTIONS)
|
|
|
13
13
|
}
|
|
14
14
|
return { success: propertyValue === expectedValue, actual: propertyValue };
|
|
15
15
|
}
|
|
16
|
-
else if (expectedValue
|
|
16
|
+
else if (isOneOfMatcher(expectedValue)) {
|
|
17
17
|
return { success: expectedValue.asymmetricMatch(propertyValue), actual: propertyValue };
|
|
18
18
|
}
|
|
19
19
|
return compareText(propertyValue.toString(), expectedValue, options);
|
package/lib/utils.js
CHANGED
|
@@ -5,7 +5,7 @@ import { executeCommandWithStrategy } from './util/executeCommand.js';
|
|
|
5
5
|
import { enhanceError, enhanceErrorBe } from './util/formatMessage.js';
|
|
6
6
|
import { waitUntil } from './util/waitUntil.js';
|
|
7
7
|
import { DEFAULT_FEATURE_FLAGS } from './constants.js';
|
|
8
|
-
import { OneOfMatcher } from './matchers/asymmetrics/oneOf.js';
|
|
8
|
+
import { isOneOfMatcher, OneOfMatcher } from './matchers/asymmetrics/oneOf.js';
|
|
9
9
|
export function isJasmineStringAsymmetricMatcher(expected) {
|
|
10
10
|
return isAsymmetricMatcher(expected) && !('toAsymmetricMatcher' in expected) && 'jasmineToString' in expected && typeof expected.jasmineToString === 'function';
|
|
11
11
|
}
|
|
@@ -88,7 +88,7 @@ export const compareTextOrArray = (actualText, expectedTexts, options) => {
|
|
|
88
88
|
return { actual: actualText, success: false };
|
|
89
89
|
}
|
|
90
90
|
if (Array.isArray(expectedTexts)) {
|
|
91
|
-
if (expectedTexts.some((expected) => expected
|
|
91
|
+
if (expectedTexts.some((expected) => isOneOfMatcher(expected))) {
|
|
92
92
|
throw new Error('OneOf is not supported in array under legacy behavior. Please enable `useToHaveTextStrictMultiElementsCompareStrategy` feature flag to use the new strict index based matching strategy with `expect.oneOf()`.');
|
|
93
93
|
}
|
|
94
94
|
else {
|
|
@@ -96,7 +96,7 @@ export const compareTextOrArray = (actualText, expectedTexts, options) => {
|
|
|
96
96
|
expectedTexts = new OneOfMatcher(...expectedTexts).withOptions(options);
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
-
if (expectedTexts
|
|
99
|
+
if (isOneOfMatcher(expectedTexts)) {
|
|
100
100
|
return { success: expectedTexts.asymmetricMatch(actualText), actual: actualText };
|
|
101
101
|
}
|
|
102
102
|
const compareResults = compareText(actualText, expectedTexts, options);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expect-webdriverio",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.6",
|
|
4
4
|
"author": "Mykola Grybyk <mykola.grybyk@gmail.com>",
|
|
5
5
|
"description": "WebdriverIO Assertion Library",
|
|
6
6
|
"license": "MIT",
|
|
@@ -92,9 +92,9 @@
|
|
|
92
92
|
"@types/mocha": "^10.0.10",
|
|
93
93
|
"@types/node": "^24.13.3",
|
|
94
94
|
"@vitest/coverage-v8": "^4.1.10",
|
|
95
|
-
"@vitest/eslint-plugin": "^1.6.
|
|
95
|
+
"@vitest/eslint-plugin": "^1.6.27",
|
|
96
96
|
"@wdio/eslint": "^0.1.3",
|
|
97
|
-
"@wdio/types": "^9.
|
|
97
|
+
"@wdio/types": "^9.31.1",
|
|
98
98
|
"eslint": "^9.39.5",
|
|
99
99
|
"husky": "^9.1.7",
|
|
100
100
|
"npm-run-all2": "^9.0.3",
|
|
@@ -22,7 +22,7 @@ type ExpectLibExpectationResult = import('expect').ExpectationResult
|
|
|
22
22
|
type ExpectLibMatcherContext = import('expect').MatcherContext
|
|
23
23
|
type MatchersObject = Parameters<typeof import('expect').expect.extend>[0]
|
|
24
24
|
type ExpectLibAnything = ReturnType<typeof expect.any> | ReturnType<typeof expect.anything>
|
|
25
|
-
type WdioSome<T> = import('
|
|
25
|
+
type WdioSome<T> = import('expect-webdriverio/api').WdioSome<T>
|
|
26
26
|
|
|
27
27
|
// Extracted from the expect library, this is the type of the matcher function used in the expect library.
|
|
28
28
|
type RawMatcherFn<Context extends ExpectLibMatcherContext = ExpectLibMatcherContext> = {
|
|
@@ -1274,6 +1274,9 @@ declare module 'expect-webdriverio' {
|
|
|
1274
1274
|
* Required since importing from 'expect-webdriverio' can trigger double initialization.
|
|
1275
1275
|
*/
|
|
1276
1276
|
declare module 'expect-webdriverio/api' {
|
|
1277
|
+
export interface WdioSome<T> {
|
|
1278
|
+
readonly elements: T
|
|
1279
|
+
}
|
|
1277
1280
|
/**
|
|
1278
1281
|
* Quantifier modifier. Wraps a `$$()` result so that the matcher passes
|
|
1279
1282
|
* when at least one element satisfies the condition (∃ semantics).
|