@wdio/visual-service 5.1.0 → 5.2.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/CHANGELOG.md +177 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +8 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/matcher.d.ts +0 -1
- package/dist/matcher.d.ts.map +1 -1
- package/dist/reporter.d.ts +14 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +97 -0
- package/dist/service.d.ts +4 -4
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +257 -58
- package/dist/storybook/launcher.d.ts.map +1 -1
- package/dist/storybook/launcher.js +4 -0
- package/dist/types.d.ts +13 -11
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +16 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +52 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,182 @@
|
|
|
1
1
|
# @wdio/visual-service
|
|
2
2
|
|
|
3
|
+
## 5.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 0b01b64: ### @wdio/visual-service
|
|
8
|
+
|
|
9
|
+
#### 🚀 New Features
|
|
10
|
+
|
|
11
|
+
**Added Reporting output**
|
|
12
|
+
You now have the option to export the compare results into a JSON report file. By enabling the module option `createJsonReportFiles: true`, each image that is compared will create a report stored in the `actual` folder, next to each `actual` image result.
|
|
13
|
+
|
|
14
|
+
The output will look like this:
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"parent": "check methods",
|
|
19
|
+
"test": "should fail comparing with a baseline",
|
|
20
|
+
"tag": "examplePageFail",
|
|
21
|
+
"instanceData": {
|
|
22
|
+
"browser": {
|
|
23
|
+
"name": "chrome-headless-shell",
|
|
24
|
+
"version": "126.0.6478.183"
|
|
25
|
+
},
|
|
26
|
+
"platform": {
|
|
27
|
+
"name": "mac",
|
|
28
|
+
"version": "not-known"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"commandName": "checkScreen",
|
|
32
|
+
"boundingBoxes": {
|
|
33
|
+
"diffBoundingBoxes": [
|
|
34
|
+
{
|
|
35
|
+
"left": 1088,
|
|
36
|
+
"top": 717,
|
|
37
|
+
"right": 1186,
|
|
38
|
+
"bottom": 730
|
|
39
|
+
}
|
|
40
|
+
//....
|
|
41
|
+
],
|
|
42
|
+
"ignoredBoxes": [
|
|
43
|
+
{
|
|
44
|
+
"left": 159,
|
|
45
|
+
"top": 652,
|
|
46
|
+
"right": 356,
|
|
47
|
+
"bottom": 703
|
|
48
|
+
}
|
|
49
|
+
//...
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
"fileData": {
|
|
53
|
+
"actualFilePath": "/Users/wswebcreation/Git/wdio/visual-testing/.tmp/actual/desktop_chrome-headless-shellexamplePageFail-local-chrome-latest-1366x768.png",
|
|
54
|
+
"baselineFilePath": "/Users/wswebcreation/Git/wdio/visual-testing/localBaseline/desktop_chrome-headless-shellexamplePageFail-local-chrome-latest-1366x768.png",
|
|
55
|
+
"diffFilePath": "/Users/wswebcreation/Git/wdio/visual-testing/.tmp/diff/desktop_chrome-headless-shell/examplePageFail-local-chrome-latest-1366x768png",
|
|
56
|
+
"fileName": "examplePageFail-local-chrome-latest-1366x768.png",
|
|
57
|
+
"size": {
|
|
58
|
+
"actual": {
|
|
59
|
+
"height": 768,
|
|
60
|
+
"width": 1366
|
|
61
|
+
},
|
|
62
|
+
"baseline": {
|
|
63
|
+
"height": 768,
|
|
64
|
+
"width": 1366
|
|
65
|
+
},
|
|
66
|
+
"diff": {
|
|
67
|
+
"height": 768,
|
|
68
|
+
"width": 1366
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"misMatchPercentage": "12.90",
|
|
73
|
+
"rawMisMatchPercentage": 12.900729014153246
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
When all tests are executed, a new JSON file with the collection of the comparisons will be generated and can be found in the root of your actual folder. The data is grouped by:
|
|
78
|
+
|
|
79
|
+
- `describe` for Jasmine/Mocha or `Feature` for CucumberJS
|
|
80
|
+
- `it` for Jasmine/Mocha or `Scenario` for CucumberJS
|
|
81
|
+
|
|
82
|
+
and then sorted by:
|
|
83
|
+
|
|
84
|
+
- `commandName`, which are the compare method names used to compare the images
|
|
85
|
+
- `instanceData`, browser first, then device, then platform
|
|
86
|
+
|
|
87
|
+
it will look like this
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
[
|
|
91
|
+
{
|
|
92
|
+
"description": "check methods",
|
|
93
|
+
"data": [
|
|
94
|
+
{
|
|
95
|
+
"test": "should fail comparing with a baseline",
|
|
96
|
+
"data": [
|
|
97
|
+
{
|
|
98
|
+
"tag": "examplePageFail",
|
|
99
|
+
"instanceData": {},
|
|
100
|
+
"commandName": "checkScreen",
|
|
101
|
+
"framework": "mocha",
|
|
102
|
+
"boundingBoxes": {
|
|
103
|
+
"diffBoundingBoxes": [],
|
|
104
|
+
"ignoredBoxes": []
|
|
105
|
+
},
|
|
106
|
+
"fileData": {},
|
|
107
|
+
"misMatchPercentage": "14.34",
|
|
108
|
+
"rawMisMatchPercentage": 14.335403703025868
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"tag": "exampleElementFail",
|
|
112
|
+
"instanceData": {},
|
|
113
|
+
"commandName": "checkElement",
|
|
114
|
+
"framework": "mocha",
|
|
115
|
+
"boundingBoxes": {
|
|
116
|
+
"diffBoundingBoxes": [],
|
|
117
|
+
"ignoredBoxes": []
|
|
118
|
+
},
|
|
119
|
+
"fileData": {},
|
|
120
|
+
"misMatchPercentage": "1.34",
|
|
121
|
+
"rawMisMatchPercentage": 1.335403703025868
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The report data will give you the opportunity to build your own visual report without doing all the magic and data collection yourself.
|
|
131
|
+
|
|
132
|
+
### webdriver-image-comparison
|
|
133
|
+
|
|
134
|
+
#### 🚀 New Features
|
|
135
|
+
|
|
136
|
+
- Add support to generate single JSON report files
|
|
137
|
+
|
|
138
|
+
### @wdio/ocr-service
|
|
139
|
+
|
|
140
|
+
#### 💅 Polish
|
|
141
|
+
|
|
142
|
+
- Refactored the CLI to use `@inquirer/prompts` instead of `inquirer`
|
|
143
|
+
|
|
144
|
+
### Committers: 1
|
|
145
|
+
|
|
146
|
+
- Wim Selles ([@wswebcreation](https://github.com/wswebcreation))
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Patch Changes
|
|
153
|
+
|
|
154
|
+
- Updated dependencies [0b01b64]
|
|
155
|
+
- webdriver-image-comparison@6.1.0
|
|
156
|
+
|
|
157
|
+
## 5.1.1
|
|
158
|
+
|
|
159
|
+
### Patch Changes
|
|
160
|
+
|
|
161
|
+
- 26c1a17: This release contains better support for Multiremote tests on the instances and global level, including better Native App support. This is related to issue https://github.com/webdriverio/visual-testing/issues/418 which is fixed by this release
|
|
162
|
+
|
|
163
|
+
# 💅 Polish
|
|
164
|
+
|
|
165
|
+
- cab1219: Update dependencies
|
|
166
|
+
- 2583542 / 8b1f837: add new tests
|
|
167
|
+
- eec29e1 / e2b2d38: update images
|
|
168
|
+
|
|
169
|
+
# 🐛 Bug Fixes
|
|
170
|
+
|
|
171
|
+
- 29f6f82 / 1ba9817: fix issue https://github.com/webdriverio/visual-testing/issues/418
|
|
172
|
+
|
|
173
|
+
# Committers: 1
|
|
174
|
+
|
|
175
|
+
- Wim Selles ([@wswebcreation](https://github.com/wswebcreation))
|
|
176
|
+
|
|
177
|
+
- Updated dependencies [26c1a17]
|
|
178
|
+
- webdriver-image-comparison@6.0.2
|
|
179
|
+
|
|
3
180
|
## 5.1.0
|
|
4
181
|
|
|
5
182
|
### Minor Changes
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export declare const V6_CLIP_SELECTOR = "#root > :first-child:not(script):not(style)";
|
|
2
2
|
export declare const CLIP_SELECTOR = "#storybook-root > :first-child:not(script):not(style)";
|
|
3
3
|
export declare const NUM_SHARDS = 1;
|
|
4
|
+
export declare const PAGE_OPTIONS_MAP: {
|
|
5
|
+
[key: string]: string;
|
|
6
|
+
};
|
|
4
7
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,gDAAgD,CAAA;AAC7E,eAAO,MAAM,aAAa,0DAA0D,CAAA;AACpF,eAAO,MAAM,UAAU,IAAI,CAAA"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,gDAAgD,CAAA;AAC7E,eAAO,MAAM,aAAa,0DAA0D,CAAA;AACpF,eAAO,MAAM,UAAU,IAAI,CAAA;AAC3B,eAAO,MAAM,gBAAgB,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAOrD,CAAA"}
|
package/dist/constants.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
1
|
export const V6_CLIP_SELECTOR = '#root > :first-child:not(script):not(style)';
|
|
2
2
|
export const CLIP_SELECTOR = '#storybook-root > :first-child:not(script):not(style)';
|
|
3
3
|
export const NUM_SHARDS = 1;
|
|
4
|
+
export const PAGE_OPTIONS_MAP = {
|
|
5
|
+
'saveScreen': 'saveScreenOptions',
|
|
6
|
+
'saveFullPageScreen': 'saveFullPageOptions',
|
|
7
|
+
'saveTabbablePage': 'saveTabbableOptions',
|
|
8
|
+
'checkScreen': 'checkScreenOptions',
|
|
9
|
+
'checkFullPageScreen': 'checkFullPageOptions',
|
|
10
|
+
'checkTabbablePage': 'checkTabbableOptions'
|
|
11
|
+
};
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/matcher.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="./expect-webdriverio.js" />
|
|
2
1
|
import type { WdioCheckFullPageMethodOptions, WdioCheckElementMethodOptions, WdioCheckScreenMethodOptions } from './types.js';
|
|
3
2
|
export declare function toMatchScreenSnapshot(browser: WebdriverIO.Browser, tag: string, expectedResultOrOptions?: number | ExpectWebdriverIO.PartialMatcher, optionsOrUndefined?: WdioCheckScreenMethodOptions): Promise<{
|
|
4
3
|
pass: boolean;
|
package/dist/matcher.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../src/matcher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../src/matcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACR,8BAA8B,EAC9B,6BAA6B,EAC7B,4BAA4B,EAC/B,MAAM,YAAY,CAAA;AA2FnB,wBAAsB,qBAAqB,CACvC,OAAO,EAAE,WAAW,CAAC,OAAO,EAC5B,GAAG,EAAE,MAAM,EACX,uBAAuB,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAAC,cAAc,EACnE,kBAAkB,CAAC,EAAE,4BAA4B;;;GAKpD;AAED,wBAAsB,uBAAuB,CACzC,OAAO,EAAE,WAAW,CAAC,OAAO,EAC5B,GAAG,EAAE,MAAM,EACX,uBAAuB,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAAC,cAAc,EACnE,kBAAkB,CAAC,EAAE,8BAA8B;;;GAKtD;AAED,wBAAsB,sBAAsB,CACxC,OAAO,EAAE,WAAW,CAAC,OAAO,EAC5B,GAAG,EAAE,MAAM,EACX,uBAAuB,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAAC,cAAc,EACnE,kBAAkB,CAAC,EAAE,6BAA6B;;;GAMrD;AAED,wBAAsB,2BAA2B,CAC7C,OAAO,EAAE,WAAW,CAAC,OAAO,EAC5B,GAAG,EAAE,MAAM,EACX,uBAAuB,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAAC,cAAc,EACnE,kBAAkB,CAAC,EAAE,8BAA8B;;;GAKtD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare class VisualReportGenerator {
|
|
2
|
+
directoryPath: string;
|
|
3
|
+
constructor({ directoryPath }: {
|
|
4
|
+
directoryPath: string;
|
|
5
|
+
});
|
|
6
|
+
generate(): void;
|
|
7
|
+
private readJsonFilesRecursively;
|
|
8
|
+
private readDirectory;
|
|
9
|
+
private readJsonFile;
|
|
10
|
+
private groupAndSortTestData;
|
|
11
|
+
private writeJsonToFile;
|
|
12
|
+
}
|
|
13
|
+
export default VisualReportGenerator;
|
|
14
|
+
//# sourceMappingURL=reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../src/reporter.ts"],"names":[],"mappings":"AAiBA,cAAM,qBAAqB;IACvB,aAAa,EAAE,MAAM,CAAA;gBAET,EAAE,aAAa,EAAE,EAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAC;IAI9C,QAAQ,IAAI,IAAI;IAcvB,OAAO,CAAC,wBAAwB;IAOhC,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,oBAAoB;IAsD5B,OAAO,CAAC,eAAe;CAG1B;AAED,eAAe,qBAAqB,CAAA"}
|
package/dist/reporter.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import logger from '@wdio/logger';
|
|
4
|
+
const log = logger('@wdio/visual-service:webdriver-image-comparison-reporter');
|
|
5
|
+
class VisualReportGenerator {
|
|
6
|
+
directoryPath;
|
|
7
|
+
constructor({ directoryPath }) {
|
|
8
|
+
this.directoryPath = directoryPath;
|
|
9
|
+
}
|
|
10
|
+
generate() {
|
|
11
|
+
try {
|
|
12
|
+
log.info('Generating visual report...');
|
|
13
|
+
const testData = this.readJsonFilesRecursively(this.directoryPath);
|
|
14
|
+
log.info('Read all json files');
|
|
15
|
+
const groupedAndSortedData = this.groupAndSortTestData(testData);
|
|
16
|
+
log.info('Grouped and sorted data');
|
|
17
|
+
this.writeJsonToFile(join(this.directoryPath, 'output.json'), groupedAndSortedData);
|
|
18
|
+
log.info('Report generated');
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
log.error('Error generating visual report:', e);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
readJsonFilesRecursively(directory) {
|
|
25
|
+
log.info(`Reading json files from ${directory}`);
|
|
26
|
+
const testData = [];
|
|
27
|
+
this.readDirectory(directory, testData);
|
|
28
|
+
return testData;
|
|
29
|
+
}
|
|
30
|
+
readDirectory(dir, testData) {
|
|
31
|
+
const items = fs.readdirSync(dir);
|
|
32
|
+
items.forEach(item => {
|
|
33
|
+
const fullPath = join(dir, item);
|
|
34
|
+
const stat = fs.statSync(fullPath);
|
|
35
|
+
if (stat.isDirectory()) {
|
|
36
|
+
this.readDirectory(fullPath, testData);
|
|
37
|
+
}
|
|
38
|
+
else if (stat.isFile() && item.endsWith('-report.json')) {
|
|
39
|
+
this.readJsonFile(fullPath, testData);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
readJsonFile(filePath, testData) {
|
|
44
|
+
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
45
|
+
const jsonContent = JSON.parse(fileContent);
|
|
46
|
+
testData.push(jsonContent); // Add JSON content to testData array
|
|
47
|
+
}
|
|
48
|
+
groupAndSortTestData(testData) {
|
|
49
|
+
const groupedData = [];
|
|
50
|
+
// Grouping by description and test
|
|
51
|
+
testData.forEach(report => {
|
|
52
|
+
const mainTestName = report.description;
|
|
53
|
+
let mainGroup = groupedData.find(group => group.description === mainTestName);
|
|
54
|
+
if (!mainGroup) {
|
|
55
|
+
mainGroup = { description: mainTestName, data: [] };
|
|
56
|
+
groupedData.push(mainGroup);
|
|
57
|
+
}
|
|
58
|
+
let testGroup = mainGroup.data.find(test => test.test === report.test);
|
|
59
|
+
if (!testGroup) {
|
|
60
|
+
testGroup = { test: report.test, data: [] };
|
|
61
|
+
mainGroup.data.push(testGroup);
|
|
62
|
+
}
|
|
63
|
+
testGroup.data.push(report);
|
|
64
|
+
});
|
|
65
|
+
// Sorting within each group
|
|
66
|
+
groupedData.forEach(mainGroup => {
|
|
67
|
+
mainGroup.data.forEach(testGroup => {
|
|
68
|
+
testGroup.data.sort((a, b) => {
|
|
69
|
+
// Sort by commandName
|
|
70
|
+
if (a.commandName !== b.commandName) {
|
|
71
|
+
return a.commandName.localeCompare(b.commandName);
|
|
72
|
+
}
|
|
73
|
+
// Sort by instanceData (browser first, then device, then platform)
|
|
74
|
+
const aBrowserName = a.instanceData.browser?.name || '';
|
|
75
|
+
const bBrowserName = b.instanceData.browser?.name || '';
|
|
76
|
+
if (aBrowserName !== bBrowserName) {
|
|
77
|
+
return aBrowserName.localeCompare(bBrowserName);
|
|
78
|
+
}
|
|
79
|
+
const aDeviceName = a.instanceData.deviceName || '';
|
|
80
|
+
const bDeviceName = b.instanceData.deviceName || '';
|
|
81
|
+
if (aDeviceName !== bDeviceName) {
|
|
82
|
+
return aDeviceName.localeCompare(bDeviceName);
|
|
83
|
+
}
|
|
84
|
+
if (a.instanceData.platform.name !== b.instanceData.platform.name) {
|
|
85
|
+
return a.instanceData.platform.name.localeCompare(b.instanceData.platform.name);
|
|
86
|
+
}
|
|
87
|
+
return 0;
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
return groupedData;
|
|
92
|
+
}
|
|
93
|
+
writeJsonToFile(filePath, data) {
|
|
94
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export default VisualReportGenerator;
|
package/dist/service.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import type { Frameworks } from '@wdio/types';
|
|
2
|
-
import type { ClassOptions } from 'webdriver-image-comparison';
|
|
3
2
|
import { BaseClass } from 'webdriver-image-comparison';
|
|
3
|
+
import type { VisualServiceOptions } from './types.js';
|
|
4
4
|
export default class WdioImageComparisonService extends BaseClass {
|
|
5
5
|
#private;
|
|
6
|
-
private _browser?;
|
|
7
6
|
private _isNativeContext;
|
|
8
|
-
constructor(options:
|
|
7
|
+
constructor(options: VisualServiceOptions, _: WebdriverIO.Capabilities, config: WebdriverIO.Config);
|
|
9
8
|
/**
|
|
10
9
|
* Set up the service if users want to use it in standalone mode
|
|
11
10
|
*/
|
|
12
11
|
remoteSetup(browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser): Promise<void>;
|
|
13
12
|
before(capabilities: WebdriverIO.Capabilities, _specs: string[], browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser): Promise<void>;
|
|
14
|
-
beforeTest(test: Frameworks.Test): void
|
|
13
|
+
beforeTest(test: Frameworks.Test): Promise<void>;
|
|
14
|
+
beforeScenario(world: Frameworks.World): void;
|
|
15
15
|
afterCommand(commandName: string, _args: string[], result: number | string, error: any): void;
|
|
16
16
|
}
|
|
17
17
|
//# sourceMappingURL=service.d.ts.map
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EACH,SAAS,EAWZ,MAAM,4BAA4B,CAAA;AAYnC,OAAO,KAAK,EAA+C,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAenG,MAAM,CAAC,OAAO,OAAO,0BAA2B,SAAQ,SAAS;;IAM7D,OAAO,CAAC,gBAAgB,CAA+B;gBAE3C,OAAO,EAAE,oBAAoB,EAAE,CAAC,EAAE,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM;IAOlG;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,kBAAkB;IAIzE,MAAM,CACR,YAAY,EAAE,WAAW,CAAC,YAAY,EACtC,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,EAAE,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,kBAAkB;IAgC3D,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI;IAOtC,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,KAAK;IAItC,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,GAAG;CAsWzF"}
|
package/dist/service.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import logger from '@wdio/logger';
|
|
2
2
|
import { expect } from '@wdio/globals';
|
|
3
3
|
import { dirname, normalize, resolve } from 'node:path';
|
|
4
|
-
import { BaseClass, checkElement, checkFullPageScreen, checkScreen, saveElement, saveFullPageScreen, saveScreen, saveTabbablePage, checkTabbablePage, FOLDERS, } from 'webdriver-image-comparison';
|
|
5
|
-
import {
|
|
4
|
+
import { BaseClass, checkElement, checkFullPageScreen, checkScreen, saveElement, saveFullPageScreen, saveScreen, saveTabbablePage, checkTabbablePage, FOLDERS, DEFAULT_TEST_CONTEXT, } from 'webdriver-image-comparison';
|
|
5
|
+
import { SevereServiceError } from 'webdriverio';
|
|
6
|
+
import { determineNativeContext, enrichTestContext, getFolders, getInstanceData, getNativeContext } from './utils.js';
|
|
6
7
|
import { toMatchScreenSnapshot, toMatchFullPageSnapshot, toMatchElementSnapshot, toMatchTabbablePageSnapshot } from './matcher.js';
|
|
7
8
|
import { waitForStorybookComponentToBeLoaded } from './storybook/utils.js';
|
|
9
|
+
import { PAGE_OPTIONS_MAP } from './constants.js';
|
|
8
10
|
const log = logger('@wdio/visual-service');
|
|
9
11
|
const elementCommands = { saveElement, checkElement };
|
|
10
12
|
const pageCommands = {
|
|
@@ -20,12 +22,14 @@ export default class WdioImageComparisonService extends BaseClass {
|
|
|
20
22
|
#config;
|
|
21
23
|
#currentFile;
|
|
22
24
|
#currentFilePath;
|
|
23
|
-
|
|
25
|
+
#testContext;
|
|
26
|
+
#browser;
|
|
24
27
|
_isNativeContext;
|
|
25
28
|
constructor(options, _, config) {
|
|
26
29
|
super(options);
|
|
27
30
|
this.#config = config;
|
|
28
31
|
this._isNativeContext = undefined;
|
|
32
|
+
this.#testContext = DEFAULT_TEST_CONTEXT;
|
|
29
33
|
}
|
|
30
34
|
/**
|
|
31
35
|
* Set up the service if users want to use it in standalone mode
|
|
@@ -34,15 +38,18 @@ export default class WdioImageComparisonService extends BaseClass {
|
|
|
34
38
|
await this.before(browser.capabilities, [], browser);
|
|
35
39
|
}
|
|
36
40
|
async before(capabilities, _specs, browser) {
|
|
37
|
-
this
|
|
38
|
-
this._isNativeContext = determineNativeContext(this
|
|
39
|
-
if (!this.
|
|
41
|
+
this.#browser = browser;
|
|
42
|
+
this._isNativeContext = determineNativeContext(this.#browser);
|
|
43
|
+
if (!this.#browser.isMultiremote) {
|
|
40
44
|
log.info('Adding commands to global browser');
|
|
41
|
-
await this.#addCommandsToBrowser(this
|
|
45
|
+
await this.#addCommandsToBrowser(this.#browser);
|
|
42
46
|
}
|
|
43
47
|
else {
|
|
44
48
|
await this.#extendMultiremoteBrowser(capabilities);
|
|
45
49
|
}
|
|
50
|
+
if (browser.isMultiremote) {
|
|
51
|
+
this.#setupMultiremoteContextListener();
|
|
52
|
+
}
|
|
46
53
|
/**
|
|
47
54
|
* add custom matcher for visual comparison when expect has been added.
|
|
48
55
|
* this is not the case in standalone mode
|
|
@@ -59,14 +66,20 @@ export default class WdioImageComparisonService extends BaseClass {
|
|
|
59
66
|
log.warn('Expect package not found. This means that the custom matchers `toMatchScreenSnapshot|toMatchFullPageSnapshot|toMatchElementSnapshot|toMatchTabbablePageSnapshot` are not added and can not be used. Please make sure to add it to your `package.json` if you want to use the Visual custom matchers.');
|
|
60
67
|
}
|
|
61
68
|
}
|
|
62
|
-
beforeTest(test) {
|
|
69
|
+
async beforeTest(test) {
|
|
63
70
|
this.#currentFile = (test.file || test.filename);
|
|
64
71
|
this.#currentFilePath = resolve(dirname(this.#currentFile), FOLDERS.DEFAULT.BASE);
|
|
72
|
+
this.#testContext = this.#getTestContext(test);
|
|
73
|
+
}
|
|
74
|
+
// For Cucumber only
|
|
75
|
+
beforeScenario(world) {
|
|
76
|
+
this.#testContext = this.#getTestContext(world);
|
|
65
77
|
}
|
|
66
78
|
afterCommand(commandName, _args, result, error) {
|
|
67
79
|
// This is for the cases where in the E2E tests we switch to a WEBVIEW or back to NATIVE_APP context
|
|
68
80
|
if (commandName === 'getContext' && error === undefined && typeof result === 'string') {
|
|
69
|
-
|
|
81
|
+
// Multiremote logic is handled in the `before` method during an event listener
|
|
82
|
+
this._isNativeContext = this.#browser?.isMultiremote ? this._isNativeContext : result.includes('NATIVE');
|
|
70
83
|
}
|
|
71
84
|
}
|
|
72
85
|
#getBaselineFolder() {
|
|
@@ -86,81 +99,267 @@ export default class WdioImageComparisonService extends BaseClass {
|
|
|
86
99
|
}
|
|
87
100
|
return baselineFolder;
|
|
88
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Add commands to the Multi Remote browser object
|
|
104
|
+
*/
|
|
89
105
|
async #extendMultiremoteBrowser(capabilities) {
|
|
90
|
-
const browser = this
|
|
106
|
+
const browser = this.#browser;
|
|
91
107
|
const browserNames = Object.keys(capabilities);
|
|
92
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Add all the commands to each browser in the Multi Remote
|
|
110
|
+
*/
|
|
93
111
|
for (const browserName of browserNames) {
|
|
94
|
-
|
|
95
|
-
const browserInstance =
|
|
112
|
+
log.info(`Adding commands to Multi Browser: ${browserName}`);
|
|
113
|
+
const browserInstance = browser.getInstance(browserName);
|
|
96
114
|
await this.#addCommandsToBrowser(browserInstance);
|
|
97
115
|
}
|
|
98
116
|
/**
|
|
99
117
|
* Add all the commands to the global browser object that will execute
|
|
100
118
|
* on each browser in the Multi Remote
|
|
119
|
+
* Start with the page commands
|
|
101
120
|
*/
|
|
102
|
-
for (const command of
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const returnData = {};
|
|
112
|
-
for (const browserName of browserNames) {
|
|
113
|
-
const multiremoteBrowser = browser;
|
|
114
|
-
const browserInstance = multiremoteBrowser.getInstance(browserName);
|
|
115
|
-
/**
|
|
116
|
-
* casting command to `checkScreen` to simplify type handling here
|
|
117
|
-
*/
|
|
118
|
-
returnData[browserName] = browserInstance[command].call(browserInstance, ...args);
|
|
119
|
-
}
|
|
120
|
-
return returnData;
|
|
121
|
-
});
|
|
122
|
-
}
|
|
121
|
+
for (const [commandName, command] of Object.entries(pageCommands)) {
|
|
122
|
+
this.#addMultiremoteCommand(browser, browserNames, commandName, command);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Add all the element commands to the global browser object that will execute
|
|
126
|
+
* on each browser in the Multi Remote
|
|
127
|
+
*/
|
|
128
|
+
for (const [commandName, command] of Object.entries(elementCommands)) {
|
|
129
|
+
this.#addMultiremoteElementCommand(browser, browserNames, commandName, command);
|
|
123
130
|
}
|
|
124
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Add commands to the "normal" browser object
|
|
134
|
+
*/
|
|
125
135
|
async #addCommandsToBrowser(currentBrowser) {
|
|
126
136
|
const instanceData = await getInstanceData(currentBrowser);
|
|
127
|
-
const
|
|
137
|
+
const isNativeContext = getNativeContext(this.#browser, currentBrowser, this._isNativeContext);
|
|
128
138
|
for (const [commandName, command] of Object.entries(elementCommands)) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
139
|
+
this.#addElementCommand(currentBrowser, commandName, command, instanceData, isNativeContext);
|
|
140
|
+
}
|
|
141
|
+
for (const [commandName, command] of Object.entries(pageCommands)) {
|
|
142
|
+
this.#addPageCommand(currentBrowser, commandName, command, instanceData, isNativeContext);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Add new element commands to the browser object
|
|
147
|
+
*/
|
|
148
|
+
#addElementCommand(browser, commandName, command, instanceData, isNativeContext) {
|
|
149
|
+
log.info(`Adding element command "${commandName}" to browser object`);
|
|
150
|
+
const self = this;
|
|
151
|
+
browser.addCommand(commandName, function (element, tag, elementOptions = {}) {
|
|
152
|
+
const elementOptionsKey = commandName === 'saveElement' ? 'saveElementOptions' : 'checkElementOptions';
|
|
153
|
+
return command({
|
|
154
|
+
methods: {
|
|
132
155
|
executor: (script, ...varArgs) => {
|
|
133
|
-
return this.execute.bind(
|
|
156
|
+
return this.execute.bind(browser)(script, ...varArgs);
|
|
134
157
|
},
|
|
135
|
-
getElementRect: this.getElementRect.bind(
|
|
136
|
-
screenShot: this.takeScreenshot.bind(
|
|
137
|
-
takeElementScreenshot: this.takeElementScreenshot.bind(
|
|
138
|
-
},
|
|
158
|
+
getElementRect: this.getElementRect.bind(browser),
|
|
159
|
+
screenShot: this.takeScreenshot.bind(browser),
|
|
160
|
+
takeElementScreenshot: this.takeElementScreenshot.bind(browser),
|
|
161
|
+
},
|
|
162
|
+
instanceData,
|
|
163
|
+
folders: getFolders(elementOptions, self.folders, self.#getBaselineFolder()),
|
|
164
|
+
element,
|
|
165
|
+
tag,
|
|
166
|
+
[elementOptionsKey]: {
|
|
139
167
|
wic: self.defaultOptions,
|
|
140
168
|
method: elementOptions,
|
|
141
|
-
},
|
|
169
|
+
},
|
|
170
|
+
isNativeContext,
|
|
171
|
+
testContext: enrichTestContext({
|
|
172
|
+
commandName,
|
|
173
|
+
currentTestContext: self.#testContext,
|
|
174
|
+
instanceData,
|
|
175
|
+
tag,
|
|
176
|
+
})
|
|
142
177
|
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Add new page commands to the browser object
|
|
182
|
+
*/
|
|
183
|
+
#addPageCommand(browser, commandName, command, instanceData, isNativeContext) {
|
|
184
|
+
log.info(`Adding browser command "${commandName}" to browser object`);
|
|
185
|
+
const self = this;
|
|
186
|
+
const pageOptionsKey = PAGE_OPTIONS_MAP[commandName];
|
|
187
|
+
if (commandName === 'waitForStorybookComponentToBeLoaded') {
|
|
188
|
+
browser.addCommand(commandName, (options) => waitForStorybookComponentToBeLoaded(options));
|
|
143
189
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
190
|
+
else {
|
|
191
|
+
browser.addCommand(commandName, function (tag, pageOptions = {}) {
|
|
192
|
+
return command({
|
|
193
|
+
methods: {
|
|
194
|
+
executor: (script, ...varArgs) => {
|
|
195
|
+
return this.execute.bind(browser)(script, ...varArgs);
|
|
196
|
+
},
|
|
197
|
+
getElementRect: this.getElementRect.bind(browser),
|
|
198
|
+
screenShot: this.takeScreenshot.bind(browser),
|
|
199
|
+
},
|
|
200
|
+
instanceData,
|
|
201
|
+
folders: getFolders(pageOptions, self.folders, self.#getBaselineFolder()),
|
|
202
|
+
tag,
|
|
203
|
+
[pageOptionsKey]: {
|
|
204
|
+
wic: self.defaultOptions,
|
|
205
|
+
method: pageOptions,
|
|
206
|
+
},
|
|
207
|
+
isNativeContext,
|
|
208
|
+
testContext: enrichTestContext({
|
|
209
|
+
commandName,
|
|
210
|
+
currentTestContext: self.#testContext,
|
|
211
|
+
instanceData,
|
|
212
|
+
tag,
|
|
213
|
+
})
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
#addMultiremoteElementCommand(browser, browserNames, commandName, command) {
|
|
219
|
+
log.info(`Adding element command "${commandName}" to Multi browser object`);
|
|
220
|
+
const self = this;
|
|
221
|
+
browser.addCommand(commandName, async function (tag, element, pageOptions = {}) {
|
|
222
|
+
const returnData = {};
|
|
223
|
+
const elementOptionsKey = commandName === 'saveElement' ? 'saveElementOptions' : 'checkElementOptions';
|
|
224
|
+
for (const browserName of browserNames) {
|
|
225
|
+
const browserInstance = browser.getInstance(browserName);
|
|
226
|
+
const isNativeContext = getNativeContext(self.#browser, browserInstance, self._isNativeContext);
|
|
227
|
+
const instanceData = await getInstanceData(browserInstance);
|
|
228
|
+
returnData[browserName] = await command({
|
|
229
|
+
methods: {
|
|
152
230
|
executor: (script, ...varArgs) => {
|
|
153
|
-
return
|
|
231
|
+
return browserInstance.execute.bind(browserInstance)(script, ...varArgs);
|
|
154
232
|
},
|
|
155
|
-
getElementRect:
|
|
156
|
-
screenShot:
|
|
157
|
-
|
|
158
|
-
|
|
233
|
+
getElementRect: browserInstance.getElementRect.bind(browserInstance),
|
|
234
|
+
screenShot: browserInstance.takeScreenshot.bind(browserInstance),
|
|
235
|
+
takeElementScreenshot: browserInstance.takeElementScreenshot.bind(browserInstance),
|
|
236
|
+
},
|
|
237
|
+
instanceData,
|
|
238
|
+
folders: getFolders(pageOptions, self.folders, self.#getBaselineFolder()),
|
|
239
|
+
tag,
|
|
240
|
+
element,
|
|
241
|
+
[elementOptionsKey]: {
|
|
159
242
|
wic: self.defaultOptions,
|
|
160
243
|
method: pageOptions,
|
|
161
|
-
},
|
|
244
|
+
},
|
|
245
|
+
isNativeContext,
|
|
246
|
+
testContext: enrichTestContext({
|
|
247
|
+
commandName,
|
|
248
|
+
currentTestContext: self.#testContext,
|
|
249
|
+
instanceData,
|
|
250
|
+
tag,
|
|
251
|
+
})
|
|
162
252
|
});
|
|
163
253
|
}
|
|
254
|
+
return returnData;
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
#addMultiremoteCommand(browser, browserNames, commandName, command) {
|
|
258
|
+
log.info(`Adding browser command "${commandName}" to Multi browser object`);
|
|
259
|
+
const self = this;
|
|
260
|
+
if (commandName === 'waitForStorybookComponentToBeLoaded') {
|
|
261
|
+
browser.addCommand(commandName, waitForStorybookComponentToBeLoaded);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
browser.addCommand(commandName, async function (tag, pageOptions = {}) {
|
|
265
|
+
const returnData = {};
|
|
266
|
+
const pageOptionsKey = PAGE_OPTIONS_MAP[commandName];
|
|
267
|
+
for (const browserName of browserNames) {
|
|
268
|
+
const browserInstance = browser.getInstance(browserName);
|
|
269
|
+
const isNativeContext = getNativeContext(self.#browser, browserInstance, self._isNativeContext);
|
|
270
|
+
const instanceData = await getInstanceData(browserInstance);
|
|
271
|
+
returnData[browserName] = await command({
|
|
272
|
+
methods: {
|
|
273
|
+
executor: (script, ...varArgs) => {
|
|
274
|
+
return browserInstance.execute.bind(browserInstance)(script, ...varArgs);
|
|
275
|
+
},
|
|
276
|
+
getElementRect: browserInstance.getElementRect.bind(browserInstance),
|
|
277
|
+
screenShot: browserInstance.takeScreenshot.bind(browserInstance),
|
|
278
|
+
},
|
|
279
|
+
instanceData,
|
|
280
|
+
folders: getFolders(pageOptions, self.folders, self.#getBaselineFolder()),
|
|
281
|
+
tag,
|
|
282
|
+
[pageOptionsKey]: {
|
|
283
|
+
wic: self.defaultOptions,
|
|
284
|
+
method: pageOptions,
|
|
285
|
+
},
|
|
286
|
+
isNativeContext,
|
|
287
|
+
testContext: enrichTestContext({
|
|
288
|
+
commandName,
|
|
289
|
+
currentTestContext: self.#testContext,
|
|
290
|
+
instanceData,
|
|
291
|
+
tag,
|
|
292
|
+
})
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
return returnData;
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
#setupMultiremoteContextListener() {
|
|
300
|
+
const multiremoteBrowser = this.#browser;
|
|
301
|
+
const browserInstances = multiremoteBrowser.instances;
|
|
302
|
+
for (const instanceName of browserInstances) {
|
|
303
|
+
const instance = multiremoteBrowser[instanceName];
|
|
304
|
+
instance.on('result', (result) => {
|
|
305
|
+
if (result.command === 'getContext') {
|
|
306
|
+
const value = result.result.value;
|
|
307
|
+
const sessionId = instance.sessionId;
|
|
308
|
+
if (typeof this._isNativeContext !== 'object' || this._isNativeContext === null) {
|
|
309
|
+
this._isNativeContext = {};
|
|
310
|
+
}
|
|
311
|
+
this._isNativeContext[sessionId] = value.includes('NATIVE');
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
#getTestContext(test) {
|
|
317
|
+
const framework = this.#config?.framework;
|
|
318
|
+
if (framework === 'mocha' && test) {
|
|
319
|
+
return {
|
|
320
|
+
...this.#testContext,
|
|
321
|
+
framework: 'mocha',
|
|
322
|
+
parent: test.parent,
|
|
323
|
+
title: test.title,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
else if (framework === 'jasmine' && test) {
|
|
327
|
+
/**
|
|
328
|
+
* When using Jasmine as the framework the title/parent are not set as with mocha.
|
|
329
|
+
*
|
|
330
|
+
* `fullName` contains all describe(), and it() separated by a space.
|
|
331
|
+
* `description` contains the current it() statement.
|
|
332
|
+
*
|
|
333
|
+
* e.g.:
|
|
334
|
+
* With the following configuration
|
|
335
|
+
*
|
|
336
|
+
* describe('x', () => {
|
|
337
|
+
* describe('y', () => {
|
|
338
|
+
* it('z', () => {});
|
|
339
|
+
* })
|
|
340
|
+
* })
|
|
341
|
+
*
|
|
342
|
+
* fullName will be "x y z"
|
|
343
|
+
* description will be "z"
|
|
344
|
+
*
|
|
345
|
+
*/
|
|
346
|
+
const { description: title, fullName } = test;
|
|
347
|
+
return {
|
|
348
|
+
...this.#testContext,
|
|
349
|
+
framework: 'jasmine',
|
|
350
|
+
parent: fullName?.replace(` ${title}`, ''),
|
|
351
|
+
title: title,
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
else if (framework === 'cucumber' && test) {
|
|
355
|
+
return {
|
|
356
|
+
...this.#testContext,
|
|
357
|
+
framework: 'cucumber',
|
|
358
|
+
// @ts-ignore
|
|
359
|
+
parent: test?.gherkinDocument?.feature?.name,
|
|
360
|
+
title: test?.pickle?.name,
|
|
361
|
+
};
|
|
164
362
|
}
|
|
363
|
+
throw new SevereServiceError(`Framework ${framework} is not supported by the Visual Service and should be either "mocha", "jasmine" or "cucumber".`);
|
|
165
364
|
}
|
|
166
365
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../../src/storybook/launcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../../src/storybook/launcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAetD,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,SAAS;;gBAGrC,OAAO,EAAE,YAAY;IAK3B,SAAS,CAAE,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,YAAY,EAAE,YAAY,CAAC,kBAAkB;IAuEpF,UAAU;CAuBnB"}
|
|
@@ -4,6 +4,7 @@ import { SevereServiceError } from 'webdriverio';
|
|
|
4
4
|
import { BaseClass } from 'webdriver-image-comparison';
|
|
5
5
|
import { createStorybookCapabilities, createTestFiles, getArgvValue, isCucumberFramework, isStorybookMode, parseSkipStories, scanStorybook, } from './utils.js';
|
|
6
6
|
import { CLIP_SELECTOR, NUM_SHARDS, V6_CLIP_SELECTOR } from '../constants.js';
|
|
7
|
+
import generateVisualReport from '../reporter.js';
|
|
7
8
|
const log = logger('@wdio/visual-service');
|
|
8
9
|
export default class VisualLauncher extends BaseClass {
|
|
9
10
|
#options;
|
|
@@ -91,5 +92,8 @@ export default class VisualLauncher extends BaseClass {
|
|
|
91
92
|
delete process.env.VISUAL_STORYBOOK_URL;
|
|
92
93
|
delete process.env.VISUAL_STORYBOOK_CLIP_SELECTOR;
|
|
93
94
|
}
|
|
95
|
+
if (this.#options.createJsonReportFiles) {
|
|
96
|
+
new generateVisualReport({ directoryPath: this.folders.actualFolder }).generate();
|
|
97
|
+
}
|
|
94
98
|
}
|
|
95
99
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import type { ScreenshotOutput, ImageCompareResult, CheckScreenMethodOptions, SaveScreenMethodOptions, CheckElementMethodOptions, SaveElementMethodOptions, CheckFullPageMethodOptions, SaveFullPageMethodOptions, ClassOptions } from 'webdriver-image-comparison';
|
|
2
|
-
import type { RectanglesOutput } from 'webdriver-image-comparison/dist/methods/rectangles.interfaces.js';
|
|
3
|
-
import type { WaitForStorybookComponentToBeLoaded } from './storybook/Types.js';
|
|
4
2
|
type MultiOutput = {
|
|
5
3
|
[browserName: string]: ScreenshotOutput;
|
|
6
4
|
};
|
|
@@ -9,6 +7,19 @@ type MultiResult = {
|
|
|
9
7
|
[browserName: string]: ImageCompareResult | number;
|
|
10
8
|
};
|
|
11
9
|
export type Result = MultiResult | (ImageCompareResult | number);
|
|
10
|
+
export type NativeContextType = boolean | Record<string, boolean>;
|
|
11
|
+
export type MultiremoteCommandResult = {
|
|
12
|
+
command: string;
|
|
13
|
+
method: string;
|
|
14
|
+
endpoint: string;
|
|
15
|
+
body: Record<string, any>;
|
|
16
|
+
result: {
|
|
17
|
+
value: string;
|
|
18
|
+
};
|
|
19
|
+
sessionId: string | undefined;
|
|
20
|
+
cid: string;
|
|
21
|
+
type: string;
|
|
22
|
+
};
|
|
12
23
|
export interface WdioIcsCommonOptions {
|
|
13
24
|
hideElements?: WebdriverIO.Element[];
|
|
14
25
|
removeElements?: WebdriverIO.Element[];
|
|
@@ -30,14 +41,5 @@ export interface WdioCheckScreenMethodOptions extends Omit<CheckScreenMethodOpti
|
|
|
30
41
|
}
|
|
31
42
|
export interface VisualServiceOptions extends ClassOptions {
|
|
32
43
|
}
|
|
33
|
-
export type PageCommandOptions = {
|
|
34
|
-
executor: <T>(script: string | ((...innerArgs: any[]) => unknown), ...varArgs: any[]) => Promise<T>;
|
|
35
|
-
getElementRect: (elementId: string) => Promise<RectanglesOutput>;
|
|
36
|
-
screenShot: () => Promise<string>;
|
|
37
|
-
};
|
|
38
|
-
export type PageCommand = (options: PageCommandOptions, ...args: any[]) => Promise<any>;
|
|
39
|
-
export interface PageCommands {
|
|
40
|
-
[commandName: string]: PageCommand | ((options: WaitForStorybookComponentToBeLoaded) => Promise<void>);
|
|
41
|
-
}
|
|
42
44
|
export {};
|
|
43
45
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACxB,uBAAuB,EACvB,yBAAyB,EACzB,wBAAwB,EACxB,0BAA0B,EAC1B,yBAAyB,EACzB,YAAY,EACf,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,gBAAgB,EAChB,kBAAkB,EAClB,wBAAwB,EACxB,uBAAuB,EACvB,yBAAyB,EACzB,wBAAwB,EACxB,0BAA0B,EAC1B,yBAAyB,EACzB,YAAY,EACf,MAAM,4BAA4B,CAAA;AAEnC,KAAK,WAAW,GAAG;IACf,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAAC;CAC3C,CAAC;AACF,MAAM,MAAM,MAAM,GAAG,WAAW,GAAG,gBAAgB,CAAC;AACpD,KAAK,WAAW,GAAG;IACf,CAAC,WAAW,EAAE,MAAM,GAAG,kBAAkB,GAAG,MAAM,CAAC;CACtD,CAAC;AACF,MAAM,MAAM,MAAM,GAAG,WAAW,GAAG,CAAC,kBAAkB,GAAG,MAAM,CAAC,CAAC;AACjE,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AACjE,MAAM,MAAM,wBAAwB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACpB,CAAA;AAED,MAAM,WAAW,oBAAoB;IACjC,YAAY,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC;IACrC,cAAc,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IAC9D,oBAAoB,CAAC,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC;CAChD;AAED,MAAM,WAAW,8BACb,SAAQ,IAAI,CAAC,0BAA0B,EAAE,MAAM,oBAAoB,CAAC,EAChE,oBAAoB;CAAG;AAC/B,MAAM,WAAW,6BACb,SAAQ,IAAI,CAAC,yBAAyB,EAAE,MAAM,oBAAoB,CAAC,EAC/D,oBAAoB;CAAG;AAC/B,MAAM,WAAW,4BACb,SAAQ,IAAI,CAAC,wBAAwB,EAAE,MAAM,oBAAoB,CAAC,EAC9D,oBAAoB;CAAG;AAC/B,MAAM,WAAW,2BACb,SAAQ,IAAI,CAAC,uBAAuB,EAAE,MAAM,oBAAoB,CAAC,EAC7D,oBAAoB;CAAG;AAC/B,MAAM,WAAW,6BACb,SAAQ,IAAI,CAAC,yBAAyB,EAAE,MAAM,oBAAoB,CAAC,EAC/D,oBAAoB;CAAG;AAC/B,MAAM,WAAW,4BACb,SAAQ,IAAI,CAAC,wBAAwB,EAAE,MAAM,oBAAoB,CAAC,EAC9D,oBAAoB;CAAG;AAE/B,MAAM,WAAW,oBAAqB,SAAQ,YAAY;CAAG"}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { Folders, InstanceData, CheckScreenMethodOptions, SaveScreenMethodOptions, CheckFullPageMethodOptions, SaveFullPageMethodOptions, CheckElementMethodOptions, SaveElementMethodOptions } from 'webdriver-image-comparison';
|
|
1
|
+
import type { Folders, InstanceData, CheckScreenMethodOptions, SaveScreenMethodOptions, CheckFullPageMethodOptions, SaveFullPageMethodOptions, CheckElementMethodOptions, SaveElementMethodOptions, TestContext } from 'webdriver-image-comparison';
|
|
2
|
+
import type { NativeContextType } from './types.js';
|
|
2
3
|
/**
|
|
3
4
|
* Get the folders data
|
|
4
5
|
*
|
|
@@ -32,6 +33,19 @@ export declare function getBrowserObject(elem: WebdriverIO.Element | WebdriverIO
|
|
|
32
33
|
/**
|
|
33
34
|
* We can't say it's native context if the autoWebview is provided and set to true, for all other cases we can say it's native
|
|
34
35
|
*/
|
|
35
|
-
export declare function determineNativeContext(driver: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser):
|
|
36
|
+
export declare function determineNativeContext(driver: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser): NativeContextType;
|
|
37
|
+
/**
|
|
38
|
+
* Get the native context for the current browser
|
|
39
|
+
*/
|
|
40
|
+
export declare function getNativeContext(browser: WebdriverIO.Browser | WebdriverIO.MultiRemoteBrowser, currentBrowser: WebdriverIO.Browser, nativeContext: NativeContextType): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Make sure we have all the data for the test context
|
|
43
|
+
*/
|
|
44
|
+
export declare function enrichTestContext({ commandName, currentTestContext: { framework, parent, title, }, instanceData: { appName, browserName, browserVersion, deviceName, isAndroid, isIOS, isMobile, platformName, platformVersion, }, tag, }: {
|
|
45
|
+
commandName: string;
|
|
46
|
+
currentTestContext: TestContext;
|
|
47
|
+
instanceData: InstanceData;
|
|
48
|
+
tag: string;
|
|
49
|
+
}): TestContext;
|
|
36
50
|
export {};
|
|
37
51
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACR,OAAO,EACP,YAAY,EACZ,wBAAwB,EACxB,uBAAuB,EACvB,0BAA0B,EAC1B,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACR,OAAO,EACP,YAAY,EACZ,wBAAwB,EACxB,uBAAuB,EACvB,0BAA0B,EAC1B,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,WAAW,EACd,MAAM,4BAA4B,CAAA;AAEnC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAOnD;;;;;GAKG;AACH,KAAK,sBAAsB,GACrB,yBAAyB,GACzB,0BAA0B,GAC1B,wBAAwB,GACxB,wBAAwB,GACxB,yBAAyB,GACzB,uBAAuB,CAAC;AAE9B,wBAAgB,UAAU,CACtB,aAAa,EAAE,sBAAsB,EACrC,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,MAAM,GACxB,OAAO,CAMT;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,iBAAiB,SAAI,GAAG;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACjB,CAKA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,gBAAgB,EAAE;IAAC,MAAM,EAAC,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,GAAG,MAAM,CAOhH;AA4GD;;GAEG;AACH,wBAAsB,eAAe,CAAC,cAAc,EAAE,WAAW,CAAC,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CA4DhG;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAE,IAAI,EAAE,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,OAAO,CAGtG;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAClC,MAAM,EAAE,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,kBAAkB,GAC7D,iBAAiB,CA0BnB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC5B,OAAO,EAAE,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,kBAAkB,EAC7D,cAAc,EAAE,WAAW,CAAC,OAAO,EACnC,aAAa,EAAE,iBAAiB,GACjC,OAAO,CAQT;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC7B,EACI,WAAW,EACX,kBAAkB,EAAE,EAChB,SAAS,EACT,MAAM,EACN,KAAK,GACR,EACD,YAAY,EAAE,EACV,OAAO,EACP,WAAW,EACX,cAAc,EACd,UAAU,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,eAAe,GAClB,EACD,GAAG,GACN,EACD;IACI,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,WAAW,CAAC;IAChC,YAAY,EAAE,YAAY,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;CACf,GACF,WAAW,CAuBb"}
|
package/dist/utils.js
CHANGED
|
@@ -137,7 +137,7 @@ export async function getInstanceData(currentBrowser) {
|
|
|
137
137
|
// @ts-ignore
|
|
138
138
|
platformVersion: rawPlatformVersion = NOT_KNOWN, } = currentCapabilities;
|
|
139
139
|
const appName = rawApp !== NOT_KNOWN
|
|
140
|
-
? rawApp.replace(/\\/g, '/').split('/').pop().replace(/[^a-zA-Z0-9]/g, '_')
|
|
140
|
+
? rawApp.replace(/\\/g, '/').split('/').pop().replace(/[^a-zA-Z0-9.]/g, '_')
|
|
141
141
|
: NOT_KNOWN;
|
|
142
142
|
const deviceName = getDeviceName(currentBrowser);
|
|
143
143
|
const nativeWebScreenshot = !!(requestedCapabilities['appium:nativeWebScreenshot']);
|
|
@@ -173,6 +173,17 @@ export function getBrowserObject(elem) {
|
|
|
173
173
|
* We can't say it's native context if the autoWebview is provided and set to true, for all other cases we can say it's native
|
|
174
174
|
*/
|
|
175
175
|
export function determineNativeContext(driver) {
|
|
176
|
+
// First check if it's multi remote
|
|
177
|
+
if (driver.isMultiremote) {
|
|
178
|
+
return Object.keys(driver).reduce((acc, instanceName) => {
|
|
179
|
+
const instance = driver[instanceName];
|
|
180
|
+
if (instance.sessionId) {
|
|
181
|
+
acc[instance.sessionId] = determineNativeContext(instance);
|
|
182
|
+
}
|
|
183
|
+
return acc;
|
|
184
|
+
}, {});
|
|
185
|
+
}
|
|
186
|
+
// If not check if it's a mobile
|
|
176
187
|
if (driver.isMobile) {
|
|
177
188
|
return !!driver.requestedCapabilities?.browserName === false
|
|
178
189
|
&& (driver.requestedCapabilities?.['appium:app'] !== undefined
|
|
@@ -180,5 +191,45 @@ export function determineNativeContext(driver) {
|
|
|
180
191
|
|| driver.requestedCapabilities?.['appium:appPackage'] !== undefined)
|
|
181
192
|
&& driver.requestedCapabilities?.['appium:autoWebview'] !== true;
|
|
182
193
|
}
|
|
194
|
+
// If not, it's webcontext
|
|
183
195
|
return false;
|
|
184
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Get the native context for the current browser
|
|
199
|
+
*/
|
|
200
|
+
export function getNativeContext(browser, currentBrowser, nativeContext) {
|
|
201
|
+
if (browser.isMultiremote) {
|
|
202
|
+
return nativeContext[currentBrowser.sessionId];
|
|
203
|
+
}
|
|
204
|
+
else if (typeof nativeContext === 'boolean') {
|
|
205
|
+
return nativeContext;
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Make sure we have all the data for the test context
|
|
211
|
+
*/
|
|
212
|
+
export function enrichTestContext({ commandName, currentTestContext: { framework, parent, title, }, instanceData: { appName, browserName, browserVersion, deviceName, isAndroid, isIOS, isMobile, platformName, platformVersion, }, tag, }) {
|
|
213
|
+
return {
|
|
214
|
+
commandName,
|
|
215
|
+
instanceData: {
|
|
216
|
+
app: appName,
|
|
217
|
+
browser: {
|
|
218
|
+
name: browserName,
|
|
219
|
+
version: browserVersion,
|
|
220
|
+
},
|
|
221
|
+
deviceName,
|
|
222
|
+
isMobile,
|
|
223
|
+
isAndroid,
|
|
224
|
+
isIOS,
|
|
225
|
+
platform: {
|
|
226
|
+
name: platformName,
|
|
227
|
+
version: platformVersion,
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
framework,
|
|
231
|
+
parent,
|
|
232
|
+
tag,
|
|
233
|
+
title,
|
|
234
|
+
};
|
|
235
|
+
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@wdio/visual-service",
|
|
3
3
|
"author": "Wim Selles - wswebcreation",
|
|
4
4
|
"description": "Image comparison / visual regression testing for WebdriverIO",
|
|
5
|
-
"version": "5.
|
|
5
|
+
"version": "5.2.0",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://webdriver.io/docs/visual-testing",
|
|
8
8
|
"repository": {
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
"type": "module",
|
|
21
21
|
"types": "./dist/index.d.ts",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@wdio/globals": "^8.
|
|
23
|
+
"@wdio/globals": "^8.39.1",
|
|
24
24
|
"@wdio/logger": "^8.38.0",
|
|
25
|
-
"@wdio/types": "^8.
|
|
25
|
+
"@wdio/types": "^8.39.0",
|
|
26
26
|
"node-fetch": "^3.3.2",
|
|
27
|
-
"webdriver-image-comparison": "^6.0
|
|
27
|
+
"webdriver-image-comparison": "^6.1.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {},
|
|
30
30
|
"scripts": {
|