expect-webdriverio 5.6.8 → 5.7.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/jasmine-wdio-expect-async.d.ts +58 -18
- package/jasmine.d.ts +9 -16
- package/jest.d.ts +6 -6
- package/lib/index.js +5 -1
- package/lib/jasmineUtils.js +3 -2
- package/lib/matchers/mock/toBeRequestedWith.js +5 -14
- package/lib/utils.js +47 -17
- package/package.json +5 -5
- package/types/expect-global.d.ts +3 -2
- package/types/expect-webdriverio.d.ts +57 -8
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
/// <reference types="./types/expect-webdriverio.d.ts"/>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Note: Under development, until proven, expect breaking changes!
|
|
5
|
+
* Augment the Jasmine namespace to match the behavior of `@wdio/jasmine-framework`.
|
|
6
|
+
* Only custom WDIO matchers are available under `expectAsync`, as well as Jasmine's built-in matchers.
|
|
7
|
+
* `expectAsync` is forced into the `expect` global ambient, making all Jasmine sync-matchers asynchronous.
|
|
8
|
+
*
|
|
9
|
+
* When using `@wdio/jasmine-framework`, specify `expect-webdriverio/jasmine-wdio-expect-async` in the tsconfig.json's types.
|
|
10
|
+
* TODO move into `@wdio/jasmine-framework` and deprecated it from `expect-webdriverio`.
|
|
11
|
+
*/
|
|
4
12
|
|
|
13
|
+
declare namespace jasmine {
|
|
5
14
|
/**
|
|
6
15
|
* Async matchers for Jasmine to allow the typing of `expectAsync` with WebDriverIO matchers.
|
|
7
16
|
* T is the type of the actual value
|
|
@@ -10,28 +19,47 @@ declare namespace jasmine {
|
|
|
10
19
|
*
|
|
11
20
|
* We force Matchers to return a `Promise<void>` since Jasmine's `expectAsync` expects a promise in all cases (different from Jest)
|
|
12
21
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
22
|
+
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- U is required to properly override Jasmine's AsyncMatchers
|
|
24
|
+
interface AsyncMatchers<T, U> extends ExpectWebdriverIO.Matchers<Promise<void>, T> {
|
|
15
25
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
26
|
+
* Override to unwrap Promise<T> since `expect` replaces `expectAsync` under @wdio/jasmine-framework.
|
|
27
|
+
* Without this, toBeResolvedTo expects Expected<Promise<X>> instead of Expected<X>.
|
|
18
28
|
*/
|
|
19
|
-
|
|
29
|
+
toBeResolvedTo(expected: Expected<T extends PromiseLike<infer V> ? V : T>): PromiseLike<void>;
|
|
30
|
+
|
|
20
31
|
/**
|
|
21
|
-
*
|
|
22
|
-
* @param snapshot snapshot string (autogenerated if not specified)
|
|
23
|
-
* @param label optional snapshot label
|
|
32
|
+
* Rejection type is unknown since promises can reject with any value.
|
|
24
33
|
*/
|
|
25
|
-
|
|
34
|
+
toBeRejectedWith(expected: unknown): PromiseLike<void>;
|
|
26
35
|
}
|
|
36
|
+
|
|
37
|
+
// Needed to reference it below for the withContext method
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
39
|
+
interface Matchers<T> {}
|
|
27
40
|
}
|
|
28
41
|
|
|
29
|
-
/**
|
|
30
|
-
* Overrides the default WDIO expect specifically for Jasmine, since `expectAsync` is forced into `expect`, making all matchers fully asynchronous. This is not the case under Jest or Mocha.
|
|
31
|
-
* Using `jasmine.AsyncMatchers` pull on WdioMatchers above but also allow to using Jasmine's built-in matchers and also `withContext` matcher.
|
|
32
|
-
*/
|
|
33
42
|
declare namespace ExpectWebdriverIO {
|
|
34
|
-
|
|
43
|
+
|
|
44
|
+
// Should be the same as https://github.com/webdriverio/webdriverio/blob/ea0e3e00288abced4c739ff9e46c46977b7cdbd2/packages/wdio-jasmine-framework/src/index.ts#L21-L29
|
|
45
|
+
interface JasmineAsymmetricMatchers extends Pick<ExpectWebdriverIO.AsymmetricMatchers, 'any' | 'anything' | 'arrayContaining' | 'objectContaining' | 'stringContaining' | 'stringMatching'> {}
|
|
46
|
+
|
|
47
|
+
// Hack to convert all sync matchers to return Promise<void> since `wdio/jasmine-framework` forces `expect` to be async
|
|
48
|
+
type JasmineSyncMatchers<T> = {
|
|
49
|
+
[K in keyof jasmine.Matchers<T>]: K extends 'not'
|
|
50
|
+
? JasmineSyncMatchers<T>
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
52
|
+
: jasmine.Matchers<T>[K] extends (...args: any) => any
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
|
+
? (...args: any[]) => Promise<void>
|
|
55
|
+
: jasmine.Matchers<T>[K]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Overrides the default WDIO expect specifically for Jasmine, since `expectAsync` is forced into `expect`, making all matchers fully asynchronous. This is not the case under Jest or Mocha.
|
|
60
|
+
* Using `jasmine.AsyncMatchers` includes the WdioMatchers from above, but also allows using Jasmine's built-in matchers and the `withContext` matcher.
|
|
61
|
+
*/
|
|
62
|
+
interface JasmineExpect extends ExpectWebdriverIO.JasmineAsymmetricMatchers, ExpectLibInverse<ExpectWebdriverIO.JasmineAsymmetricMatchers> {
|
|
35
63
|
/**
|
|
36
64
|
* The `expect` function is used every time you want to test a value.
|
|
37
65
|
* You will rarely call `expect` by itself.
|
|
@@ -40,10 +68,22 @@ declare namespace ExpectWebdriverIO {
|
|
|
40
68
|
* - T: the type of the actual value, e.g. any type, not just WebdriverIO.Browser or WebdriverIO.Element
|
|
41
69
|
* - R: the type of the return value, e.g. Promise<void> or void
|
|
42
70
|
*
|
|
43
|
-
* Note: The function must stay here in the namespace to overwrite correctly the expect function from the expect library.
|
|
44
|
-
*
|
|
45
71
|
* @param actual The value to apply matchers against.
|
|
46
72
|
*/
|
|
47
|
-
<T = unknown>(actual: T):
|
|
73
|
+
<T = unknown>(actual: T): {
|
|
74
|
+
withContext(message: string): jasmine.AsyncMatchers<T, Promise<void>> & JasmineSyncMatchers<T>;
|
|
75
|
+
} & jasmine.AsyncMatchers<T, Promise<void>> & JasmineSyncMatchers<T>
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Under `@wdio/jasmine-framework`, the global `expect` is overridden to use Jasmine's `expectAsync`.
|
|
81
|
+
* It contains custom WebdriverIO matchers as well as Jasmine's built-in async & sync matchers but not the basic Jest's expect library matchers.
|
|
82
|
+
*/
|
|
83
|
+
// @ts-expect-error: IDE might flag this, but ignore it. This way the `tsc:root-types` can pass!
|
|
84
|
+
declare const expect: ExpectWebdriverIO.JasmineExpect
|
|
85
|
+
declare namespace NodeJS {
|
|
86
|
+
interface Global {
|
|
87
|
+
expect: ExpectWebdriverIO.JasmineExpect
|
|
48
88
|
}
|
|
49
89
|
}
|
package/jasmine.d.ts
CHANGED
|
@@ -1,27 +1,20 @@
|
|
|
1
1
|
/// <reference types="./types/expect-webdriverio.d.ts"/>
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Augment the Jasmine namespace to include the WDIO custom async matchers only.
|
|
5
|
+
* When using the vanilla Jasmine Library, use `jasmine.addAsyncMatchers(wdioCustomMatchers)` and specify `expect-webdriverio/jasmine` in the tsconfig.json's types.
|
|
6
|
+
*/
|
|
7
|
+
|
|
3
8
|
declare namespace jasmine {
|
|
4
9
|
|
|
5
10
|
/**
|
|
6
|
-
* Async matchers for Jasmine to allow the typing of `expectAsync` with WebDriverIO matchers.
|
|
11
|
+
* Async matchers for Jasmine to allow the typing of `expectAsync` with WebDriverIO custom matchers.
|
|
7
12
|
* T is the type of the actual value
|
|
8
13
|
* U is the type of the expected value
|
|
9
14
|
* Both T,U must stay named as they are to override the default `AsyncMatchers` type from Jasmine.
|
|
10
15
|
*
|
|
11
|
-
* We force Matchers to return a `Promise<void>` since Jasmine's `expectAsync`
|
|
16
|
+
* We force Matchers to return a `Promise<void>` since under Jasmine's `expectAsync` everything is a promise.
|
|
12
17
|
*/
|
|
13
18
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
14
|
-
interface AsyncMatchers<T, U> extends
|
|
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
|
-
}
|
|
19
|
+
interface AsyncMatchers<T, U> extends ExpectWebdriverIO.Matchers<Promise<void>, T> {}
|
|
20
|
+
}
|
package/jest.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/// <reference types="./types/expect-webdriverio.d.ts"/>
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Augment the Jest namespace to include the matchers
|
|
5
|
-
* When Jest Library is used,
|
|
4
|
+
* Augment the Jest namespace to include the WebDriverIO custom matchers only.
|
|
5
|
+
* When Jest Library is used, specify `expect-webdriverio/jest` for this file in the tsconfig.json's types.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
declare namespace jest {
|
|
@@ -13,7 +13,7 @@ declare namespace jest {
|
|
|
13
13
|
* Below are overloaded Jest's matchers not part of `expect` but of `jest-snapshot`.
|
|
14
14
|
* @see https://github.com/jestjs/jest/blob/73dbef5d2d3195a1e55fb254c54cce70d3036252/packages/jest-snapshot/src/types.ts#L37
|
|
15
15
|
*
|
|
16
|
-
* Note: We need to define them below so that they are correctly
|
|
16
|
+
* Note: We need to define them below so that they are correctly overloaded.
|
|
17
17
|
* Else even when extending `WdioJestOverloadedMatchers` we have typing errors.
|
|
18
18
|
*/
|
|
19
19
|
|
|
@@ -21,17 +21,17 @@ declare namespace jest {
|
|
|
21
21
|
* snapshot matcher
|
|
22
22
|
* @param label optional snapshot label
|
|
23
23
|
*/
|
|
24
|
-
toMatchSnapshot(label?: string): T extends
|
|
24
|
+
toMatchSnapshot(label?: string): T extends WdioElementOrPromiseLike ? Promise<void> : R;
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* inline snapshot matcher
|
|
28
28
|
* @param snapshot snapshot string (autogenerated if not specified)
|
|
29
29
|
* @param label optional snapshot label
|
|
30
30
|
*/
|
|
31
|
-
toMatchInlineSnapshot(snapshot?: string, label?: string): T extends
|
|
31
|
+
toMatchInlineSnapshot(snapshot?: string, label?: string): T extends WdioElementOrPromiseLike ? Promise<void> : R;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
interface Expect extends ExpectWebdriverIO.Expect {}
|
|
35
35
|
|
|
36
36
|
interface InverseAsymmetricMatchers extends ExpectWebdriverIO.AsymmetricMatchers {}
|
|
37
|
-
}
|
|
37
|
+
}
|
package/lib/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as wdioMatchers from './matchers.js';
|
|
|
3
3
|
import { DEFAULT_OPTIONS, defaultOptionsList } from './constants.js';
|
|
4
4
|
import createSoftExpect from './softExpect.js';
|
|
5
5
|
import { SoftAssertService } from './softAssert.js';
|
|
6
|
+
export const wdioCustomMatchers = {};
|
|
6
7
|
export const matchers = new Map();
|
|
7
8
|
const filteredMatchers = {};
|
|
8
9
|
const extend = expectLib.extend;
|
|
@@ -15,7 +16,10 @@ expectLib.extend = (m) => {
|
|
|
15
16
|
if (!m || typeof m !== 'object') {
|
|
16
17
|
return;
|
|
17
18
|
}
|
|
18
|
-
Object.entries(m).forEach(([name, matcher]) =>
|
|
19
|
+
Object.entries(m).forEach(([name, matcher]) => {
|
|
20
|
+
wdioCustomMatchers[name] = matcher;
|
|
21
|
+
matchers.set(name, matcher);
|
|
22
|
+
});
|
|
19
23
|
return extend(m);
|
|
20
24
|
};
|
|
21
25
|
expectLib.extend(filteredMatchers);
|
package/lib/jasmineUtils.js
CHANGED
|
@@ -11,11 +11,12 @@ function asymmetricMatch(a, b) {
|
|
|
11
11
|
if (asymmetricA && asymmetricB) {
|
|
12
12
|
return undefined;
|
|
13
13
|
}
|
|
14
|
+
const matchersUtil = { equals, contains: equals };
|
|
14
15
|
if (asymmetricA) {
|
|
15
|
-
return a.asymmetricMatch(b);
|
|
16
|
+
return a.asymmetricMatch(b, matchersUtil);
|
|
16
17
|
}
|
|
17
18
|
if (asymmetricB) {
|
|
18
|
-
return b.asymmetricMatch(a);
|
|
19
|
+
return b.asymmetricMatch(a, matchersUtil);
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
function eq(a, b, aStack, bStack, customTesters, hasKey) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { waitUntil, enhanceError } from '../../utils.js';
|
|
1
|
+
import { waitUntil, enhanceError, isAsymmetricMatcher, getAsymmetricMatcherValue } from '../../utils.js';
|
|
2
2
|
import { equals } from '../../jasmineUtils.js';
|
|
3
3
|
import { DEFAULT_OPTIONS } from '../../constants.js';
|
|
4
4
|
const STR_LIMIT = 80;
|
|
@@ -88,15 +88,6 @@ const headersMatcher = (headers, expected) => {
|
|
|
88
88
|
}
|
|
89
89
|
return equals(headers, expected);
|
|
90
90
|
};
|
|
91
|
-
const isMatcher = (filter) => {
|
|
92
|
-
const proto = Object.getPrototypeOf(filter);
|
|
93
|
-
return (typeof filter === 'object' &&
|
|
94
|
-
filter !== null &&
|
|
95
|
-
typeof proto === 'object' &&
|
|
96
|
-
proto &&
|
|
97
|
-
'asymmetricMatch' in proto &&
|
|
98
|
-
typeof proto.asymmetricMatch === 'function');
|
|
99
|
-
};
|
|
100
91
|
const minifyRequestMock = (requestMock, requestedWith) => {
|
|
101
92
|
if (requestMock === undefined) {
|
|
102
93
|
return requestMock;
|
|
@@ -129,10 +120,10 @@ const requestedWithParamToString = (param, transformFn) => {
|
|
|
129
120
|
if (typeof param === 'function') {
|
|
130
121
|
param = param.toString();
|
|
131
122
|
}
|
|
132
|
-
else if (
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
123
|
+
else if (isAsymmetricMatcher(param)) {
|
|
124
|
+
const sample = getAsymmetricMatcherValue(param);
|
|
125
|
+
const sampleString = typeof sample === 'string' ? sample : sample instanceof RegExp ? sample.toString() : JSON.stringify(sample) || sample?.toString();
|
|
126
|
+
return `${param.constructor.name} ${sampleString || ''}`;
|
|
136
127
|
}
|
|
137
128
|
else if (transformFn && typeof param === 'object' && param !== null) {
|
|
138
129
|
param = transformFn(param);
|
package/lib/utils.js
CHANGED
|
@@ -5,19 +5,47 @@ import { wrapExpectedWithArray } from './util/elementsUtil.js';
|
|
|
5
5
|
import { executeCommand } from './util/executeCommand.js';
|
|
6
6
|
import { enhanceError, enhanceErrorBe, numberError } from './util/formatMessage.js';
|
|
7
7
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export function isJasmineStringAsymmetricMatcher(expected) {
|
|
9
|
+
return isAsymmetricMatcher(expected) && 'expected' in expected;
|
|
10
|
+
}
|
|
11
11
|
export function isAsymmetricMatcher(expected) {
|
|
12
12
|
return (typeof expected === 'object' &&
|
|
13
|
-
expected &&
|
|
14
|
-
'$$typeof' in expected &&
|
|
13
|
+
!!expected &&
|
|
15
14
|
'asymmetricMatch' in expected &&
|
|
16
|
-
expected
|
|
17
|
-
|
|
15
|
+
!!expected.asymmetricMatch);
|
|
16
|
+
}
|
|
17
|
+
export function isStringContainingMatcherLike(expected) {
|
|
18
|
+
return !!expected && expected.constructor.name === 'StringContaining';
|
|
19
|
+
}
|
|
20
|
+
export function isInversedStringContainingMatcher(expected) {
|
|
21
|
+
return isStringContainingMatcherLike(expected) && expected.inverse === true;
|
|
18
22
|
}
|
|
19
|
-
function
|
|
20
|
-
|
|
23
|
+
export function getStringAsymmetricMatcherValue(expected) {
|
|
24
|
+
if ('expected' in expected) {
|
|
25
|
+
return expected.expected;
|
|
26
|
+
}
|
|
27
|
+
else if ('regexp' in expected) {
|
|
28
|
+
return expected.regexp;
|
|
29
|
+
}
|
|
30
|
+
else if ('sample' in expected) {
|
|
31
|
+
return expected.sample;
|
|
32
|
+
}
|
|
33
|
+
throw new Error(`Could not extract value from asymmetric matcher: ${expected}. Please report this issue to the expect-webdriverio maintainers.`);
|
|
34
|
+
}
|
|
35
|
+
export function getAsymmetricMatcherValue(expected) {
|
|
36
|
+
if ('expected' in expected) {
|
|
37
|
+
return expected.expected;
|
|
38
|
+
}
|
|
39
|
+
else if ('expectedObject' in expected) {
|
|
40
|
+
return expected.expectedObject;
|
|
41
|
+
}
|
|
42
|
+
else if ('regexp' in expected) {
|
|
43
|
+
return expected.regexp;
|
|
44
|
+
}
|
|
45
|
+
else if ('sample' in expected) {
|
|
46
|
+
return expected.sample;
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
21
49
|
}
|
|
22
50
|
const waitUntil = async (condition, isNot = false, { wait = DEFAULT_OPTIONS.wait, interval = DEFAULT_OPTIONS.interval } = {}) => {
|
|
23
51
|
if (wait === 0) {
|
|
@@ -102,10 +130,11 @@ export const compareText = (actual, expected, { ignoreCase = false, trim = true,
|
|
|
102
130
|
if (typeof expected === 'string') {
|
|
103
131
|
expected = expected.toLowerCase();
|
|
104
132
|
}
|
|
105
|
-
else if (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
133
|
+
else if (isStringContainingMatcherLike(expected)) {
|
|
134
|
+
const sample = getStringAsymmetricMatcherValue(expected).toString().toLocaleLowerCase();
|
|
135
|
+
expected = (isInversedStringContainingMatcher(expected)
|
|
136
|
+
? expect.not.stringContaining(sample)
|
|
137
|
+
: expect.stringContaining(sample));
|
|
109
138
|
}
|
|
110
139
|
}
|
|
111
140
|
if (isAsymmetricMatcher(expected)) {
|
|
@@ -169,10 +198,11 @@ export const compareTextWithArray = (actual, expectedArray, { ignoreCase = false
|
|
|
169
198
|
if (typeof item === 'string') {
|
|
170
199
|
return item.toLowerCase();
|
|
171
200
|
}
|
|
172
|
-
if (
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
201
|
+
if (isStringContainingMatcherLike(item)) {
|
|
202
|
+
const sample = getStringAsymmetricMatcherValue(item).toString().toLocaleLowerCase();
|
|
203
|
+
return (isInversedStringContainingMatcher(item)
|
|
204
|
+
? expect.not.stringContaining(sample)
|
|
205
|
+
: expect.stringContaining(sample));
|
|
176
206
|
}
|
|
177
207
|
return item;
|
|
178
208
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expect-webdriverio",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.7.0",
|
|
4
4
|
"author": "Mykola Grybyk <mykola.grybyk@gmail.com>",
|
|
5
5
|
"description": "WebdriverIO Assertion Library",
|
|
6
6
|
"license": "MIT",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"ts:mocha": "cd test-types/mocha && vitest --typecheck --typecheck.tsconfig ./tsconfig.json --run",
|
|
72
72
|
"checks:all": "npm run build && npm run compile && npm run tsc:root-types && npm run test && npm run ts",
|
|
73
73
|
"watch": "npm run compile -- --watch",
|
|
74
|
-
"prepare": "husky
|
|
74
|
+
"prepare": "husky",
|
|
75
75
|
"playgrounds:setup": "cd playgrounds && npm run setup",
|
|
76
76
|
"playgrounds:checks:all": "cd playgrounds && npm run checks:all",
|
|
77
77
|
"playgrounds:snapshots:update": "cd playgrounds && npm run snapshots:update"
|
|
@@ -83,12 +83,12 @@
|
|
|
83
83
|
"jest-matcher-utils": "^30.4.1"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
|
+
"@jest/globals": "^30.4.1",
|
|
86
87
|
"@types/debug": "^4.1.13",
|
|
87
88
|
"@types/jasmine": "^5.1.15",
|
|
88
89
|
"@types/jest": "^30.0.0",
|
|
89
|
-
"@types/node": "^24.12.4",
|
|
90
90
|
"@types/mocha": "^10.0.10",
|
|
91
|
-
"@
|
|
91
|
+
"@types/node": "^24.12.4",
|
|
92
92
|
"@vitest/coverage-v8": "^4.1.7",
|
|
93
93
|
"@wdio/eslint": "^0.1.3",
|
|
94
94
|
"@wdio/types": "^9.27.2",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"npm-run-all2": "^9.0.1",
|
|
98
98
|
"release-it": "^20.2.0",
|
|
99
99
|
"rimraf": "^6.1.3",
|
|
100
|
-
"
|
|
100
|
+
"strip-ansi": "^7.2.0",
|
|
101
101
|
"typescript": "^5.9.3",
|
|
102
102
|
"vitest": "^4.1.7",
|
|
103
103
|
"webdriverio": "^9.27.2"
|
package/types/expect-global.d.ts
CHANGED
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
* Required when used in standalone mode (mocha) or to override the one of Jasmine
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
|
|
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
9
|
declare const expect: ExpectWebdriverIO.Expect
|
|
10
10
|
|
|
11
11
|
declare namespace NodeJS {
|
|
12
12
|
interface Global {
|
|
13
|
+
// @ts-expect-error: Both wdio & Jasmine augmentation declare different global expect explaining why TS is complaining here
|
|
13
14
|
expect: ExpectWebdriverIO.Expect
|
|
14
15
|
}
|
|
15
|
-
}
|
|
16
|
+
}
|
|
@@ -20,6 +20,7 @@ type ExpectLibSyncExpectationResult = import('expect').SyncExpectationResult
|
|
|
20
20
|
type ExpectLibAsyncExpectationResult = import('expect').AsyncExpectationResult
|
|
21
21
|
type ExpectLibExpectationResult = import('expect').ExpectationResult
|
|
22
22
|
type ExpectLibMatcherContext = import('expect').MatcherContext
|
|
23
|
+
type MatchersObject = Parameters<typeof import('expect').expect.extend>[0]
|
|
23
24
|
|
|
24
25
|
// Extracted from the expect library, this is the type of the matcher function used in the expect library.
|
|
25
26
|
type RawMatcherFn<Context extends ExpectLibMatcherContext = ExpectLibMatcherContext> = {
|
|
@@ -31,6 +32,7 @@ type RawMatcherFn<Context extends ExpectLibMatcherContext = ExpectLibMatcherCont
|
|
|
31
32
|
* Real Promise and wdio chainable promise types.
|
|
32
33
|
*/
|
|
33
34
|
type WdioPromiseLike<T = unknown> = PromiseLike<T> | ChainablePromiseElement | ChainablePromiseArray
|
|
35
|
+
type WdioElementOrPromiseLike<T = unknown> = WdioPromiseLike<T> | WebdriverIO.Element
|
|
34
36
|
type ElementPromise = Promise<WebdriverIO.Element>
|
|
35
37
|
type ElementArrayPromise = Promise<WebdriverIO.ElementArray>
|
|
36
38
|
|
|
@@ -201,7 +203,7 @@ interface WdioElementOrArrayMatchers<_R, ActualT = unknown> {
|
|
|
201
203
|
ActualT,
|
|
202
204
|
(
|
|
203
205
|
property: string,
|
|
204
|
-
value?: string | RegExp |
|
|
206
|
+
value?: string | RegExp | ExpectWebdriverIO.PartialMatcher<string> | null,
|
|
205
207
|
options?: ExpectWebdriverIO.StringOptions,
|
|
206
208
|
) => Promise<void>
|
|
207
209
|
>
|
|
@@ -396,18 +398,18 @@ interface WdioElementArrayOnlyMatchers<_R, ActualT = unknown> {
|
|
|
396
398
|
* Therefore, they also need to be redefined in the jest.d.ts file so correctly overload the matchers from the Jest namespace.
|
|
397
399
|
* @see jest.d.ts
|
|
398
400
|
*/
|
|
399
|
-
interface WdioJestOverloadedMatchers<
|
|
401
|
+
interface WdioJestOverloadedMatchers<R, ActualT> {
|
|
400
402
|
/**
|
|
401
403
|
* snapshot matcher
|
|
402
404
|
* @param label optional snapshot label
|
|
403
405
|
*/
|
|
404
|
-
toMatchSnapshot(label?: string): ActualT extends
|
|
406
|
+
toMatchSnapshot(label?: string): ActualT extends WdioElementOrPromiseLike ? Promise<void> : R
|
|
405
407
|
/**
|
|
406
408
|
* inline snapshot matcher
|
|
407
409
|
* @param snapshot snapshot string (autogenerated if not specified)
|
|
408
410
|
* @param label optional snapshot label
|
|
409
411
|
*/
|
|
410
|
-
toMatchInlineSnapshot(snapshot?: string, label?: string): ActualT extends
|
|
412
|
+
toMatchInlineSnapshot(snapshot?: string, label?: string): ActualT extends WdioElementOrPromiseLike ? Promise<void> : R
|
|
411
413
|
}
|
|
412
414
|
|
|
413
415
|
/**
|
|
@@ -466,8 +468,41 @@ type WdioAsymmetricMatchers = ExpectLibAsymmetricMatchers
|
|
|
466
468
|
type WdioAsymmetricMatcher<R> = ExpectWebdriverIO.PartialMatcher<R> & {
|
|
467
469
|
// Overwrite protected properties of expect.AsymmetricMatcher to access them
|
|
468
470
|
sample: R;
|
|
471
|
+
inverse?: boolean;
|
|
469
472
|
}
|
|
470
473
|
|
|
474
|
+
type JasmineBaseAsymmetricMatcher = {
|
|
475
|
+
jasmineToString(): string;
|
|
476
|
+
asymmetricMatch(other: unknown): boolean;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Jasmine asymetric matcher does not always use sample, some use expected. `any` uses even `expectedObject`
|
|
481
|
+
* @see https://github.com/jasmine/jasmine/tree/v5.13.0/src/core/asymmetric_equality
|
|
482
|
+
*/
|
|
483
|
+
type JasmineAsymmetricMatcher<R> = JasmineBaseAsymmetricMatcher & ({
|
|
484
|
+
expected: R;
|
|
485
|
+
} | {
|
|
486
|
+
sample: R;
|
|
487
|
+
} | {
|
|
488
|
+
regexp: string | RegExp;
|
|
489
|
+
} | {
|
|
490
|
+
expectedObject: R;
|
|
491
|
+
} | {} // jasmine.anything()
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
type JasmineStringContainingAsymmetricMatcher<R> = JasmineBaseAsymmetricMatcher & {
|
|
495
|
+
expected: R;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
type JasmineStringMatchingAsymmetricMatcher<R extends string | RegExp> = JasmineBaseAsymmetricMatcher & {
|
|
499
|
+
regexp: R;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
type JasmineStringAsymmetricMatcher<R extends string | RegExp> = JasmineStringContainingAsymmetricMatcher<R> | JasmineStringMatchingAsymmetricMatcher<R>
|
|
503
|
+
|
|
504
|
+
type AsymmetricMatcher<R> = WdioAsymmetricMatcher<R> | JasmineStringContainingAsymmetricMatcher<R> | (R extends string | RegExp ? JasmineStringMatchingAsymmetricMatcher<R> : never) | JasmineAsymmetricMatcher<R>
|
|
505
|
+
|
|
471
506
|
declare namespace ExpectWebdriverIO {
|
|
472
507
|
/**
|
|
473
508
|
* When importing expect from 'expect-webdriverio', instead of using globals this is the one used.
|
|
@@ -510,7 +545,13 @@ declare namespace ExpectWebdriverIO {
|
|
|
510
545
|
<T = unknown>(actual: T): T extends PromiseLike<unknown> ? ExpectWebdriverIO.MatchersAndInverse<void, T> & ExpectWebdriverIO.PromiseMatchers<T> : ExpectWebdriverIO.MatchersAndInverse<void, T>;
|
|
511
546
|
}
|
|
512
547
|
|
|
513
|
-
|
|
548
|
+
/**
|
|
549
|
+
* Matchers defining the custom wdio matchers.
|
|
550
|
+
* Matchers is documented as the interface to augment to add other custom matchers.
|
|
551
|
+
*
|
|
552
|
+
* We MUST NOT have Jest's expect Lib matchers here, so that we can use it with Jasmine augmentation as well.
|
|
553
|
+
*/
|
|
554
|
+
interface Matchers<R extends void | Promise<void>, T> extends WdioCustomMatchers<R, T> {}
|
|
514
555
|
|
|
515
556
|
interface AsymmetricMatchers extends WdioAsymmetricMatchers {}
|
|
516
557
|
|
|
@@ -520,7 +561,7 @@ declare namespace ExpectWebdriverIO {
|
|
|
520
561
|
* End of block overloading types from the expect library.
|
|
521
562
|
*/
|
|
522
563
|
|
|
523
|
-
type MatchersAndInverse<R extends void | Promise<void>, ActualT> = ExpectWebdriverIO.Matchers<R, ActualT> & ExpectLibInverse<ExpectWebdriverIO.Matchers<R, ActualT>>
|
|
564
|
+
type MatchersAndInverse<R extends void | Promise<void>, ActualT> = (ExpectWebdriverIO.Matchers<R, ActualT> & ExpectLibMatchers<R, ActualT>) & ExpectLibInverse<ExpectWebdriverIO.Matchers<R, ActualT> & ExpectLibMatchers<R, ActualT>>
|
|
524
565
|
|
|
525
566
|
/**
|
|
526
567
|
* Take from expect library
|
|
@@ -583,17 +624,25 @@ declare namespace ExpectWebdriverIO {
|
|
|
583
624
|
type AsyncAssertionResult = ExpectLibAsyncExpectationResult
|
|
584
625
|
|
|
585
626
|
/**
|
|
586
|
-
* Used
|
|
627
|
+
* Used to register wdio custom matcher like the Jest's `expect.extend`. Wdio main project configure the matchers in the runner when using Jasmine.
|
|
628
|
+
* Contains only the custom matchers from wdio, and not the ones from the expect library, to avoid any conflict with the matchers from the expect library when using Jasmine or Jest.
|
|
629
|
+
* Map to src/index.ts#wdioCustomMatchers
|
|
630
|
+
*
|
|
587
631
|
* Equivalent as `MatchersObject` from the expect library.
|
|
588
632
|
* @see https://github.com/jestjs/jest/blob/fd3d6cf9fe416b549a74b6577e5e1ea1130e3659/packages/expect/src/types.ts#L43C13-L43C27
|
|
589
633
|
*/
|
|
634
|
+
const wdioCustomMatchers: MatchersObject
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* @deprecated use `wdioCustomMatchers` instead
|
|
638
|
+
*/
|
|
590
639
|
const matchers: Map<string, RawMatcherFn>
|
|
591
640
|
|
|
592
641
|
interface AssertionHookParams {
|
|
593
642
|
/**
|
|
594
643
|
* name of the matcher, e.g. `toHaveText` or `toBeClickable`
|
|
595
644
|
*/
|
|
596
|
-
matcherName: keyof Matchers<void, unknown
|
|
645
|
+
matcherName: keyof Matchers<void, unknown>
|
|
597
646
|
/**
|
|
598
647
|
* Value that the user has passed in
|
|
599
648
|
*
|