@percy/webdriver-utils 1.27.0-alpha.0 → 1.27.0-beta.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/dist/index.js +7 -3
- package/dist/metadata/desktopMetaData.js +2 -2
- package/dist/metadata/mobileMetaData.js +8 -0
- package/dist/providers/automateProvider.js +15 -9
- package/dist/providers/genericProvider.js +66 -13
- package/dist/providers/providerResolver.js +2 -2
- package/dist/util/cache.js +1 -0
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -11,7 +11,8 @@ export default class WebdriverUtils {
|
|
|
11
11
|
snapshotName,
|
|
12
12
|
clientInfo,
|
|
13
13
|
environmentInfo,
|
|
14
|
-
options = {}
|
|
14
|
+
options = {},
|
|
15
|
+
buildInfo = {}
|
|
15
16
|
}) {
|
|
16
17
|
this.sessionId = sessionId;
|
|
17
18
|
this.commandExecutorUrl = commandExecutorUrl;
|
|
@@ -26,11 +27,14 @@ export default class WebdriverUtils {
|
|
|
26
27
|
this.options = camelCasedOptions;
|
|
27
28
|
this.clientInfo = clientInfo;
|
|
28
29
|
this.environmentInfo = environmentInfo;
|
|
30
|
+
this.buildInfo = buildInfo;
|
|
29
31
|
}
|
|
30
32
|
async automateScreenshot() {
|
|
31
|
-
this.log.info('Starting automate screenshot');
|
|
32
|
-
const automate = ProviderResolver.resolve(this.sessionId, this.commandExecutorUrl, this.capabilities, this.sessionCapabilites, this.clientInfo, this.environmentInfo, this.options);
|
|
33
|
+
this.log.info('Starting automate screenshot ...');
|
|
34
|
+
const automate = ProviderResolver.resolve(this.sessionId, this.commandExecutorUrl, this.capabilities, this.sessionCapabilites, this.clientInfo, this.environmentInfo, this.options, this.buildInfo);
|
|
35
|
+
this.log.debug('Resolved provider ...');
|
|
33
36
|
await automate.createDriver();
|
|
37
|
+
this.log.debug('Created driver ...');
|
|
34
38
|
return await automate.screenshot(this.snapshotName, this.options);
|
|
35
39
|
}
|
|
36
40
|
}
|
|
@@ -23,7 +23,7 @@ export default class DesktopMetaData {
|
|
|
23
23
|
|
|
24
24
|
// combination of browserName + browserVersion + osVersion + osName
|
|
25
25
|
deviceName() {
|
|
26
|
-
return this.
|
|
26
|
+
return this.osName() + '_' + this.osVersion() + '_' + this.browserName() + '_' + this.browserVersion();
|
|
27
27
|
}
|
|
28
28
|
orientation() {
|
|
29
29
|
return 'landscape';
|
|
@@ -40,7 +40,7 @@ export default class DesktopMetaData {
|
|
|
40
40
|
}
|
|
41
41
|
async screenResolution() {
|
|
42
42
|
const data = await this.driver.executeScript({
|
|
43
|
-
script: 'return [window.screen.width.toString(), window.screen.height.toString()];',
|
|
43
|
+
script: 'return [(window.screen.width * window.devicePixelRatio).toString(), (window.screen.height * window.devicePixelRatio).toString()];',
|
|
44
44
|
args: []
|
|
45
45
|
});
|
|
46
46
|
const screenInfo = data.value;
|
|
@@ -40,6 +40,14 @@ export default class MobileMetaData {
|
|
|
40
40
|
height
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
|
+
async screenResolution() {
|
|
44
|
+
const data = await this.driver.executeScript({
|
|
45
|
+
script: 'return [(window.screen.width * window.devicePixelRatio).toString(), (window.screen.height * window.devicePixelRatio).toString()];',
|
|
46
|
+
args: []
|
|
47
|
+
});
|
|
48
|
+
const screenInfo = data.value;
|
|
49
|
+
return `${screenInfo[0]} x ${screenInfo[1]}`;
|
|
50
|
+
}
|
|
43
51
|
async devicePixelRatio() {
|
|
44
52
|
const devicePixelRatio = await this.driver.executeScript({
|
|
45
53
|
script: 'return window.devicePixelRatio;',
|
|
@@ -7,8 +7,8 @@ const {
|
|
|
7
7
|
TimeIt
|
|
8
8
|
} = utils;
|
|
9
9
|
export default class AutomateProvider extends GenericProvider {
|
|
10
|
-
constructor(sessionId, commandExecutorUrl, capabilities, sessionCapabilites, clientInfo, environmentInfo, options) {
|
|
11
|
-
super(sessionId, commandExecutorUrl, capabilities, sessionCapabilites, clientInfo, environmentInfo, options);
|
|
10
|
+
constructor(sessionId, commandExecutorUrl, capabilities, sessionCapabilites, clientInfo, environmentInfo, options, buildInfo) {
|
|
11
|
+
super(sessionId, commandExecutorUrl, capabilities, sessionCapabilites, clientInfo, environmentInfo, options, buildInfo);
|
|
12
12
|
this._markedPercy = false;
|
|
13
13
|
}
|
|
14
14
|
static supports(commandExecutorUrl) {
|
|
@@ -22,8 +22,11 @@ export default class AutomateProvider extends GenericProvider {
|
|
|
22
22
|
}) {
|
|
23
23
|
let response = null;
|
|
24
24
|
let error;
|
|
25
|
+
log.info('Preparing to capture screenshots on automate ...');
|
|
25
26
|
try {
|
|
27
|
+
log.debug('Marking automate session as percy ...');
|
|
26
28
|
let result = await this.percyScreenshotBegin(name);
|
|
29
|
+
log.debug('Fetching the debug url ...');
|
|
27
30
|
this.setDebugUrl(result);
|
|
28
31
|
response = await super.screenshot(name, {
|
|
29
32
|
ignoreRegionXpaths,
|
|
@@ -45,8 +48,8 @@ export default class AutomateProvider extends GenericProvider {
|
|
|
45
48
|
try {
|
|
46
49
|
let result = await this.browserstackExecutor('percyScreenshot', {
|
|
47
50
|
name,
|
|
48
|
-
percyBuildId:
|
|
49
|
-
percyBuildUrl:
|
|
51
|
+
percyBuildId: this.buildInfo.id,
|
|
52
|
+
percyBuildUrl: this.buildInfo.url,
|
|
50
53
|
state: 'begin'
|
|
51
54
|
});
|
|
52
55
|
this._markedPercy = result.success;
|
|
@@ -69,16 +72,18 @@ export default class AutomateProvider extends GenericProvider {
|
|
|
69
72
|
state: 'end'
|
|
70
73
|
});
|
|
71
74
|
} catch (e) {
|
|
72
|
-
log.debug(`[${name}] Could not
|
|
75
|
+
log.debug(`[${name}] Could not execute percyScreenshot command for Automate`);
|
|
76
|
+
log.error(e);
|
|
73
77
|
}
|
|
74
78
|
});
|
|
75
79
|
}
|
|
76
|
-
async getTiles(fullscreen) {
|
|
80
|
+
async getTiles(headerHeight, footerHeight, fullscreen) {
|
|
77
81
|
if (!this.driver) throw new Error('Driver is null, please initialize driver with createDriver().');
|
|
82
|
+
log.info('Starting actual screenshotting phase');
|
|
78
83
|
const response = await TimeIt.run('percyScreenshot:screenshot', async () => {
|
|
79
84
|
return await this.browserstackExecutor('percyScreenshot', {
|
|
80
85
|
state: 'screenshot',
|
|
81
|
-
percyBuildId:
|
|
86
|
+
percyBuildId: this.buildInfo.id,
|
|
82
87
|
screenshotType: 'singlepage',
|
|
83
88
|
scaleFactor: await this.driver.executeScript({
|
|
84
89
|
script: 'return window.devicePixelRatio;',
|
|
@@ -93,12 +98,13 @@ export default class AutomateProvider extends GenericProvider {
|
|
|
93
98
|
}
|
|
94
99
|
const tiles = [];
|
|
95
100
|
const tileResponse = JSON.parse(responseValue.result);
|
|
101
|
+
log.debug('Tiles captured successfully');
|
|
96
102
|
for (let tileData of tileResponse.sha) {
|
|
97
103
|
tiles.push(new Tile({
|
|
98
104
|
statusBarHeight: 0,
|
|
99
105
|
navBarHeight: 0,
|
|
100
|
-
headerHeight
|
|
101
|
-
footerHeight
|
|
106
|
+
headerHeight,
|
|
107
|
+
footerHeight,
|
|
102
108
|
fullscreen,
|
|
103
109
|
sha: tileData.split('-')[0] // drop build id
|
|
104
110
|
}));
|
|
@@ -2,12 +2,17 @@ import utils from '@percy/sdk-utils';
|
|
|
2
2
|
import MetaDataResolver from '../metadata/metaDataResolver.js';
|
|
3
3
|
import Tile from '../util/tile.js';
|
|
4
4
|
import Driver from '../driver.js';
|
|
5
|
+
import Cache from '../util/cache.js';
|
|
6
|
+
const {
|
|
7
|
+
request
|
|
8
|
+
} = utils;
|
|
9
|
+
const DEVICES_CONFIG_URL = 'https://storage.googleapis.com/percy-utils/devices.json';
|
|
5
10
|
const log = utils.logger('webdriver-utils:genericProvider');
|
|
6
11
|
export default class GenericProvider {
|
|
7
12
|
clientInfo = new Set();
|
|
8
13
|
environmentInfo = new Set();
|
|
9
14
|
options = {};
|
|
10
|
-
constructor(sessionId, commandExecutorUrl, capabilities, sessionCapabilites, clientInfo, environmentInfo, options) {
|
|
15
|
+
constructor(sessionId, commandExecutorUrl, capabilities, sessionCapabilites, clientInfo, environmentInfo, options, buildInfo) {
|
|
11
16
|
this.sessionId = sessionId;
|
|
12
17
|
this.commandExecutorUrl = commandExecutorUrl;
|
|
13
18
|
this.capabilities = capabilities;
|
|
@@ -15,13 +20,46 @@ export default class GenericProvider {
|
|
|
15
20
|
this.addClientInfo(clientInfo);
|
|
16
21
|
this.addEnvironmentInfo(environmentInfo);
|
|
17
22
|
this.options = options;
|
|
23
|
+
this.buildInfo = buildInfo;
|
|
18
24
|
this.driver = null;
|
|
19
25
|
this.metaData = null;
|
|
20
26
|
this.debugUrl = null;
|
|
27
|
+
this.header = 0;
|
|
28
|
+
this.footer = 0;
|
|
29
|
+
}
|
|
30
|
+
addDefaultOptions() {
|
|
31
|
+
this.options.freezeAnimation = this.options.freezeAnimation || false;
|
|
32
|
+
}
|
|
33
|
+
defaultPercyCSS() {
|
|
34
|
+
return `*, *::before, *::after {
|
|
35
|
+
-moz-transition: none !important;
|
|
36
|
+
transition: none !important;
|
|
37
|
+
-moz-animation: none !important;
|
|
38
|
+
animation: none !important;
|
|
39
|
+
animation-duration: 0 !important;
|
|
40
|
+
caret-color: transparent !important;
|
|
41
|
+
content-visibility: visible !important;
|
|
42
|
+
}
|
|
43
|
+
html{
|
|
44
|
+
scrollbar-width: auto !important;
|
|
45
|
+
}
|
|
46
|
+
svg {
|
|
47
|
+
shape-rendering: geometricPrecision !important;
|
|
48
|
+
}
|
|
49
|
+
scrollbar, scrollcorner, scrollbar thumb, scrollbar scrollbarbutton {
|
|
50
|
+
pointer-events: none !important;
|
|
51
|
+
-moz-appearance: none !important;
|
|
52
|
+
display: none !important;
|
|
53
|
+
}
|
|
54
|
+
video::-webkit-media-controls {
|
|
55
|
+
display: none !important;
|
|
56
|
+
}`;
|
|
21
57
|
}
|
|
22
58
|
async createDriver() {
|
|
23
59
|
this.driver = new Driver(this.sessionId, this.commandExecutorUrl);
|
|
60
|
+
log.debug(`Passed capabilities -> ${JSON.stringify(this.capabilities)}`);
|
|
24
61
|
const caps = await this.driver.getCapabilites();
|
|
62
|
+
log.debug(`Fetched capabilities -> ${JSON.stringify(caps)}`);
|
|
25
63
|
this.metaData = await MetaDataResolver.resolve(this.driver, caps, this.capabilities);
|
|
26
64
|
}
|
|
27
65
|
static supports(_commandExecutorUrl) {
|
|
@@ -62,16 +100,19 @@ export default class GenericProvider {
|
|
|
62
100
|
customIgnoreRegions = []
|
|
63
101
|
}) {
|
|
64
102
|
let fullscreen = false;
|
|
65
|
-
|
|
103
|
+
this.addDefaultOptions();
|
|
104
|
+
const percyCSS = (this.defaultPercyCSS() + (this.options.percyCSS || '')).split('\n').join('');
|
|
105
|
+
log.debug(`Applying the percyCSS - ${this.options.percyCSS}`);
|
|
66
106
|
await this.addPercyCSS(percyCSS);
|
|
107
|
+
log.debug('Fetching comparisong tag ...');
|
|
67
108
|
const tag = await this.getTag();
|
|
68
|
-
const tiles = await this.getTiles(fullscreen);
|
|
69
|
-
const ignoreRegions = await this.findIgnoredRegions(ignoreRegionXpaths, ignoreRegionSelectors, ignoreRegionElements, customIgnoreRegions);
|
|
70
|
-
await this.setDebugUrl();
|
|
71
|
-
await this.removePercyCSS();
|
|
72
109
|
log.debug(`${name} : Tag ${JSON.stringify(tag)}`);
|
|
110
|
+
const tiles = await this.getTiles(this.header, this.footer, fullscreen);
|
|
73
111
|
log.debug(`${name} : Tiles ${JSON.stringify(tiles)}`);
|
|
112
|
+
const ignoreRegions = await this.findIgnoredRegions(ignoreRegionXpaths, ignoreRegionSelectors, ignoreRegionElements, customIgnoreRegions);
|
|
113
|
+
await this.setDebugUrl();
|
|
74
114
|
log.debug(`${name} : Debug url ${this.debugUrl}`);
|
|
115
|
+
await this.removePercyCSS();
|
|
75
116
|
return {
|
|
76
117
|
name,
|
|
77
118
|
tag,
|
|
@@ -90,31 +131,34 @@ export default class GenericProvider {
|
|
|
90
131
|
// execute script and return dom content
|
|
91
132
|
return 'dummyValue';
|
|
92
133
|
}
|
|
93
|
-
async getTiles(fullscreen) {
|
|
134
|
+
async getTiles(headerHeight, footerHeight, fullscreen) {
|
|
94
135
|
if (!this.driver) throw new Error('Driver is null, please initialize driver with createDriver().');
|
|
95
136
|
const base64content = await this.driver.takeScreenshot();
|
|
137
|
+
log.debug('Tiles captured successfully');
|
|
96
138
|
return {
|
|
97
139
|
tiles: [new Tile({
|
|
98
140
|
content: base64content,
|
|
99
|
-
// TODO: Need to add method to fetch these attr
|
|
100
141
|
statusBarHeight: 0,
|
|
101
142
|
navBarHeight: 0,
|
|
102
|
-
headerHeight
|
|
103
|
-
footerHeight
|
|
143
|
+
headerHeight,
|
|
144
|
+
footerHeight,
|
|
104
145
|
fullscreen
|
|
105
146
|
})],
|
|
106
|
-
// TODO: Add Generic support sha for contextual diff
|
|
147
|
+
// TODO: Add Generic support sha for contextual diff for non-automate
|
|
107
148
|
domInfoSha: await this.getDomContent()
|
|
108
149
|
};
|
|
109
150
|
}
|
|
110
151
|
async getTag() {
|
|
111
152
|
if (!this.driver) throw new Error('Driver is null, please initialize driver with createDriver().');
|
|
112
|
-
|
|
153
|
+
let {
|
|
113
154
|
width,
|
|
114
155
|
height
|
|
115
156
|
} = await this.metaData.windowSize();
|
|
116
157
|
const resolution = await this.metaData.screenResolution();
|
|
117
158
|
const orientation = this.metaData.orientation();
|
|
159
|
+
[this.header, this.footer] = await this.getHeaderFooter();
|
|
160
|
+
// for android window size only constitutes of browser viewport, hence adding nav / status / url bar heights
|
|
161
|
+
height = this.metaData.osName() === 'android' ? height + this.header + this.footer : height;
|
|
118
162
|
return {
|
|
119
163
|
name: this.metaData.deviceName(),
|
|
120
164
|
osName: this.metaData.osName(),
|
|
@@ -128,7 +172,7 @@ export default class GenericProvider {
|
|
|
128
172
|
};
|
|
129
173
|
}
|
|
130
174
|
|
|
131
|
-
// TODO: Add Debugging Url
|
|
175
|
+
// TODO: Add Debugging Url for non-automate
|
|
132
176
|
async setDebugUrl() {
|
|
133
177
|
this.debugUrl = 'https://localhost/v1';
|
|
134
178
|
}
|
|
@@ -220,4 +264,13 @@ export default class GenericProvider {
|
|
|
220
264
|
}
|
|
221
265
|
return ignoredElementsArray;
|
|
222
266
|
}
|
|
267
|
+
async getHeaderFooter() {
|
|
268
|
+
// passing 0 as key, since across different pages and tests, this config will remain same
|
|
269
|
+
const devicesConfig = await Cache.withCache(Cache.devicesConfig, 0, async () => {
|
|
270
|
+
return (await request(DEVICES_CONFIG_URL)).body;
|
|
271
|
+
});
|
|
272
|
+
let deviceKey = `${this.metaData.deviceName()}-${this.metaData.osVersion()}`;
|
|
273
|
+
let browserName = this.capabilities.browserName;
|
|
274
|
+
return devicesConfig[deviceKey] ? devicesConfig[deviceKey][browserName] ? [devicesConfig[deviceKey][browserName].header, devicesConfig[deviceKey][browserName].footer] : [0, 0] : [0, 0];
|
|
275
|
+
}
|
|
223
276
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import GenericProvider from './genericProvider.js';
|
|
2
2
|
import AutomateProvider from './automateProvider.js';
|
|
3
3
|
export default class ProviderResolver {
|
|
4
|
-
static resolve(sessionId, commandExecutorUrl, capabilities, sessionCapabilities, clientInfo, environmentInfo, options) {
|
|
4
|
+
static resolve(sessionId, commandExecutorUrl, capabilities, sessionCapabilities, clientInfo, environmentInfo, options, buildInfo) {
|
|
5
5
|
// We can safely do [0] because GenericProvider is catch all
|
|
6
6
|
const Klass = [AutomateProvider, GenericProvider].filter(x => x.supports(commandExecutorUrl))[0];
|
|
7
|
-
return new Klass(sessionId, commandExecutorUrl, capabilities, sessionCapabilities, clientInfo, environmentInfo, options);
|
|
7
|
+
return new Klass(sessionId, commandExecutorUrl, capabilities, sessionCapabilities, clientInfo, environmentInfo, options, buildInfo);
|
|
8
8
|
}
|
|
9
9
|
}
|
package/dist/util/cache.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/webdriver-utils",
|
|
3
|
-
"version": "1.27.0-
|
|
3
|
+
"version": "1.27.0-beta.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"publishConfig": {
|
|
11
11
|
"access": "public",
|
|
12
|
-
"tag": "
|
|
12
|
+
"tag": "beta"
|
|
13
13
|
},
|
|
14
14
|
"engines": {
|
|
15
15
|
"node": ">=14"
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"test:coverage": "yarn test --coverage"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@percy/config": "1.27.0-
|
|
33
|
-
"@percy/sdk-utils": "1.27.0-
|
|
32
|
+
"@percy/config": "1.27.0-beta.0",
|
|
33
|
+
"@percy/sdk-utils": "1.27.0-beta.0"
|
|
34
34
|
},
|
|
35
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "2bc16314f51dddcc1cda459e7aa4b7b2db85f00a"
|
|
36
36
|
}
|