@percy/webdriver-utils 1.27.5-alpha.0 → 1.27.6-alpha.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/driver.js +18 -36
- package/dist/index.js +1 -0
- package/dist/metadata/desktopMetaData.js +1 -1
- package/dist/providers/automateProvider.js +21 -11
- package/dist/providers/capabilityManager.js +5 -0
- package/dist/providers/genericProvider.js +0 -17
- package/dist/util/capabilityValidator.js +72 -0
- package/dist/util/constants.js +7 -0
- package/package.json +4 -4
- package/dist/util/utils.js +0 -8
package/dist/driver.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import utils from '@percy/sdk-utils';
|
|
2
2
|
import Cache from './util/cache.js';
|
|
3
|
-
import httpsAgent from './util/utils.js';
|
|
4
3
|
const {
|
|
5
4
|
request
|
|
6
5
|
} = utils;
|
|
@@ -11,14 +10,20 @@ export default class Driver {
|
|
|
11
10
|
this.executorUrl = executorUrl.includes('@') ? `https://${executorUrl.split('@')[1]}` : executorUrl;
|
|
12
11
|
this.passedCapabilities = passedCapabilities;
|
|
13
12
|
}
|
|
13
|
+
static requestPostOptions(command) {
|
|
14
|
+
return {
|
|
15
|
+
method: 'POST',
|
|
16
|
+
headers: {
|
|
17
|
+
'Content-Type': 'application/json;charset=utf-8'
|
|
18
|
+
},
|
|
19
|
+
body: JSON.stringify(command)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
14
22
|
async getCapabilites() {
|
|
15
23
|
return await Cache.withCache(Cache.caps, this.sessionId, async () => {
|
|
16
24
|
try {
|
|
17
|
-
const options = {
|
|
18
|
-
agent: httpsAgent()
|
|
19
|
-
};
|
|
20
25
|
const baseUrl = `${this.executorUrl}/session/${this.sessionId}`;
|
|
21
|
-
const caps = JSON.parse((await request(baseUrl
|
|
26
|
+
const caps = JSON.parse((await request(baseUrl)).body);
|
|
22
27
|
return caps.value;
|
|
23
28
|
} catch (err) {
|
|
24
29
|
log.warn(`Falling back to legacy protocol, Error: ${err.message}`);
|
|
@@ -27,11 +32,8 @@ export default class Driver {
|
|
|
27
32
|
});
|
|
28
33
|
}
|
|
29
34
|
async getWindowSize() {
|
|
30
|
-
const options = {
|
|
31
|
-
agent: httpsAgent()
|
|
32
|
-
};
|
|
33
35
|
const baseUrl = `${this.executorUrl}/session/${this.sessionId}/window/current/size`;
|
|
34
|
-
const windowSize = JSON.parse((await request(baseUrl
|
|
36
|
+
const windowSize = JSON.parse((await request(baseUrl)).body);
|
|
35
37
|
return windowSize;
|
|
36
38
|
}
|
|
37
39
|
|
|
@@ -45,46 +47,26 @@ export default class Driver {
|
|
|
45
47
|
if (!command.script.includes('browserstack_executor')) {
|
|
46
48
|
command.script = `/* percy_automate_script */ \n ${command.script}`;
|
|
47
49
|
}
|
|
48
|
-
const options =
|
|
49
|
-
method: 'POST',
|
|
50
|
-
headers: {
|
|
51
|
-
'Content-Type': 'application/json;charset=utf-8'
|
|
52
|
-
},
|
|
53
|
-
agent: httpsAgent(),
|
|
54
|
-
body: JSON.stringify(command)
|
|
55
|
-
};
|
|
50
|
+
const options = Driver.requestPostOptions(command);
|
|
56
51
|
const baseUrl = `${this.executorUrl}/session/${this.sessionId}/execute/sync`;
|
|
57
52
|
const response = JSON.parse((await request(baseUrl, options)).body);
|
|
58
53
|
return response;
|
|
59
54
|
}
|
|
60
55
|
async takeScreenshot() {
|
|
61
|
-
const options = {
|
|
62
|
-
agent: httpsAgent()
|
|
63
|
-
};
|
|
64
56
|
const baseUrl = `${this.executorUrl}/session/${this.sessionId}/screenshot`;
|
|
65
|
-
const screenShot = JSON.parse((await request(baseUrl
|
|
57
|
+
const screenShot = JSON.parse((await request(baseUrl)).body);
|
|
66
58
|
return screenShot.value;
|
|
67
59
|
}
|
|
68
60
|
async rect(elementId) {
|
|
69
|
-
const options = {
|
|
70
|
-
agent: httpsAgent()
|
|
71
|
-
};
|
|
72
61
|
const baseUrl = `${this.executorUrl}/session/${this.sessionId}/element/${elementId}/rect`;
|
|
73
|
-
const response = JSON.parse((await request(baseUrl
|
|
62
|
+
const response = JSON.parse((await request(baseUrl)).body);
|
|
74
63
|
return response.value;
|
|
75
64
|
}
|
|
76
65
|
async findElement(using, value) {
|
|
77
|
-
const options = {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
},
|
|
82
|
-
agent: httpsAgent(),
|
|
83
|
-
body: JSON.stringify({
|
|
84
|
-
using,
|
|
85
|
-
value
|
|
86
|
-
})
|
|
87
|
-
};
|
|
66
|
+
const options = Driver.requestPostOptions({
|
|
67
|
+
using,
|
|
68
|
+
value
|
|
69
|
+
});
|
|
88
70
|
const baseUrl = `${this.executorUrl}/session/${this.sessionId}/element`;
|
|
89
71
|
const response = JSON.parse((await request(baseUrl, options)).body);
|
|
90
72
|
return response.value;
|
package/dist/index.js
CHANGED
|
@@ -23,6 +23,7 @@ export default class WebdriverUtils {
|
|
|
23
23
|
const comparisonData = await automate.screenshot(snapshotName, options);
|
|
24
24
|
comparisonData.metadata.cliScreenshotStartTime = startTime;
|
|
25
25
|
comparisonData.metadata.cliScreenshotEndTime = Date.now();
|
|
26
|
+
log.debug(`[${snapshotName}] : Comparison Data: ${JSON.stringify(comparisonData)}`);
|
|
26
27
|
return comparisonData;
|
|
27
28
|
} catch (e) {
|
|
28
29
|
log.error(`[${snapshotName}] : Error - ${e.message}`);
|
|
@@ -49,7 +49,7 @@ export default class DesktopMetaData {
|
|
|
49
49
|
async screenResolution() {
|
|
50
50
|
return await Cache.withCache(Cache.resolution, this.driver.sessionId, async () => {
|
|
51
51
|
const data = await this.driver.executeScript({
|
|
52
|
-
script: 'return [(window.screen.width * window.devicePixelRatio).toString(), (window.screen.height * window.devicePixelRatio).toString()];',
|
|
52
|
+
script: 'return [parseInt(window.screen.width * window.devicePixelRatio).toString(), parseInt(window.screen.height * window.devicePixelRatio).toString()];',
|
|
53
53
|
args: []
|
|
54
54
|
});
|
|
55
55
|
const screenInfo = data.value;
|
|
@@ -47,8 +47,7 @@ export default class AutomateProvider extends GenericProvider {
|
|
|
47
47
|
error = e;
|
|
48
48
|
throw e;
|
|
49
49
|
} finally {
|
|
50
|
-
|
|
51
|
-
await this.percyScreenshotEnd(name, (_response = response) === null || _response === void 0 ? void 0 : (_response$body = _response.body) === null || _response$body === void 0 ? void 0 : _response$body.link, `${error}`);
|
|
50
|
+
await this.percyScreenshotEnd(name, error);
|
|
52
51
|
}
|
|
53
52
|
return response;
|
|
54
53
|
}
|
|
@@ -61,23 +60,38 @@ export default class AutomateProvider extends GenericProvider {
|
|
|
61
60
|
percyBuildUrl: this.buildInfo.url,
|
|
62
61
|
state: 'begin'
|
|
63
62
|
});
|
|
63
|
+
// Selenium Hub, set status error Code to 13 if an error is thrown
|
|
64
|
+
// Handling error with Selenium dialect is != W3C
|
|
65
|
+
if ((result === null || result === void 0 ? void 0 : result.status) === 13) throw new Error((result === null || result === void 0 ? void 0 : result.value) || 'Got invalid error response');
|
|
64
66
|
this._markedPercy = result.success;
|
|
65
67
|
return result;
|
|
66
68
|
} catch (e) {
|
|
69
|
+
var _e$response, _JSON$parse, _e$response2;
|
|
67
70
|
log.debug(`[${name}] : Could not mark Automate session as percy`);
|
|
68
71
|
log.error(`[${name}] : error: ${e.toString()}`);
|
|
69
|
-
|
|
72
|
+
/**
|
|
73
|
+
* - Handling Error when dialect is W3C
|
|
74
|
+
* ERROR response format from SeleniumHUB `{
|
|
75
|
+
* sessionId: ...,
|
|
76
|
+
* status: 13,
|
|
77
|
+
* value: { error: '', message: ''}
|
|
78
|
+
* }
|
|
79
|
+
*/
|
|
80
|
+
const errResponse = (e === null || e === void 0 ? void 0 : (_e$response = e.response) === null || _e$response === void 0 ? void 0 : _e$response.body) && ((_JSON$parse = JSON.parse(e === null || e === void 0 ? void 0 : (_e$response2 = e.response) === null || _e$response2 === void 0 ? void 0 : _e$response2.body)) === null || _JSON$parse === void 0 ? void 0 : _JSON$parse.value) || {};
|
|
81
|
+
const errMessage = (errResponse === null || errResponse === void 0 ? void 0 : errResponse.message) || (errResponse === null || errResponse === void 0 ? void 0 : errResponse.error) || (e === null || e === void 0 ? void 0 : e.message) || (e === null || e === void 0 ? void 0 : e.error) || (e === null || e === void 0 ? void 0 : e.value) || e.toString();
|
|
82
|
+
throw new Error(errMessage);
|
|
70
83
|
}
|
|
71
84
|
});
|
|
72
85
|
}
|
|
73
|
-
async percyScreenshotEnd(name,
|
|
86
|
+
async percyScreenshotEnd(name, error) {
|
|
74
87
|
return await TimeIt.run('percyScreenshotEnd', async () => {
|
|
75
88
|
try {
|
|
89
|
+
var _this$buildInfo;
|
|
76
90
|
await this.browserstackExecutor('percyScreenshot', {
|
|
77
91
|
name,
|
|
78
|
-
percyScreenshotUrl,
|
|
79
|
-
status:
|
|
80
|
-
statusMessage,
|
|
92
|
+
percyScreenshotUrl: (_this$buildInfo = this.buildInfo) === null || _this$buildInfo === void 0 ? void 0 : _this$buildInfo.url,
|
|
93
|
+
status: error ? 'failure' : 'success',
|
|
94
|
+
statusMessage: error ? `${error}` : '',
|
|
81
95
|
state: 'end'
|
|
82
96
|
});
|
|
83
97
|
} catch (e) {
|
|
@@ -168,10 +182,6 @@ export default class AutomateProvider extends GenericProvider {
|
|
|
168
182
|
} = await this.metaData.windowSize();
|
|
169
183
|
const resolution = await this.metaData.screenResolution();
|
|
170
184
|
const orientation = (_ref = this.metaData.orientation() || automateCaps.deviceOrientation) === null || _ref === void 0 ? void 0 : _ref.toLowerCase();
|
|
171
|
-
|
|
172
|
-
// for android window size only constitutes of browser viewport, hence adding nav / status / url bar heights
|
|
173
|
-
[this.header, this.footer] = await this.getHeaderFooter(deviceName, osVersion, browserName);
|
|
174
|
-
height = this.metaData.device() && (osName === null || osName === void 0 ? void 0 : osName.toLowerCase()) === 'android' ? height + this.header + this.footer : height;
|
|
175
185
|
return {
|
|
176
186
|
name: deviceName,
|
|
177
187
|
osName,
|
|
@@ -2,12 +2,6 @@ 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
|
-
import httpsAgent from '../util/utils.js';
|
|
7
|
-
const {
|
|
8
|
-
request
|
|
9
|
-
} = utils;
|
|
10
|
-
const DEVICES_CONFIG_URL = 'https://storage.googleapis.com/percy-utils/devices.json';
|
|
11
5
|
const log = utils.logger('webdriver-utils:genericProvider');
|
|
12
6
|
export default class GenericProvider {
|
|
13
7
|
clientInfo = new Set();
|
|
@@ -133,9 +127,6 @@ export default class GenericProvider {
|
|
|
133
127
|
} = await this.metaData.windowSize();
|
|
134
128
|
const resolution = await this.metaData.screenResolution();
|
|
135
129
|
const orientation = this.metaData.orientation();
|
|
136
|
-
[this.header, this.footer] = await this.getHeaderFooter();
|
|
137
|
-
// for android window size only constitutes of browser viewport, hence adding nav / status / url bar heights
|
|
138
|
-
height = this.metaData.osName() === 'android' ? height + this.header + this.footer : height;
|
|
139
130
|
return {
|
|
140
131
|
name: this.metaData.deviceName(),
|
|
141
132
|
osName: this.metaData.osName(),
|
|
@@ -239,12 +230,4 @@ export default class GenericProvider {
|
|
|
239
230
|
}
|
|
240
231
|
return elementsArray;
|
|
241
232
|
}
|
|
242
|
-
async getHeaderFooter(deviceName, osVersion, browserName) {
|
|
243
|
-
// passing 0 as key, since across different pages and tests, this config will remain same
|
|
244
|
-
const devicesConfig = await Cache.withCache(Cache.devicesConfig, 0, async () => {
|
|
245
|
-
return (await request(DEVICES_CONFIG_URL, httpsAgent())).body;
|
|
246
|
-
});
|
|
247
|
-
let deviceKey = `${deviceName}-${osVersion}`;
|
|
248
|
-
return devicesConfig[deviceKey] ? devicesConfig[deviceKey][browserName] ? [devicesConfig[deviceKey][browserName].header, devicesConfig[deviceKey][browserName].footer] : [0, 0] : [0, 0];
|
|
249
|
-
}
|
|
250
233
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { colors } from '@percy/logger/utils';
|
|
4
|
+
import semver from 'semver';
|
|
5
|
+
export default class CapabilitiesValidator {
|
|
6
|
+
constructor(automateCapabilities, sessionCapabilities) {
|
|
7
|
+
this.automateCapabilities = automateCapabilities;
|
|
8
|
+
this.sessionCapabilities = sessionCapabilities;
|
|
9
|
+
}
|
|
10
|
+
WARN_LOG_LEVEL = 'WARN';
|
|
11
|
+
ERROR_LOG_LEVEL = 'ERROR';
|
|
12
|
+
log(message, errorLevel = this.ERROR_LOG_LEVEL) {
|
|
13
|
+
if (errorLevel === this.WARN_LOG_LEVEL) {
|
|
14
|
+
console.warn(colors.yellow(message));
|
|
15
|
+
} else if (errorLevel === this.ERROR_LOG_LEVEL) {
|
|
16
|
+
console.error(colors.red(message));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
existsInArray(array, value) {
|
|
20
|
+
if (!array || array.length === 0) return false;
|
|
21
|
+
return array.some(element => {
|
|
22
|
+
return element === value;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
validateBrowserOSVersions() {
|
|
26
|
+
var _this$sessionCapabili, _this$sessionCapabili2;
|
|
27
|
+
const cwd = process.cwd();
|
|
28
|
+
const excludeBrowserData = JSON.parse(fs.readFileSync(path.join(cwd, 'packages/webdriver-utils/src/util/exclude_browsers.json')));
|
|
29
|
+
let {
|
|
30
|
+
os,
|
|
31
|
+
osVersion,
|
|
32
|
+
browserName,
|
|
33
|
+
browserVersion,
|
|
34
|
+
deviceName
|
|
35
|
+
} = this.automateCapabilities;
|
|
36
|
+
const platform = (_this$sessionCapabili = this.sessionCapabilities) === null || _this$sessionCapabili === void 0 ? void 0 : (_this$sessionCapabili2 = _this$sessionCapabili.platformName) === null || _this$sessionCapabili2 === void 0 ? void 0 : _this$sessionCapabili2.toLowerCase();
|
|
37
|
+
if (!os || !osVersion || !browserName || !browserVersion) {
|
|
38
|
+
this.log('OS/Browser Combination is not supported on Percy');
|
|
39
|
+
throw new Error('OS/Browser Combination is not supported on Percy');
|
|
40
|
+
}
|
|
41
|
+
const isMobile = ['ios', 'android'].includes(platform);
|
|
42
|
+
if (isMobile && !deviceName) {
|
|
43
|
+
this.log('Device capabilities are incorrect or not supported on Percy');
|
|
44
|
+
throw new Error('Device capabilities are incorrect or not supported on Percy');
|
|
45
|
+
}
|
|
46
|
+
if (excludeBrowserData !== null && excludeBrowserData !== void 0 && excludeBrowserData.os[os]) {
|
|
47
|
+
const osData = excludeBrowserData === null || excludeBrowserData === void 0 ? void 0 : excludeBrowserData.os[os];
|
|
48
|
+
if (osData !== null && osData !== void 0 && osData.os_versions) {
|
|
49
|
+
if (this.existsInArray(osData.os_versions, osVersion)) {
|
|
50
|
+
this.log(`${os} ${osVersion} is not supported on Percy`);
|
|
51
|
+
throw new Error(`${os} ${osVersion} is not supported on Percy`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (osData !== null && osData !== void 0 && osData.browsers) {
|
|
55
|
+
const browserData = osData === null || osData === void 0 ? void 0 : osData.browsers[browserName.toLowerCase()];
|
|
56
|
+
if (browserData && browserData.min_version === 'all') {
|
|
57
|
+
this.log(`${browserName} is not supported on Percy`);
|
|
58
|
+
throw new Error(`${browserName} is not supported on Percy`);
|
|
59
|
+
} else if (browserData && parseInt(browserVersion, 10) < parseInt(browserData.min_version, 10)) {
|
|
60
|
+
this.log(`${browserName}: ${browserVersion} is not supported on Percy`);
|
|
61
|
+
throw new Error(`${browserName}: ${browserVersion} is not supported on Percy`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (osData !== null && osData !== void 0 && osData.device_names) {
|
|
65
|
+
if (this.existsInArray(osData === null || osData === void 0 ? void 0 : osData.device_names, deviceName)) {
|
|
66
|
+
this.log(`${deviceName} is not supported on Percy`);
|
|
67
|
+
throw new Error(`${deviceName} is not supported in Percy`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/webdriver-utils",
|
|
3
|
-
"version": "1.27.
|
|
3
|
+
"version": "1.27.6-alpha.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"test:coverage": "yarn test --coverage"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@percy/config": "1.27.
|
|
33
|
-
"@percy/sdk-utils": "1.27.
|
|
32
|
+
"@percy/config": "1.27.6-alpha.0",
|
|
33
|
+
"@percy/sdk-utils": "1.27.6-alpha.0"
|
|
34
34
|
},
|
|
35
|
-
"gitHead": "
|
|
35
|
+
"gitHead": "415a083dc13e9453990b042a41d6676f6618df0c"
|
|
36
36
|
}
|