expect-webdriverio 4.8.1 → 4.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +2 -2
- package/lib/matchers/snapshot.js +86 -0
- package/lib/matchers.js +2 -0
- package/lib/snapshot.js +72 -0
- package/package.json +4 -3
- package/types/expect-webdriverio.d.ts +20 -11
- package/types/standalone.d.ts +5 -0
package/lib/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { expect as expectLib } from 'expect';
|
|
2
2
|
import wdioMatchers from './matchers.js';
|
|
3
|
-
import * as expectUtils from './utils.js';
|
|
4
3
|
import { DEFAULT_OPTIONS } from './constants.js';
|
|
5
4
|
expectLib.extend({ ...wdioMatchers });
|
|
6
5
|
export const expect = expectLib;
|
|
@@ -14,4 +13,5 @@ export const setDefaultOptions = (options = {}) => {
|
|
|
14
13
|
});
|
|
15
14
|
};
|
|
16
15
|
export const setOptions = setDefaultOptions;
|
|
17
|
-
export
|
|
16
|
+
export * from './snapshot.js';
|
|
17
|
+
export * as utils from './utils.js';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { expect } from '../index.js';
|
|
3
|
+
import { SnapshotService } from '../snapshot.js';
|
|
4
|
+
function returnSnapshotError(snapshotError) {
|
|
5
|
+
try {
|
|
6
|
+
expect(snapshotError.actual).toBe(snapshotError.expected);
|
|
7
|
+
}
|
|
8
|
+
catch (e) {
|
|
9
|
+
return {
|
|
10
|
+
pass: false,
|
|
11
|
+
message: () => e.message
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
throw snapshotError;
|
|
15
|
+
}
|
|
16
|
+
function toMatchSnapshotAssert(received, message, inlineOptions) {
|
|
17
|
+
const snapshotService = SnapshotService.initiate();
|
|
18
|
+
try {
|
|
19
|
+
snapshotService.client.assert({
|
|
20
|
+
received,
|
|
21
|
+
message,
|
|
22
|
+
filepath: snapshotService.currentFilePath,
|
|
23
|
+
name: snapshotService.currentTestName,
|
|
24
|
+
...(inlineOptions ? {
|
|
25
|
+
...inlineOptions,
|
|
26
|
+
isInline: true
|
|
27
|
+
} : {
|
|
28
|
+
isInline: false
|
|
29
|
+
})
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
pass: true,
|
|
33
|
+
message: () => 'Snapshot matches'
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
return returnSnapshotError(e);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function toMatchSnapshotAsync(asyncReceived, message, inlineOptions) {
|
|
41
|
+
let received = await asyncReceived;
|
|
42
|
+
if (received && typeof received === 'object' && 'elementId' in received) {
|
|
43
|
+
received = await received.getHTML(true);
|
|
44
|
+
}
|
|
45
|
+
return toMatchSnapshotAssert(received, message, inlineOptions);
|
|
46
|
+
}
|
|
47
|
+
function toMatchSnapshotHelper(received, message, inlineOptions) {
|
|
48
|
+
const snapshotService = SnapshotService.initiate();
|
|
49
|
+
if (!snapshotService.currentFilePath || !snapshotService.currentTestName) {
|
|
50
|
+
throw new Error('Snapshot service is not initialized');
|
|
51
|
+
}
|
|
52
|
+
if (received && typeof received === 'object' &&
|
|
53
|
+
('elementId' in received ||
|
|
54
|
+
'then' in received)) {
|
|
55
|
+
return toMatchSnapshotAsync(received, message, inlineOptions);
|
|
56
|
+
}
|
|
57
|
+
return toMatchSnapshotAssert(received, message, inlineOptions);
|
|
58
|
+
}
|
|
59
|
+
export function toMatchSnapshot(received, message) {
|
|
60
|
+
return toMatchSnapshotHelper(received, message);
|
|
61
|
+
}
|
|
62
|
+
export function toMatchInlineSnapshot(received, inlineSnapshot, message) {
|
|
63
|
+
const browserErrorStack = this.errorStack;
|
|
64
|
+
function __INLINE_SNAPSHOT__(inlineSnapshot, message) {
|
|
65
|
+
const error = new Error('inline snapshot');
|
|
66
|
+
if (browserErrorStack && error.stack) {
|
|
67
|
+
error.stack = [
|
|
68
|
+
...error.stack.split('\n').slice(0, 3),
|
|
69
|
+
...browserErrorStack
|
|
70
|
+
.split('\n')
|
|
71
|
+
.slice(2)
|
|
72
|
+
.map((line) => line
|
|
73
|
+
.replace(/http:\/\/localhost:\d+/g, '')
|
|
74
|
+
.replace('/@fs/', '/'))
|
|
75
|
+
].join('\n');
|
|
76
|
+
}
|
|
77
|
+
error.stack = error.stack?.split('\n').filter((line) => (line.includes('__INLINE_SNAPSHOT__') ||
|
|
78
|
+
!(line.includes('__EXTERNAL_MATCHER_TRAP__') ||
|
|
79
|
+
line.includes(`expect-webdriverio${path.sep}lib${path.sep}matchers${path.sep}snapshot.js:`)))).join('\n');
|
|
80
|
+
return toMatchSnapshotHelper(received, message, {
|
|
81
|
+
inlineSnapshot,
|
|
82
|
+
error
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return __INLINE_SNAPSHOT__(inlineSnapshot, message);
|
|
86
|
+
}
|
package/lib/matchers.js
CHANGED
|
@@ -24,6 +24,7 @@ import * as toHaveStyle from './matchers/element/toHaveStyle.js';
|
|
|
24
24
|
import * as toBeRequested from './matchers/mock/toBeRequested.js';
|
|
25
25
|
import * as toBeRequestedTimes from './matchers/mock/toBeRequestedTimes.js';
|
|
26
26
|
import * as toBeRequestedWith from './matchers/mock/toBeRequestedWith.js';
|
|
27
|
+
import * as snapshotMatchers from './matchers/snapshot.js';
|
|
27
28
|
const matchers = {
|
|
28
29
|
...toHaveClipboardText,
|
|
29
30
|
...toHaveTitle,
|
|
@@ -51,6 +52,7 @@ const matchers = {
|
|
|
51
52
|
...toBeRequested,
|
|
52
53
|
...toBeRequestedTimes,
|
|
53
54
|
...toBeRequestedWith,
|
|
55
|
+
...snapshotMatchers
|
|
54
56
|
};
|
|
55
57
|
Object.keys(matchers).forEach((key) => {
|
|
56
58
|
if (key.endsWith('Fn')) {
|
package/lib/snapshot.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
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");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
6
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
7
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
9
|
+
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");
|
|
10
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
|
+
};
|
|
12
|
+
var _SnapshotService_instances, _SnapshotService_currentFilePath, _SnapshotService_currentTestName, _SnapshotService_options, _SnapshotService_snapshotResults, _SnapshotService_snapshotEnvironment, _SnapshotService_snapshotClient, _SnapshotService_isEqual;
|
|
13
|
+
import { expect } from '@wdio/globals';
|
|
14
|
+
import { SnapshotClient } from '@vitest/snapshot';
|
|
15
|
+
import { NodeSnapshotEnvironment } from '@vitest/snapshot/environment';
|
|
16
|
+
let service;
|
|
17
|
+
export class SnapshotService {
|
|
18
|
+
constructor(updateState) {
|
|
19
|
+
_SnapshotService_instances.add(this);
|
|
20
|
+
_SnapshotService_currentFilePath.set(this, void 0);
|
|
21
|
+
_SnapshotService_currentTestName.set(this, void 0);
|
|
22
|
+
_SnapshotService_options.set(this, void 0);
|
|
23
|
+
_SnapshotService_snapshotResults.set(this, []);
|
|
24
|
+
_SnapshotService_snapshotEnvironment.set(this, new NodeSnapshotEnvironment());
|
|
25
|
+
_SnapshotService_snapshotClient.set(this, new SnapshotClient({
|
|
26
|
+
isEqual: __classPrivateFieldGet(this, _SnapshotService_instances, "m", _SnapshotService_isEqual).bind(this),
|
|
27
|
+
}));
|
|
28
|
+
__classPrivateFieldSet(this, _SnapshotService_options, {
|
|
29
|
+
updateSnapshot: updateState,
|
|
30
|
+
snapshotEnvironment: __classPrivateFieldGet(this, _SnapshotService_snapshotEnvironment, "f"),
|
|
31
|
+
}, "f");
|
|
32
|
+
}
|
|
33
|
+
get currentFilePath() {
|
|
34
|
+
return __classPrivateFieldGet(this, _SnapshotService_currentFilePath, "f");
|
|
35
|
+
}
|
|
36
|
+
get currentTestName() {
|
|
37
|
+
return __classPrivateFieldGet(this, _SnapshotService_currentTestName, "f");
|
|
38
|
+
}
|
|
39
|
+
get client() {
|
|
40
|
+
return __classPrivateFieldGet(this, _SnapshotService_snapshotClient, "f");
|
|
41
|
+
}
|
|
42
|
+
get results() {
|
|
43
|
+
return __classPrivateFieldGet(this, _SnapshotService_snapshotResults, "f");
|
|
44
|
+
}
|
|
45
|
+
beforeTest(test) {
|
|
46
|
+
__classPrivateFieldSet(this, _SnapshotService_currentFilePath, test.file, "f");
|
|
47
|
+
__classPrivateFieldSet(this, _SnapshotService_currentTestName, `${test.parent} > ${test.title}`, "f");
|
|
48
|
+
__classPrivateFieldGet(this, _SnapshotService_snapshotClient, "f").startCurrentRun(test.file, test.fullTitle, __classPrivateFieldGet(this, _SnapshotService_options, "f"));
|
|
49
|
+
}
|
|
50
|
+
async afterTest() {
|
|
51
|
+
const result = await __classPrivateFieldGet(this, _SnapshotService_snapshotClient, "f").finishCurrentRun();
|
|
52
|
+
if (!result) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
__classPrivateFieldGet(this, _SnapshotService_snapshotResults, "f").push(result);
|
|
56
|
+
}
|
|
57
|
+
static initiate(updateState = 'new') {
|
|
58
|
+
if (!service) {
|
|
59
|
+
service = new SnapshotService(updateState);
|
|
60
|
+
}
|
|
61
|
+
return service;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
_SnapshotService_currentFilePath = new WeakMap(), _SnapshotService_currentTestName = new WeakMap(), _SnapshotService_options = new WeakMap(), _SnapshotService_snapshotResults = new WeakMap(), _SnapshotService_snapshotEnvironment = new WeakMap(), _SnapshotService_snapshotClient = new WeakMap(), _SnapshotService_instances = new WeakSet(), _SnapshotService_isEqual = function _SnapshotService_isEqual(received, expected) {
|
|
65
|
+
try {
|
|
66
|
+
expect(received).toBe(expected);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expect-webdriverio",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.9.1",
|
|
4
4
|
"author": "Mykola Grybyk <mykola.grybyk@gmail.com>",
|
|
5
5
|
"description": "WebdriverIO Assertion Library",
|
|
6
6
|
"license": "MIT",
|
|
@@ -75,8 +75,8 @@
|
|
|
75
75
|
"rimraf": "^5.0.5",
|
|
76
76
|
"shelljs": "^0.8.5",
|
|
77
77
|
"typescript": "^5.3.3",
|
|
78
|
-
"vitest": "1.
|
|
79
|
-
"webdriverio": "8.27.
|
|
78
|
+
"vitest": "1.2.0",
|
|
79
|
+
"webdriverio": "8.27.2"
|
|
80
80
|
},
|
|
81
81
|
"optionalDependencies": {
|
|
82
82
|
"@wdio/globals": "^8.27.0",
|
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
"webdriverio": "^8.27.0"
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
|
+
"@vitest/snapshot": "^1.2.1",
|
|
87
88
|
"expect": "^29.7.0",
|
|
88
89
|
"jest-matcher-utils": "^29.7.0",
|
|
89
90
|
"lodash.isequal": "^4.5.0"
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
declare namespace ExpectWebdriverIO {
|
|
2
|
-
|
|
3
|
-
* expect function declaration, containing two generics:
|
|
4
|
-
* - T: the type of the actual value, e.g. WebdriverIO.Browser or WebdriverIO.Element
|
|
5
|
-
* - R: the type of the return value, e.g. Promise<void> or void
|
|
6
|
-
*/
|
|
7
|
-
function expect<T = unknown, R extends void | Promise<void> = void | Promise<void>>(
|
|
8
|
-
actual: T
|
|
9
|
-
): Matchers<R, T>
|
|
2
|
+
const expect: ExpectWebdriverIO.Expect
|
|
10
3
|
function setOptions(options: DefaultOptions): void
|
|
11
4
|
function getConfig(): any
|
|
12
5
|
|
|
6
|
+
class SnapshotService {
|
|
7
|
+
static initiate(
|
|
8
|
+
updateState?: import('@vitest/snapshot').SnapshotUpdateState
|
|
9
|
+
): import('@wdio/types').Services.ServiceInstance & {
|
|
10
|
+
results: import('@vitest/snapshot').SnapshotResult[]
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
13
14
|
interface AssertionResult {
|
|
14
15
|
pass: boolean
|
|
15
16
|
message(): string
|
|
@@ -467,12 +468,10 @@ declare namespace ExpectWebdriverIO {
|
|
|
467
468
|
): R
|
|
468
469
|
|
|
469
470
|
// ==== network mock ====
|
|
470
|
-
|
|
471
471
|
/**
|
|
472
472
|
* Check that `WebdriverIO.Mock` was called
|
|
473
473
|
*/
|
|
474
474
|
toBeRequested(options?: ExpectWebdriverIO.CommandOptions): R
|
|
475
|
-
|
|
476
475
|
/**
|
|
477
476
|
* Check that `WebdriverIO.Mock` was called N times
|
|
478
477
|
*/
|
|
@@ -480,11 +479,21 @@ declare namespace ExpectWebdriverIO {
|
|
|
480
479
|
times: number | ExpectWebdriverIO.NumberOptions,
|
|
481
480
|
options?: ExpectWebdriverIO.NumberOptions
|
|
482
481
|
): R
|
|
483
|
-
|
|
484
482
|
/**
|
|
485
483
|
* Check that `WebdriverIO.Mock` was called with the specific parameters
|
|
486
484
|
*/
|
|
487
485
|
toBeRequestedWith(requestedWith: RequestedWith, options?: ExpectWebdriverIO.CommandOptions): R
|
|
486
|
+
/**
|
|
487
|
+
* snapshot matcher
|
|
488
|
+
* @param label optional snapshot label
|
|
489
|
+
*/
|
|
490
|
+
toMatchSnapshot(label?: string): R
|
|
491
|
+
/**
|
|
492
|
+
* inline snapshot matcher
|
|
493
|
+
* @param snapshot snapshot string (autogenerated if not specified)
|
|
494
|
+
* @param label optional snapshot label
|
|
495
|
+
*/
|
|
496
|
+
toMatchInlineSnapshot(snapshot?: string, label?: string): R
|
|
488
497
|
}
|
|
489
498
|
|
|
490
499
|
type RequestedWith = {
|
package/types/standalone.d.ts
CHANGED
|
@@ -10,6 +10,11 @@ declare namespace ExpectWebdriverIO {
|
|
|
10
10
|
rejects: Matchers<R, T>
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* expect function declaration, containing two generics:
|
|
15
|
+
* - T: the type of the actual value, e.g. WebdriverIO.Browser or WebdriverIO.Element
|
|
16
|
+
* - R: the type of the return value, e.g. Promise<void> or void
|
|
17
|
+
*/
|
|
13
18
|
type Expect = {
|
|
14
19
|
<T = unknown, R extends void | Promise<void> = void | Promise<void>>(actual: T): Matchers<R, T>
|
|
15
20
|
extend(map: Record<string, Function>): void
|