expect-webdriverio 5.4.3 → 5.6.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 +1 -1
- package/jasmine-wdio-expect-async.d.ts +22 -0
- package/jasmine.d.ts +23 -2
- package/jest.d.ts +34 -2
- package/lib/matchers/element/toHaveAttribute.js +1 -1
- package/lib/matchers/element/toHaveClass.js +2 -2
- package/lib/matchers/mock/toBeRequestedWith.js +7 -7
- package/lib/matchers/snapshot.js +1 -1
- package/lib/snapshot.js +35 -49
- package/lib/softAssert.js +4 -4
- package/lib/softAssertService.js +2 -0
- package/lib/tsconfig.build.tsbuildinfo +1 -1
- package/lib/utils.js +32 -11
- package/package.json +35 -25
- package/types/expect-global.d.ts +15 -0
- package/types/expect-webdriverio.d.ts +531 -341
- package/types/jest-global.d.ts +0 -10
- package/types/standalone.d.ts +0 -34
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# expect-webdriverio [](https://github.com/webdriverio/expect-webdriverio/actions/workflows/test.yml)
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
###### [API](docs/API.md) | [TypeScript / JS Autocomplete](
|
|
4
|
+
###### [API](docs/API.md) | [TypeScript / JS Autocomplete](docs/Types.md) | [Examples](docs/Examples.md) | [Extending Matchers](docs/CustomMatchers.md)
|
|
5
5
|
|
|
6
6
|
> [WebdriverIO](https://webdriver.io/) Assertion library inspired by [expect](https://www.npmjs.com/package/expect)
|
|
7
7
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/// <reference types="./types/expect-webdriverio.d.ts"/>
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Overrides the default wdio `expect` for Jasmine case specifically since the `expect` is now completely asynchronous which is not the case under Jest or standalone.
|
|
5
|
+
*/
|
|
6
|
+
declare namespace ExpectWebdriverIO {
|
|
7
|
+
interface Expect extends ExpectWebdriverIO.AsymmetricMatchers, ExpectLibInverse<ExpectWebdriverIO.InverseAsymmetricMatchers>, WdioExpect {
|
|
8
|
+
/**
|
|
9
|
+
* The `expect` function is used every time you want to test a value.
|
|
10
|
+
* You will rarely call `expect` by itself.
|
|
11
|
+
*
|
|
12
|
+
* expect function declaration contains two generics:
|
|
13
|
+
* - T: the type of the actual value, e.g. any type, not just WebdriverIO.Browser or WebdriverIO.Element
|
|
14
|
+
* - R: the type of the return value, e.g. Promise<void> or void
|
|
15
|
+
*
|
|
16
|
+
* Note: The function must stay here in the namespace to overwrite correctly the expect function from the expect library.
|
|
17
|
+
*
|
|
18
|
+
* @param actual The value to apply matchers against.
|
|
19
|
+
*/
|
|
20
|
+
<T = unknown>(actual: T): ExpectWebdriverIO.MatchersAndInverse<Promise<void>, T>
|
|
21
|
+
}
|
|
22
|
+
}
|
package/jasmine.d.ts
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
/// <reference types="./types/expect-webdriverio.d.ts"/>
|
|
2
2
|
|
|
3
3
|
declare namespace jasmine {
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Async matchers for Jasmine to allow the typing of `expectAsync` with WebDriverIO matchers.
|
|
7
|
+
* T is the type of the actual value
|
|
8
|
+
* U is the type of the expected value
|
|
9
|
+
* Both T,U must stay named as they are to override the default `AsyncMatchers` type from Jasmine.
|
|
10
|
+
*
|
|
11
|
+
* We force Matchers to return a `Promise<void>` since Jasmine's `expectAsync` expects a promise in all cases (different from Jest)
|
|
12
|
+
*/
|
|
4
13
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
5
|
-
interface AsyncMatchers<T, U> extends ExpectWebdriverIO.Matchers<Promise<void>, T> {
|
|
6
|
-
|
|
14
|
+
interface AsyncMatchers<T, U> extends Omit<ExpectWebdriverIO.Matchers<Promise<void>, T>, 'toMatchSnapshot' | 'toMatchInlineSnapshot'> {
|
|
15
|
+
/**
|
|
16
|
+
* snapshot matcher
|
|
17
|
+
* @param label optional snapshot label
|
|
18
|
+
*/
|
|
19
|
+
toMatchSnapshot(label?: string): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* inline snapshot matcher
|
|
22
|
+
* @param snapshot snapshot string (autogenerated if not specified)
|
|
23
|
+
* @param label optional snapshot label
|
|
24
|
+
*/
|
|
25
|
+
toMatchInlineSnapshot(snapshot?: string, label?: string): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
}
|
package/jest.d.ts
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
/// <reference types="./types/expect-webdriverio.d.ts"/>
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Augment the Jest namespace to include the matchers from expect-webdriverio.
|
|
5
|
+
* When Jest Library is used, it specifies `expect-webdriverio/jest` for this file in the tsconfig.json's types.
|
|
6
|
+
*/
|
|
7
|
+
|
|
3
8
|
declare namespace jest {
|
|
4
|
-
|
|
5
|
-
|
|
9
|
+
|
|
10
|
+
interface Matchers<R extends void | Promise<void>, T> extends ExpectWebdriverIO.Matchers<R, T> {
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Below are overloaded Jest's matchers not part of `expect` but of `jest-snapshot`.
|
|
14
|
+
* @see https://github.com/jestjs/jest/blob/73dbef5d2d3195a1e55fb254c54cce70d3036252/packages/jest-snapshot/src/types.ts#L37
|
|
15
|
+
*
|
|
16
|
+
* Note: We need to define them below so that they are correctly typed overloaded.
|
|
17
|
+
* Else even when extending `WdioJestOverloadedMatchers` we have typing errors.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* snapshot matcher
|
|
22
|
+
* @param label optional snapshot label
|
|
23
|
+
*/
|
|
24
|
+
toMatchSnapshot(label?: string): T extends WdioPromiseLike ? Promise<void> : void;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* inline snapshot matcher
|
|
28
|
+
* @param snapshot snapshot string (autogenerated if not specified)
|
|
29
|
+
* @param label optional snapshot label
|
|
30
|
+
*/
|
|
31
|
+
toMatchInlineSnapshot(snapshot?: string, label?: string): T extends WdioPromiseLike ? Promise<void> : void;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface Expect extends ExpectWebdriverIO.Expect {}
|
|
35
|
+
|
|
36
|
+
interface InverseAsymmetricMatchers extends ExpectWebdriverIO.AsymmetricMatchers {}
|
|
37
|
+
}
|
|
@@ -53,7 +53,7 @@ export async function toHaveAttribute(received, attribute, value, options = DEFA
|
|
|
53
53
|
expectedValue: [attribute, value],
|
|
54
54
|
options,
|
|
55
55
|
});
|
|
56
|
-
const result =
|
|
56
|
+
const result = value !== undefined
|
|
57
57
|
? await toHaveAttributeAndValue.call(this, received, attribute, value, options)
|
|
58
58
|
: await toHaveAttributeFn.call(this, received, attribute);
|
|
59
59
|
await options.afterAssertion?.({
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
2
|
-
import { compareText, compareTextWithArray, enhanceError, executeCommand,
|
|
2
|
+
import { compareText, compareTextWithArray, enhanceError, executeCommand, isAsymmetricMatcher, waitUntil, wrapExpectedWithArray } from '../../utils.js';
|
|
3
3
|
import { toHaveAttributeAndValue } from './toHaveAttribute.js';
|
|
4
4
|
async function condition(el, attribute, value, options) {
|
|
5
5
|
const actualClass = await el.getAttribute(attribute);
|
|
6
6
|
if (typeof actualClass !== 'string') {
|
|
7
7
|
return { result: false };
|
|
8
8
|
}
|
|
9
|
-
if (
|
|
9
|
+
if (isAsymmetricMatcher(value)) {
|
|
10
10
|
return compareText(actualClass, value, options);
|
|
11
11
|
}
|
|
12
12
|
const classes = actualClass.split(' ');
|
|
@@ -45,7 +45,7 @@ export async function toBeRequestedWith(received, expectedValue = {}, options =
|
|
|
45
45
|
return result;
|
|
46
46
|
}
|
|
47
47
|
const methodMatcher = (method, expected) => {
|
|
48
|
-
if (
|
|
48
|
+
if (expected === undefined) {
|
|
49
49
|
return true;
|
|
50
50
|
}
|
|
51
51
|
if (!Array.isArray(expected)) {
|
|
@@ -61,7 +61,7 @@ const methodMatcher = (method, expected) => {
|
|
|
61
61
|
.includes(method);
|
|
62
62
|
};
|
|
63
63
|
const statusCodeMatcher = (statusCode, expected) => {
|
|
64
|
-
if (
|
|
64
|
+
if (expected === undefined) {
|
|
65
65
|
return true;
|
|
66
66
|
}
|
|
67
67
|
if (!Array.isArray(expected)) {
|
|
@@ -70,7 +70,7 @@ const statusCodeMatcher = (statusCode, expected) => {
|
|
|
70
70
|
return expected.includes(statusCode);
|
|
71
71
|
};
|
|
72
72
|
const urlMatcher = (url, expected) => {
|
|
73
|
-
if (
|
|
73
|
+
if (expected === undefined) {
|
|
74
74
|
return true;
|
|
75
75
|
}
|
|
76
76
|
if (typeof expected === 'function') {
|
|
@@ -79,7 +79,7 @@ const urlMatcher = (url, expected) => {
|
|
|
79
79
|
return equals(url, expected);
|
|
80
80
|
};
|
|
81
81
|
const headersMatcher = (headers, expected) => {
|
|
82
|
-
if (
|
|
82
|
+
if (expected === undefined ||
|
|
83
83
|
typeof expected === 'object' && Object.keys(expected).length === 0) {
|
|
84
84
|
return true;
|
|
85
85
|
}
|
|
@@ -98,7 +98,7 @@ const isMatcher = (filter) => {
|
|
|
98
98
|
typeof proto.asymmetricMatch === 'function');
|
|
99
99
|
};
|
|
100
100
|
const minifyRequestMock = (requestMock, requestedWith) => {
|
|
101
|
-
if (
|
|
101
|
+
if (requestMock === undefined) {
|
|
102
102
|
return requestMock;
|
|
103
103
|
}
|
|
104
104
|
const r = {
|
|
@@ -123,7 +123,7 @@ const minifyRequestedWith = (r) => {
|
|
|
123
123
|
return result;
|
|
124
124
|
};
|
|
125
125
|
const requestedWithParamToString = (param, transformFn) => {
|
|
126
|
-
if (
|
|
126
|
+
if (param === undefined) {
|
|
127
127
|
return;
|
|
128
128
|
}
|
|
129
129
|
if (typeof param === 'function') {
|
|
@@ -175,7 +175,7 @@ const shortenString = (str, limit = STR_LIMIT) => {
|
|
|
175
175
|
};
|
|
176
176
|
const deleteUndefinedValues = (obj, baseline = obj) => {
|
|
177
177
|
Object.keys(obj).forEach((k) => {
|
|
178
|
-
if (
|
|
178
|
+
if (baseline[k] === undefined) {
|
|
179
179
|
delete obj[k];
|
|
180
180
|
}
|
|
181
181
|
});
|
package/lib/matchers/snapshot.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { expect } from 'expect';
|
|
3
3
|
import { stripSnapshotIndentation } from '@vitest/snapshot';
|
|
4
|
-
import { SnapshotService } from '../snapshot
|
|
4
|
+
import { SnapshotService } from '../snapshot';
|
|
5
5
|
function returnSnapshotError(snapshotError) {
|
|
6
6
|
try {
|
|
7
7
|
expect(snapshotError.actual).toBe(snapshotError.expected);
|
package/lib/snapshot.js
CHANGED
|
@@ -1,43 +1,29 @@
|
|
|
1
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
-
};
|
|
7
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
-
};
|
|
12
|
-
var _WebdriverIOSnapshotEnvironment_resolveSnapshotPath, _SnapshotService_instances, _SnapshotService_currentFilePath, _SnapshotService_currentTestName, _SnapshotService_options, _SnapshotService_snapshotResults, _SnapshotService_snapshotClient, _SnapshotService_isEqual;
|
|
13
1
|
import { expect } from '@wdio/globals';
|
|
14
2
|
import { SnapshotClient } from '@vitest/snapshot';
|
|
15
3
|
import { NodeSnapshotEnvironment } from '@vitest/snapshot/environment';
|
|
16
4
|
let service;
|
|
17
5
|
class WebdriverIOSnapshotEnvironment extends NodeSnapshotEnvironment {
|
|
6
|
+
#resolveSnapshotPath;
|
|
18
7
|
constructor(resolveSnapshotPath) {
|
|
19
8
|
super({});
|
|
20
|
-
|
|
21
|
-
__classPrivateFieldSet(this, _WebdriverIOSnapshotEnvironment_resolveSnapshotPath, resolveSnapshotPath, "f");
|
|
9
|
+
this.#resolveSnapshotPath = resolveSnapshotPath;
|
|
22
10
|
}
|
|
23
11
|
async resolvePath(filepath) {
|
|
24
|
-
if (
|
|
25
|
-
return
|
|
12
|
+
if (this.#resolveSnapshotPath) {
|
|
13
|
+
return this.#resolveSnapshotPath(filepath, '.snap');
|
|
26
14
|
}
|
|
27
15
|
return super.resolvePath(filepath);
|
|
28
16
|
}
|
|
29
17
|
}
|
|
30
|
-
_WebdriverIOSnapshotEnvironment_resolveSnapshotPath = new WeakMap();
|
|
31
18
|
export class SnapshotService {
|
|
19
|
+
#currentFilePath;
|
|
20
|
+
#currentTestName;
|
|
21
|
+
#options;
|
|
22
|
+
#snapshotResults = [];
|
|
23
|
+
#snapshotClient = new SnapshotClient({
|
|
24
|
+
isEqual: this.#isEqual.bind(this),
|
|
25
|
+
});
|
|
32
26
|
constructor(options) {
|
|
33
|
-
_SnapshotService_instances.add(this);
|
|
34
|
-
_SnapshotService_currentFilePath.set(this, void 0);
|
|
35
|
-
_SnapshotService_currentTestName.set(this, void 0);
|
|
36
|
-
_SnapshotService_options.set(this, void 0);
|
|
37
|
-
_SnapshotService_snapshotResults.set(this, []);
|
|
38
|
-
_SnapshotService_snapshotClient.set(this, new SnapshotClient({
|
|
39
|
-
isEqual: __classPrivateFieldGet(this, _SnapshotService_instances, "m", _SnapshotService_isEqual).bind(this),
|
|
40
|
-
}));
|
|
41
27
|
const updateSnapshot = (Boolean(process.env.CI) && !options?.updateState)
|
|
42
28
|
? 'none'
|
|
43
29
|
: options?.updateState
|
|
@@ -48,45 +34,54 @@ export class SnapshotService {
|
|
|
48
34
|
escapeString: false,
|
|
49
35
|
...options.snapshotFormat
|
|
50
36
|
} : undefined;
|
|
51
|
-
|
|
37
|
+
this.#options = {
|
|
52
38
|
updateSnapshot,
|
|
53
39
|
snapshotEnvironment: new WebdriverIOSnapshotEnvironment(options?.resolveSnapshotPath),
|
|
54
40
|
...(snapshotFormatConfig && { snapshotFormat: snapshotFormatConfig })
|
|
55
|
-
}
|
|
41
|
+
};
|
|
56
42
|
}
|
|
57
43
|
get currentFilePath() {
|
|
58
|
-
return
|
|
44
|
+
return this.#currentFilePath;
|
|
59
45
|
}
|
|
60
46
|
get currentTestName() {
|
|
61
|
-
return
|
|
47
|
+
return this.#currentTestName;
|
|
62
48
|
}
|
|
63
49
|
get client() {
|
|
64
|
-
return
|
|
50
|
+
return this.#snapshotClient;
|
|
65
51
|
}
|
|
66
52
|
get results() {
|
|
67
|
-
return
|
|
53
|
+
return this.#snapshotResults;
|
|
68
54
|
}
|
|
69
55
|
async beforeTest(test) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
await
|
|
56
|
+
this.#currentFilePath = test.file;
|
|
57
|
+
this.#currentTestName = `${test.parent} > ${test.title}`;
|
|
58
|
+
await this.#snapshotClient.setup(test.file, this.#options);
|
|
73
59
|
}
|
|
74
60
|
async beforeStep(step, scenario) {
|
|
75
61
|
const file = scenario.uri;
|
|
76
62
|
const testName = `${scenario.name} > ${step.text}`;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
await
|
|
63
|
+
this.#currentFilePath = file;
|
|
64
|
+
this.#currentTestName = testName;
|
|
65
|
+
await this.#snapshotClient.setup(file, this.#options);
|
|
80
66
|
}
|
|
81
67
|
async after() {
|
|
82
|
-
if (!
|
|
68
|
+
if (!this.#currentFilePath) {
|
|
83
69
|
return;
|
|
84
70
|
}
|
|
85
|
-
const result = await
|
|
71
|
+
const result = await this.#snapshotClient.finish(this.#currentFilePath);
|
|
86
72
|
if (!result) {
|
|
87
73
|
return;
|
|
88
74
|
}
|
|
89
|
-
|
|
75
|
+
this.#snapshotResults.push(result);
|
|
76
|
+
}
|
|
77
|
+
#isEqual(received, expected) {
|
|
78
|
+
try {
|
|
79
|
+
expect(received).toBe(expected);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
90
85
|
}
|
|
91
86
|
static initiate(options) {
|
|
92
87
|
if (!service) {
|
|
@@ -95,12 +90,3 @@ export class SnapshotService {
|
|
|
95
90
|
return service;
|
|
96
91
|
}
|
|
97
92
|
}
|
|
98
|
-
_SnapshotService_currentFilePath = new WeakMap(), _SnapshotService_currentTestName = new WeakMap(), _SnapshotService_options = new WeakMap(), _SnapshotService_snapshotResults = new WeakMap(), _SnapshotService_snapshotClient = new WeakMap(), _SnapshotService_instances = new WeakSet(), _SnapshotService_isEqual = function _SnapshotService_isEqual(received, expected) {
|
|
99
|
-
try {
|
|
100
|
-
expect(received).toBe(expected);
|
|
101
|
-
return true;
|
|
102
|
-
}
|
|
103
|
-
catch {
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
};
|
package/lib/softAssert.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export class SoftAssertService {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
2
|
+
static instance;
|
|
3
|
+
failureMap = new Map();
|
|
4
|
+
currentTest = null;
|
|
5
|
+
constructor() { }
|
|
6
6
|
static getInstance() {
|
|
7
7
|
if (!SoftAssertService.instance) {
|
|
8
8
|
SoftAssertService.instance = new SoftAssertService();
|
package/lib/softAssertService.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/constants.ts","../src/index.ts","../src/jasmineUtils.ts","../src/matchers.ts","../src/snapshot.ts","../src/softAssert.ts","../src/softAssertService.ts","../src/softExpect.ts","../src/types.ts","../src/utils.ts","../src/matchers/snapshot.ts","../src/matchers/browser/toHaveClipboardText.ts","../src/matchers/browser/toHaveTitle.ts","../src/matchers/browser/toHaveUrl.ts","../src/matchers/element/toBeClickable.ts","../src/matchers/element/toBeDisabled.ts","../src/matchers/element/toBeDisplayed.ts","../src/matchers/element/toBeDisplayedInViewport.ts","../src/matchers/element/toBeEnabled.ts","../src/matchers/element/toBeExisting.ts","../src/matchers/element/toBeFocused.ts","../src/matchers/element/toBeSelected.ts","../src/matchers/element/toHaveAttribute.ts","../src/matchers/element/toHaveChildren.ts","../src/matchers/element/toHaveClass.ts","../src/matchers/element/toHaveComputedLabel.ts","../src/matchers/element/toHaveComputedRole.ts","../src/matchers/element/toHaveElementProperty.ts","../src/matchers/element/toHaveHTML.ts","../src/matchers/element/toHaveHeight.ts","../src/matchers/element/toHaveHref.ts","../src/matchers/element/toHaveId.ts","../src/matchers/element/toHaveSize.ts","../src/matchers/element/toHaveStyle.ts","../src/matchers/element/toHaveText.ts","../src/matchers/element/toHaveValue.ts","../src/matchers/element/toHaveWidth.ts","../src/matchers/elements/toBeElementsArrayOfSize.ts","../src/matchers/mock/toBeRequested.ts","../src/matchers/mock/toBeRequestedTimes.ts","../src/matchers/mock/toBeRequestedWith.ts","../src/util/elementsUtil.ts","../src/util/executeCommand.ts","../src/util/formatMessage.ts","../src/util/refetchElements.ts"],"version":"5.
|
|
1
|
+
{"root":["../src/constants.ts","../src/index.ts","../src/jasmineUtils.ts","../src/matchers.ts","../src/snapshot.ts","../src/softAssert.ts","../src/softAssertService.ts","../src/softExpect.ts","../src/types.ts","../src/utils.ts","../src/matchers/snapshot.ts","../src/matchers/browser/toHaveClipboardText.ts","../src/matchers/browser/toHaveTitle.ts","../src/matchers/browser/toHaveUrl.ts","../src/matchers/element/toBeClickable.ts","../src/matchers/element/toBeDisabled.ts","../src/matchers/element/toBeDisplayed.ts","../src/matchers/element/toBeDisplayedInViewport.ts","../src/matchers/element/toBeEnabled.ts","../src/matchers/element/toBeExisting.ts","../src/matchers/element/toBeFocused.ts","../src/matchers/element/toBeSelected.ts","../src/matchers/element/toHaveAttribute.ts","../src/matchers/element/toHaveChildren.ts","../src/matchers/element/toHaveClass.ts","../src/matchers/element/toHaveComputedLabel.ts","../src/matchers/element/toHaveComputedRole.ts","../src/matchers/element/toHaveElementProperty.ts","../src/matchers/element/toHaveHTML.ts","../src/matchers/element/toHaveHeight.ts","../src/matchers/element/toHaveHref.ts","../src/matchers/element/toHaveId.ts","../src/matchers/element/toHaveSize.ts","../src/matchers/element/toHaveStyle.ts","../src/matchers/element/toHaveText.ts","../src/matchers/element/toHaveValue.ts","../src/matchers/element/toHaveWidth.ts","../src/matchers/elements/toBeElementsArrayOfSize.ts","../src/matchers/mock/toBeRequested.ts","../src/matchers/mock/toBeRequestedTimes.ts","../src/matchers/mock/toBeRequestedWith.ts","../src/util/elementsUtil.ts","../src/util/executeCommand.ts","../src/util/formatMessage.ts","../src/util/refetchElements.ts"],"version":"5.9.3"}
|
package/lib/utils.js
CHANGED
|
@@ -7,10 +7,9 @@ import { enhanceError, enhanceErrorBe, numberError } from './util/formatMessage.
|
|
|
7
7
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
8
8
|
const asymmetricMatcher = typeof Symbol === 'function' && Symbol.for
|
|
9
9
|
? Symbol.for('jest.asymmetricMatcher')
|
|
10
|
-
:
|
|
11
|
-
export function
|
|
10
|
+
: 0x13_57_a5;
|
|
11
|
+
export function isAsymmetricMatcher(expected) {
|
|
12
12
|
return (typeof expected === 'object' &&
|
|
13
|
-
typeof expected === 'object' &&
|
|
14
13
|
expected &&
|
|
15
14
|
'$$typeof' in expected &&
|
|
16
15
|
'asymmetricMatch' in expected &&
|
|
@@ -18,7 +17,7 @@ export function isAsymmeyricMatcher(expected) {
|
|
|
18
17
|
Boolean(expected.asymmetricMatch));
|
|
19
18
|
}
|
|
20
19
|
function isStringContainingMatcher(expected) {
|
|
21
|
-
return
|
|
20
|
+
return isAsymmetricMatcher(expected) && ['StringContaining', 'StringNotContaining'].includes(expected.toString());
|
|
22
21
|
}
|
|
23
22
|
const waitUntil = async (condition, isNot = false, { wait = DEFAULT_OPTIONS.wait, interval = DEFAULT_OPTIONS.interval } = {}) => {
|
|
24
23
|
if (wait === 0) {
|
|
@@ -31,7 +30,6 @@ const waitUntil = async (condition, isNot = false, { wait = DEFAULT_OPTIONS.wait
|
|
|
31
30
|
if (Date.now() - start > wait) {
|
|
32
31
|
throw new Error('timeout');
|
|
33
32
|
}
|
|
34
|
-
error = undefined;
|
|
35
33
|
try {
|
|
36
34
|
const result = isNot !== (await condition());
|
|
37
35
|
error = undefined;
|
|
@@ -110,7 +108,7 @@ export const compareText = (actual, expected, { ignoreCase = false, trim = true,
|
|
|
110
108
|
: expect.not.stringContaining(expected.sample?.toString().toLowerCase()));
|
|
111
109
|
}
|
|
112
110
|
}
|
|
113
|
-
if (
|
|
111
|
+
if (isAsymmetricMatcher(expected)) {
|
|
114
112
|
const result = expected.asymmetricMatch(actual);
|
|
115
113
|
return {
|
|
116
114
|
value: actual,
|
|
@@ -183,7 +181,7 @@ export const compareTextWithArray = (actual, expectedArray, { ignoreCase = false
|
|
|
183
181
|
if (expected instanceof RegExp) {
|
|
184
182
|
return !!actual.match(expected);
|
|
185
183
|
}
|
|
186
|
-
if (
|
|
184
|
+
if (isAsymmetricMatcher(expected)) {
|
|
187
185
|
return expected.asymmetricMatch(actual);
|
|
188
186
|
}
|
|
189
187
|
if (containing) {
|
|
@@ -217,12 +215,12 @@ export const compareObject = (actual, expected) => {
|
|
|
217
215
|
result: deepEql(actual, expected),
|
|
218
216
|
};
|
|
219
217
|
};
|
|
220
|
-
export const compareStyle = async (actualEl, style, { ignoreCase =
|
|
218
|
+
export const compareStyle = async (actualEl, style, { ignoreCase = false, trim = true, containing = false, atStart = false, atEnd = false, atIndex, replace, }) => {
|
|
221
219
|
let result = true;
|
|
222
220
|
const actual = {};
|
|
223
221
|
for (const key in style) {
|
|
224
222
|
const css = await actualEl.getCSSProperty(key);
|
|
225
|
-
let actualVal = css.value;
|
|
223
|
+
let actualVal = String(css.value || '');
|
|
226
224
|
let expectedVal = style[key];
|
|
227
225
|
if (trim) {
|
|
228
226
|
actualVal = actualVal.trim();
|
|
@@ -232,8 +230,31 @@ export const compareStyle = async (actualEl, style, { ignoreCase = true, trim =
|
|
|
232
230
|
actualVal = actualVal.toLowerCase();
|
|
233
231
|
expectedVal = expectedVal.toLowerCase();
|
|
234
232
|
}
|
|
235
|
-
|
|
236
|
-
|
|
233
|
+
if (containing) {
|
|
234
|
+
result = actualVal.includes(expectedVal);
|
|
235
|
+
actual[key] = actualVal;
|
|
236
|
+
}
|
|
237
|
+
else if (atStart) {
|
|
238
|
+
result = actualVal.startsWith(expectedVal);
|
|
239
|
+
actual[key] = actualVal;
|
|
240
|
+
}
|
|
241
|
+
else if (atEnd) {
|
|
242
|
+
result = actualVal.endsWith(expectedVal);
|
|
243
|
+
actual[key] = actualVal;
|
|
244
|
+
}
|
|
245
|
+
else if (atIndex) {
|
|
246
|
+
result = actualVal.substring(atIndex, actualVal.length).startsWith(expectedVal);
|
|
247
|
+
actual[key] = actualVal;
|
|
248
|
+
}
|
|
249
|
+
else if (replace) {
|
|
250
|
+
const replacedActual = replaceActual(replace, actualVal);
|
|
251
|
+
result = replacedActual === expectedVal;
|
|
252
|
+
actual[key] = replacedActual;
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
result = result && actualVal === expectedVal;
|
|
256
|
+
actual[key] = css.value;
|
|
257
|
+
}
|
|
237
258
|
}
|
|
238
259
|
return {
|
|
239
260
|
value: actual,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expect-webdriverio",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.6.0",
|
|
4
4
|
"author": "Mykola Grybyk <mykola.grybyk@gmail.com>",
|
|
5
5
|
"description": "WebdriverIO Assertion Library",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"exports": {
|
|
24
24
|
".": [
|
|
25
25
|
{
|
|
26
|
-
"types": "./types/
|
|
26
|
+
"types": "./types/expect-webdriverio.d.ts",
|
|
27
27
|
"import": "./lib/index.js"
|
|
28
28
|
},
|
|
29
29
|
"./lib/index.js"
|
|
@@ -33,54 +33,64 @@
|
|
|
33
33
|
"types": "./jest.d.ts"
|
|
34
34
|
}
|
|
35
35
|
],
|
|
36
|
-
"./
|
|
36
|
+
"./jasmine": [
|
|
37
|
+
{
|
|
38
|
+
"types": "./jasmine.d.ts"
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"./types": "./types/expect-global.d.ts",
|
|
42
|
+
"./expect-global": "./types/expect-global.d.ts"
|
|
37
43
|
},
|
|
38
|
-
"types": "./types/
|
|
44
|
+
"types": "./types/expect-webdriverio.d.ts",
|
|
39
45
|
"typeScriptVersion": "3.8.3",
|
|
40
46
|
"engines": {
|
|
41
|
-
"node": ">=
|
|
47
|
+
"node": ">=20"
|
|
42
48
|
},
|
|
43
49
|
"scripts": {
|
|
44
50
|
"build": "run-s clean compile",
|
|
45
51
|
"clean": "run-p clean:*",
|
|
46
52
|
"clean:build": "rimraf ./lib",
|
|
47
|
-
"clean:tests": "rimraf test-types/**/node_modules && rimraf test-types/**/dist",
|
|
48
53
|
"compile": "tsc --build tsconfig.build.json",
|
|
49
|
-
"tsc:root-types": "
|
|
54
|
+
"tsc:root-types": "node types-checks-filter-out-node_modules.js",
|
|
50
55
|
"test": "run-s test:*",
|
|
51
56
|
"test:tsc": "tsc --project tsconfig.json --noEmit",
|
|
52
57
|
"test:lint": "eslint .",
|
|
53
58
|
"test:unit": "vitest --run",
|
|
54
|
-
"test:types": "
|
|
55
|
-
"ts": "run-s ts:*",
|
|
56
|
-
"ts:
|
|
57
|
-
"ts:jest": "cd test-types/jest && tsc
|
|
58
|
-
"ts:
|
|
59
|
+
"test:types": "npm run ts && npm run tsc:root-types",
|
|
60
|
+
"ts": "run-s ts:* ts:*:*",
|
|
61
|
+
"ts:jest:@jest/global": "cd test-types/jest-@jest_global && tsc --project ./tsconfig.json",
|
|
62
|
+
"ts:jest:@types-jest": "cd test-types/jest-@types_jest && tsc --project ./tsconfig.json",
|
|
63
|
+
"ts:mocha": "cd test-types/mocha && tsc --project ./tsconfig.json",
|
|
64
|
+
"ts:jasmine": "cd test-types/jasmine && tsc --project ./tsconfig.json",
|
|
65
|
+
"ts:jasmine-async": "cd test-types/jasmine-async && tsc --project ./tsconfig.json",
|
|
59
66
|
"watch": "npm run compile -- --watch",
|
|
60
67
|
"prepare": "husky install"
|
|
61
68
|
},
|
|
62
69
|
"dependencies": {
|
|
63
|
-
"@vitest/snapshot": "^
|
|
70
|
+
"@vitest/snapshot": "^4.0.16",
|
|
64
71
|
"deep-eql": "^5.0.2",
|
|
65
|
-
"expect": "^30.
|
|
66
|
-
"jest-matcher-utils": "^30.
|
|
72
|
+
"expect": "^30.2.0",
|
|
73
|
+
"jest-matcher-utils": "^30.2.0"
|
|
67
74
|
},
|
|
68
75
|
"devDependencies": {
|
|
69
76
|
"@types/debug": "^4.1.12",
|
|
77
|
+
"@types/jasmine": "^5.1.8",
|
|
70
78
|
"@types/jest": "^30.0.0",
|
|
71
|
-
"@types/node": "^24.
|
|
72
|
-
"@
|
|
73
|
-
"@
|
|
74
|
-
"@
|
|
75
|
-
"eslint": "^
|
|
79
|
+
"@types/node": "^24.10.1",
|
|
80
|
+
"@types/mocha": "^10.0.10",
|
|
81
|
+
"@jest/globals": "^30.2.0",
|
|
82
|
+
"@vitest/coverage-v8": "^4.0.16",
|
|
83
|
+
"@wdio/eslint": "^0.1.2",
|
|
84
|
+
"@wdio/types": "^9.20.0",
|
|
85
|
+
"eslint": "^9.39.2",
|
|
76
86
|
"husky": "^9.1.7",
|
|
77
87
|
"npm-run-all2": "^8.0.4",
|
|
78
|
-
"release-it": "^19.0
|
|
79
|
-
"rimraf": "^6.
|
|
88
|
+
"release-it": "^19.1.0",
|
|
89
|
+
"rimraf": "^6.1.2",
|
|
80
90
|
"shelljs": "^0.10.0",
|
|
81
|
-
"typescript": "^5.
|
|
82
|
-
"vitest": "^
|
|
83
|
-
"webdriverio": "^9.
|
|
91
|
+
"typescript": "^5.9.3",
|
|
92
|
+
"vitest": "^4.0.16",
|
|
93
|
+
"webdriverio": "^9.21.0"
|
|
84
94
|
},
|
|
85
95
|
"peerDependencies": {
|
|
86
96
|
"@wdio/globals": "^9.0.0",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="./expect-webdriverio.d.ts"/>
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Global declaration file for WebdriverIO's Expect library to force the expect.
|
|
5
|
+
* Required when used in standalone mode (mocha) or to override the one of Jasmine
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
//// @ts-expect-error: IDE might flags this one but just does be concerned by it. This way the `tsc:root-types` can pass!
|
|
9
|
+
declare const expect: ExpectWebdriverIO.Expect
|
|
10
|
+
|
|
11
|
+
declare namespace NodeJS {
|
|
12
|
+
interface Global {
|
|
13
|
+
expect: ExpectWebdriverIO.Expect
|
|
14
|
+
}
|
|
15
|
+
}
|