@testim/testim-cli 3.252.0 → 3.254.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/OverrideTestDataBuilder.js +1 -1
- package/agent/routers/cliJsCode/index.js +4 -4
- package/agent/routers/cliJsCode/router.js +46 -42
- package/agent/routers/cliJsCode/service.js +18 -13
- package/agent/routers/codim/router.js +14 -17
- package/agent/routers/codim/router.test.js +15 -14
- package/agent/routers/codim/service.js +1 -1
- package/agent/routers/general/index.js +4 -8
- package/agent/routers/hybrid/registerRoutes.js +18 -18
- package/agent/routers/index.js +9 -8
- package/agent/routers/playground/router.js +12 -11
- package/agent/routers/playground/service.js +19 -18
- package/agent/routers/standalone-browser/registerRoutes.js +10 -10
- package/cdpTestRunner.js +4 -3
- package/chromiumInstaller.js +4 -5
- package/cli/onExit.js +2 -2
- package/cli.js +7 -6
- package/cliAgentMode.js +4 -5
- package/codim/codim-cli.js +11 -10
- package/codim/hybrid-utils.js +1 -1
- package/codim/measure-perf.js +9 -6
- package/codim/template.js/tests/examples/01-simple-text-validation.test.js +6 -6
- package/codim/template.js/tests/examples/02-using-locators.test.js +13 -15
- package/codim/template.js/tests/examples/03-using-hooks.test.js +17 -19
- package/codim/template.js/tests/examples/04-skip-and-only.test.js +16 -17
- package/codim/template.js/tests/examples/05-multiple-windows.test.js +16 -17
- package/codim/template.js/webpack.config.js +1 -1
- package/codim/template.ts/webpack.config.js +3 -3
- package/commons/AbortError.js +4 -4
- package/commons/chrome-launcher.js +6 -6
- package/commons/constants.js +2 -0
- package/commons/detectDebugger.js +4 -2
- package/commons/getSessionPlayerRequire.js +2 -20
- package/commons/initializeUserWithAuth.js +2 -2
- package/commons/lazyRequire.js +10 -9
- package/commons/logger.js +4 -4
- package/commons/performance-logger.js +14 -8
- package/commons/prepareRunnerAndTestimStartUtils.js +6 -7
- package/commons/socket/baseSocketServiceSocketIO.js +32 -34
- package/commons/socket/realDataService.js +6 -5
- package/commons/socket/realDataServiceSocketIO.js +4 -4
- package/commons/socket/remoteStepService.js +4 -3
- package/commons/socket/remoteStepServiceSocketIO.js +11 -12
- package/commons/socket/socketService.js +50 -52
- package/commons/socket/testResultServiceSocketIO.js +11 -11
- package/commons/testimDesiredCapabilitiesBuilder.js +44 -0
- package/commons/testimNgrok.js +2 -2
- package/commons/testimNgrok.test.js +1 -1
- package/commons/testimServicesApi.js +37 -21
- package/commons/xhr2.js +97 -100
- package/credentialsManager.js +17 -20
- package/errors.js +5 -0
- package/fixLocalBuild.js +2 -0
- package/npm-shrinkwrap.json +4455 -1576
- package/package.json +9 -7
- package/player/WebdriverioWebDriverApi.js +7 -2
- package/player/appiumTestPlayer.js +102 -0
- package/player/chromeLauncherTestPlayer.js +0 -1
- package/player/seleniumTestPlayer.js +3 -2
- package/player/services/frameLocator.js +2 -1
- package/player/services/mobileFrameLocatorMock.js +32 -0
- package/player/services/playbackTimeoutCalculator.js +1 -0
- package/player/services/portSelector.js +10 -8
- package/player/services/tabService.js +29 -0
- package/player/services/tabServiceMock.js +166 -0
- package/player/stepActions/navigationStepAction.js +11 -10
- package/player/stepActions/sleepStepAction.js +4 -5
- package/player/stepActions/stepAction.js +15 -1
- package/player/stepActions/textStepAction.js +4 -11
- package/player/utils/stepActionUtils.js +4 -2
- package/player/utils/windowUtils.js +139 -125
- package/player/webdriver.js +40 -26
- package/processHandler.js +3 -3
- package/processHandler.test.js +1 -1
- package/reports/consoleReporter.js +3 -2
- package/reports/debugReporter.js +41 -39
- package/reports/jsonReporter.js +53 -50
- package/reports/junitReporter.js +1 -2
- package/reports/reporter.js +135 -136
- package/runOptions.js +8 -7
- package/runner.js +13 -0
- package/runners/ParallelWorkerManager.js +2 -0
- package/runners/TestPlanRunner.js +142 -74
- package/runners/buildCodeTests.js +38 -37
- package/runners/runnerUtils.js +3 -3
- package/services/lambdatestService.js +3 -5
- package/stepPlayers/cliJsStepPlayback.js +22 -17
- package/testRunHandler.js +8 -0
- package/testRunStatus.js +458 -460
- package/{utils.js → utils/index.js} +25 -117
- package/utils/promiseUtils.js +78 -0
- package/utils/stringUtils.js +96 -0
- package/{utils.test.js → utils/utils.test.js} +2 -2
- package/workers/BaseWorker.js +29 -20
- package/workers/WorkerAppium.js +123 -0
- package/workers/WorkerExtensionSingleBrowser.js +4 -4
- package/workers/WorkerSelenium.js +5 -2
|
@@ -2,162 +2,176 @@
|
|
|
2
2
|
|
|
3
3
|
const Promise = require('bluebird');
|
|
4
4
|
const pRetry = require('p-retry');
|
|
5
|
+
const { delay } = require('../../utils');
|
|
5
6
|
const { PageNotAvailableError } = require('../../errors');
|
|
6
7
|
const logger = require('../../commons/logger').getLogger('window-utils');
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
WindowUtils.prototype.getElementFromPoint = function (x, y) {
|
|
14
|
-
function elementFromPoint(x, y) {
|
|
15
|
-
var el = document.elementFromPoint(x, y);
|
|
16
|
-
return { testimId: el ? el.getAttribute('testim_dom_element_id') : null, tagName: el ? el.tagName : null };
|
|
9
|
+
class WindowUtils {
|
|
10
|
+
constructor(id, driver) {
|
|
11
|
+
this.id = id;
|
|
12
|
+
this.driver = driver;
|
|
17
13
|
}
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
getElementFromPoint(x, y) {
|
|
16
|
+
/* eslint-disable */
|
|
17
|
+
function elementFromPoint(x, y) {
|
|
18
|
+
var el = document.elementFromPoint(x, y);
|
|
19
|
+
return { testimId: el ? el.getAttribute('testim_dom_element_id') : null, tagName: el ? el.tagName : null };
|
|
20
|
+
}
|
|
21
|
+
/* eslint-enable */
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
23
|
+
return this.driver.executeJS(elementFromPoint, x, y).then(result => result.value);
|
|
24
|
+
}
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
26
|
+
getLocation() {
|
|
27
|
+
return this.driver.getUrl();
|
|
28
|
+
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
30
|
+
stopListeningToScroll() {
|
|
31
|
+
return Promise.resolve();
|
|
32
|
+
}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
34
|
+
resumeListeningToScroll() {
|
|
35
|
+
return Promise.resolve();
|
|
36
|
+
}
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
function scrollWithoutAnimation(position) {
|
|
41
|
-
var scrollBehaviorSupported = 'scrollBehavior' in document.documentElement.style;
|
|
42
|
-
if (scrollBehaviorSupported) {
|
|
43
|
-
return window.scrollTo({ left: position.x, top: position.y, behavior: 'instant' });
|
|
44
|
-
}
|
|
45
|
-
return window.scrollTo(position.x, position.y);
|
|
38
|
+
scrollToPosition(pos) {
|
|
39
|
+
return this.driver.scroll(pos.x, pos.y);
|
|
46
40
|
}
|
|
47
|
-
return this.driver.executeJS(scrollWithoutAnimation, pos);
|
|
48
|
-
};
|
|
49
41
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
42
|
+
scrollToPositionWithoutAnimation(pos) {
|
|
43
|
+
/* eslint-disable */
|
|
44
|
+
// if scroll behaviour is not supported, then the scrolling is not animated anyway
|
|
45
|
+
function scrollWithoutAnimation(position) {
|
|
46
|
+
var scrollBehaviorSupported = 'scrollBehavior' in document.documentElement.style;
|
|
47
|
+
if (scrollBehaviorSupported) {
|
|
48
|
+
return window.scrollTo({ left: position.x, top: position.y, behavior: 'instant' });
|
|
49
|
+
}
|
|
50
|
+
return window.scrollTo(position.x, position.y);
|
|
51
|
+
}
|
|
52
|
+
/* eslint-enable */
|
|
53
|
+
return this.driver.executeJS(scrollWithoutAnimation, pos);
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
getCurrentScrollPosition() {
|
|
57
|
+
/* eslint-disable */
|
|
58
|
+
function scrollPosition() {
|
|
59
|
+
return { x: window.scrollX, y: window.scrollY };
|
|
60
|
+
}
|
|
61
|
+
/* eslint-enable */
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
return this.driver.executeJS(scrollPosition).then(result => result.value);
|
|
64
|
+
}
|
|
60
65
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
navigate(location, NAVIGATION_MAX_TIME = 15000) {
|
|
67
|
+
const that = this;
|
|
68
|
+
|
|
69
|
+
async function navigate(retries = 3) {
|
|
70
|
+
try {
|
|
71
|
+
await that.driver.url(location);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
const shouldRetryNavigation = err.seleniumStack && err.message.includes('method IWebBrowser2::Navigate2() failed');
|
|
74
|
+
if (shouldRetryNavigation && retries > 0) {
|
|
75
|
+
logger.warn('selenium navigation failed. retrying to navigate', { err });
|
|
76
|
+
await delay(1500);
|
|
77
|
+
return navigate(retries - 1);
|
|
78
|
+
}
|
|
79
|
+
throw err;
|
|
70
80
|
}
|
|
71
|
-
|
|
81
|
+
return undefined;
|
|
72
82
|
}
|
|
73
|
-
|
|
83
|
+
|
|
84
|
+
return Promise.race([navigate(), delay(NAVIGATION_MAX_TIME)]);
|
|
74
85
|
}
|
|
75
86
|
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
reloadTab(timeoutMSec = 15000) {
|
|
88
|
+
return Promise.race([
|
|
89
|
+
this.driver.reloadTab(),
|
|
90
|
+
delay(timeoutMSec),
|
|
91
|
+
]);
|
|
92
|
+
}
|
|
78
93
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
Promise.delay(timeoutMSec),
|
|
83
|
-
]);
|
|
84
|
-
};
|
|
94
|
+
getViewportSize() {
|
|
95
|
+
return this.driver.getViewportSize();
|
|
96
|
+
}
|
|
85
97
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
98
|
+
maximizeWithoutValidation() {
|
|
99
|
+
return this.driver.maximizeWithoutValidation();
|
|
100
|
+
}
|
|
89
101
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
102
|
+
getFullPageSize() {
|
|
103
|
+
/* eslint-disable */
|
|
104
|
+
function fullPageSize() {
|
|
105
|
+
var body = document.body;
|
|
106
|
+
var html = document.documentElement;
|
|
107
|
+
var height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
|
|
108
|
+
var width = Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth);
|
|
109
|
+
return {
|
|
110
|
+
height: height,
|
|
111
|
+
width: width
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/* eslint-enable */
|
|
115
|
+
|
|
116
|
+
return this.driver.executeJS(fullPageSize).then(result => result.value);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
extractToNewWindow() {
|
|
120
|
+
return Promise.resolve();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
checkSize(size) {
|
|
124
|
+
return Promise.delay(1000)
|
|
125
|
+
.then(() => this.getViewportSize())
|
|
126
|
+
.then(actualSize => {
|
|
127
|
+
if (actualSize.width !== size.width || actualSize.height !== size.height) {
|
|
128
|
+
return Promise.reject({ actualSize, expectedSize: size });
|
|
129
|
+
}
|
|
130
|
+
return { actualSize, expectedSize: size };
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
setViewportSize(size) {
|
|
135
|
+
return this.driver.setViewportSize(size.width, size.height)
|
|
136
|
+
.then(() => this.checkSize(size));
|
|
137
|
+
}
|
|
93
138
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return this.driver.executeJS(fullPageSize).then(result => Promise.resolve(result.value));
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
WindowUtils.prototype.extractToNewWindow = function () {
|
|
109
|
-
return Promise.resolve();
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
WindowUtils.prototype.checkSize = function (size) {
|
|
113
|
-
return Promise.delay(1000)
|
|
114
|
-
.then(() => this.getViewportSize())
|
|
115
|
-
.then(actualSize => {
|
|
116
|
-
if (actualSize.width !== size.width || actualSize.height !== size.height) {
|
|
117
|
-
return Promise.reject({ actualSize: actualSize, expectedSize: size });
|
|
139
|
+
validatePageIsAvailable() {
|
|
140
|
+
/* eslint-disable */
|
|
141
|
+
function pageIsAvailable() {
|
|
142
|
+
var locationObj;
|
|
143
|
+
// this sometimes happens on IE
|
|
144
|
+
if (typeof location !== 'undefined') {
|
|
145
|
+
locationObj = location;
|
|
146
|
+
} else if (typeof window !== 'undefined' && typeof window.location !== 'undefined') {
|
|
147
|
+
locationObj = window.location;
|
|
148
|
+
} else {
|
|
149
|
+
return false;
|
|
118
150
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
WindowUtils.prototype.setViewportSize = function (size) {
|
|
124
|
-
return this.driver.setViewportSize(size.width, size.height)
|
|
125
|
-
.then(() => this.checkSize(size));
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
WindowUtils.prototype.validatePageIsAvailable = function () {
|
|
129
|
-
function pageIsAvailable() {
|
|
130
|
-
var locationObj;
|
|
131
|
-
// this sometimes happens on IE
|
|
132
|
-
if (typeof location !== 'undefined') {
|
|
133
|
-
locationObj = location;
|
|
134
|
-
} else if (typeof window !== 'undefined' && typeof window.location !== 'undefined') {
|
|
135
|
-
locationObj = window.location;
|
|
136
|
-
} else {
|
|
137
|
-
return false;
|
|
151
|
+
|
|
152
|
+
return locationObj.href !== 'chrome-error://chromewebdata/' && locationObj.href !== 'safari-resource:/ErrorPage.html' && locationObj.href.indexOf('res://ieframe.dll/http_404.htm') !== 0 && locationObj.href.indexOf('ms-appx-web://microsoft.microsoftedge/assets/errorpages/') !== 0;
|
|
138
153
|
}
|
|
154
|
+
/* eslint-enable */
|
|
139
155
|
|
|
140
|
-
return
|
|
156
|
+
return this.driver.executeJS(pageIsAvailable).then(result => (result.value ? Promise.resolve() : Promise.reject(new PageNotAvailableError())));
|
|
141
157
|
}
|
|
142
158
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
WindowUtils.prototype.focusTab = function () {
|
|
147
|
-
return this.driver.switchTab(this.id);
|
|
148
|
-
};
|
|
159
|
+
focusTab() {
|
|
160
|
+
return this.driver.switchTab(this.id);
|
|
161
|
+
}
|
|
149
162
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
163
|
+
quit() {
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
153
166
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
167
|
+
getOsAndBrowser() {
|
|
168
|
+
return pRetry(() => this.driver.getBrowserAndOS(), { retries: 3 })
|
|
169
|
+
.then(osAndBrowser => ({ uaBrowserName: osAndBrowser.browser, uaOs: osAndBrowser.os, userAgent: osAndBrowser.userAgent, browserVersion: osAndBrowser.browserVersion }));
|
|
170
|
+
}
|
|
158
171
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
172
|
+
getUserAgentInfo() {
|
|
173
|
+
return pRetry(() => this.driver.getUserAgentInfo(), { retries: 3 });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
162
176
|
|
|
163
177
|
module.exports = WindowUtils;
|
package/player/webdriver.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-var */
|
|
2
|
+
|
|
2
3
|
'use strict';
|
|
3
4
|
|
|
4
5
|
const logger = require('../commons/logger').getLogger('webdriver');
|
|
@@ -34,7 +35,7 @@ const playerUtils = () => {
|
|
|
34
35
|
|
|
35
36
|
async function getCdpAddress(initResult) {
|
|
36
37
|
try {
|
|
37
|
-
const debuggerHost = initResult
|
|
38
|
+
const debuggerHost = initResult?.value?.['goog:chromeOptions']?.debuggerAddress;
|
|
38
39
|
if (!debuggerHost) {
|
|
39
40
|
return undefined;
|
|
40
41
|
}
|
|
@@ -66,10 +67,12 @@ class WebDriver extends WebDriverApi {
|
|
|
66
67
|
this.browserClosedCallbacks = this.browserClosedCallbacks.filter(cb => cb !== callback);
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
// eslint-disable-next-line max-len, default-param-last
|
|
69
71
|
async init(browserOptions, testName, testRunConfig, gridInfo, customExtensionLocalLocation, executionId, testResultId, seleniumPerfStats = new SeleniumPerfStats(), fastInit = false, lambdatestService) {
|
|
70
72
|
this.browserClosedFailedKeepAlives = 0;
|
|
71
73
|
this.ignoreHiddenTagsText = _(browserOptions).get('company.activePlan.premiumFeatures.ignoreHiddenTagsText');
|
|
72
74
|
this.browserClosedCallbacks = [];
|
|
75
|
+
// eslint-disable-next-line max-len
|
|
73
76
|
const capabilities = desiredCapabilitiesBuilder.buildSeleniumOptions(browserOptions, testName, testRunConfig, gridInfo, customExtensionLocalLocation, executionId, testResultId, lambdatestService);
|
|
74
77
|
if (capabilities.desiredCapabilities) {
|
|
75
78
|
delete capabilities.desiredCapabilities.marionette;
|
|
@@ -77,8 +80,8 @@ class WebDriver extends WebDriverApi {
|
|
|
77
80
|
if (capabilities.capabilities) {
|
|
78
81
|
delete capabilities.capabilities.alwaysMatch.marionette;
|
|
79
82
|
}
|
|
80
|
-
const browser = browserOptions.browser || (testRunConfig
|
|
81
|
-
this.initUnsupportedActions(browser, lambdatestService
|
|
83
|
+
const browser = browserOptions.browser || (testRunConfig?.browserValue);
|
|
84
|
+
this.initUnsupportedActions(browser, lambdatestService?.isLambdatestRun());
|
|
82
85
|
this.browserAndOS = null;
|
|
83
86
|
this.seleniumPerfStats = seleniumPerfStats;
|
|
84
87
|
const driverDelay = fastInit ? 0 : 1500;
|
|
@@ -90,7 +93,7 @@ class WebDriver extends WebDriverApi {
|
|
|
90
93
|
this.cdpUrl = await getCdpAddress(initResult);
|
|
91
94
|
perf.log('after getCdpAddress in webdriver.js init');
|
|
92
95
|
logger.info(`init new session testName: ${testName}`, { sessionId: this.getSessionId(), testResultId });
|
|
93
|
-
await
|
|
96
|
+
await utils.delay(driverDelay);
|
|
94
97
|
await focus();
|
|
95
98
|
perf.log('after focus and delay in webdriver.js init');
|
|
96
99
|
} catch (err) {
|
|
@@ -217,6 +220,9 @@ class WebDriver extends WebDriverApi {
|
|
|
217
220
|
});
|
|
218
221
|
}
|
|
219
222
|
|
|
223
|
+
/**
|
|
224
|
+
* @returns {Promise<{ value: HTMLElement }>}
|
|
225
|
+
*/
|
|
220
226
|
getElement(locatedElement) {
|
|
221
227
|
const perfId = this.seleniumPerfStats.markStart(SELENIUM_PERF_MARKS.GET_ELEMENT);
|
|
222
228
|
if (typeof locatedElement === 'string' || typeof locatedElement === 'number') { // support testimId in the meanwhile for backwards compatability
|
|
@@ -252,7 +258,8 @@ class WebDriver extends WebDriverApi {
|
|
|
252
258
|
.then(() => this.executeAsync(fn, args));
|
|
253
259
|
}
|
|
254
260
|
|
|
255
|
-
|
|
261
|
+
/** @type {import('clickim/src/background/stepActions/stepActionUtils').StepActionUtils['markDynamicParent']} */
|
|
262
|
+
async markDynamicParent(target, dynamicParentId, frameHandler) {
|
|
256
263
|
function setDynamicParentAttribute(data) {
|
|
257
264
|
var attributeName = data.attributeName;
|
|
258
265
|
var attributeValue = data.attributeValue;
|
|
@@ -274,6 +281,7 @@ class WebDriver extends WebDriverApi {
|
|
|
274
281
|
});
|
|
275
282
|
}
|
|
276
283
|
|
|
284
|
+
/** @return {Promise<{ value: { top: number; left: number } | null }>} */
|
|
277
285
|
getLocatedElementRectWithPadding(locatedElement) {
|
|
278
286
|
// this is here to conform with clickim's logic in frame offset calculations
|
|
279
287
|
function getLocationCode(locatedElement) {
|
|
@@ -281,8 +289,8 @@ class WebDriver extends WebDriverApi {
|
|
|
281
289
|
if (!element) {
|
|
282
290
|
return null;
|
|
283
291
|
}
|
|
284
|
-
var paddingTop = parseInt(window.getComputedStyle(element).paddingTop.replace('px', '')) || 0;
|
|
285
|
-
var paddingLeft = parseInt(window.getComputedStyle(element).paddingLeft.replace('px', '')) || 0;
|
|
292
|
+
var paddingTop = parseInt(window.getComputedStyle(element).paddingTop.replace('px', ''), 10) || 0;
|
|
293
|
+
var paddingLeft = parseInt(window.getComputedStyle(element).paddingLeft.replace('px', ''), 10) || 0;
|
|
286
294
|
var rect = element.getBoundingClientRect();
|
|
287
295
|
return { top: Math.round(rect.top + paddingTop), left: Math.round(rect.left + paddingLeft) };
|
|
288
296
|
}
|
|
@@ -298,6 +306,7 @@ class WebDriver extends WebDriverApi {
|
|
|
298
306
|
return this.getLocatedElementRectWithPadding(locatedElement);
|
|
299
307
|
}
|
|
300
308
|
|
|
309
|
+
/** @returns {Promise<{ value: null | Record<'bottom' | 'height' | 'x' | 'right' | 'y' | 'width', number> }>} */
|
|
301
310
|
getLocatedElementRect(locatedElement) {
|
|
302
311
|
function getLocationCode(locatedElement) {
|
|
303
312
|
var element = getLocatedElement(locatedElement);
|
|
@@ -311,7 +320,7 @@ class WebDriver extends WebDriverApi {
|
|
|
311
320
|
x: Math.round(rect.left),
|
|
312
321
|
right: Math.round(rect.right),
|
|
313
322
|
y: Math.round(rect.top),
|
|
314
|
-
width: Math.round(rect.width)
|
|
323
|
+
width: Math.round(rect.width),
|
|
315
324
|
};
|
|
316
325
|
}
|
|
317
326
|
|
|
@@ -340,6 +349,7 @@ class WebDriver extends WebDriverApi {
|
|
|
340
349
|
}
|
|
341
350
|
|
|
342
351
|
var children = Array.apply(null, node.childNodes).filter(function (x) { return x.nodeType === Node.ELEMENT_NODE; });
|
|
352
|
+
// eslint-disable-next-line prefer-arrow-callback
|
|
343
353
|
children.forEach(function (child) {
|
|
344
354
|
if (typeof child.tagName === 'string' && child.tagName.toLowerCase() === 'title') {
|
|
345
355
|
node.removeChild(child);
|
|
@@ -360,10 +370,14 @@ class WebDriver extends WebDriverApi {
|
|
|
360
370
|
if (element.shadowRoot && Object.getOwnPropertyDescriptor(element.ownerDocument.defaultView.Node.prototype,'textContent').get.toString().indexOf('[native code]') === -1) {
|
|
361
371
|
return element.shadowRoot.textContent.replace(/(\r\n|\n|\r)/gm, '');
|
|
362
372
|
}
|
|
373
|
+
// eslint-disable-next-line no-empty
|
|
363
374
|
} catch (err) { }
|
|
375
|
+
// eslint-disable-next-line prefer-arrow-callback
|
|
364
376
|
if (ignoreHiddenTagsText && Array.prototype.some.call(element.children, function (elem) { return elem.hidden; })) {
|
|
365
377
|
var dupElement = element.cloneNode(true);
|
|
378
|
+
// eslint-disable-next-line prefer-arrow-callback
|
|
366
379
|
var hiddenChildren = Array.prototype.filter.call(dupElement.children, function (elem) { return elem.hidden; });
|
|
380
|
+
// eslint-disable-next-line prefer-arrow-callback
|
|
367
381
|
hiddenChildren.forEach(function (child) {
|
|
368
382
|
dupElement.removeChild(child);
|
|
369
383
|
});
|
|
@@ -509,7 +523,7 @@ class WebDriver extends WebDriverApi {
|
|
|
509
523
|
throw new Error('number or type of arguments don\'t agree with setViewportSize command');
|
|
510
524
|
}
|
|
511
525
|
|
|
512
|
-
|
|
526
|
+
const shouldIndent = (typeof type === 'undefined') ? true : type;
|
|
513
527
|
|
|
514
528
|
return shouldIndent ? _setViewportSize.call(this, size) : this.windowHandleSize(size);
|
|
515
529
|
}
|
|
@@ -524,7 +538,7 @@ class WebDriver extends WebDriverApi {
|
|
|
524
538
|
|
|
525
539
|
getBrowserMajorVersion(parse) {
|
|
526
540
|
try {
|
|
527
|
-
return parseInt(parse.browser.major);
|
|
541
|
+
return parseInt(parse.browser.major, 10);
|
|
528
542
|
} catch (err) {
|
|
529
543
|
logger.error('failed to get browser version', { err: err });
|
|
530
544
|
return 0;
|
|
@@ -555,6 +569,7 @@ class WebDriver extends WebDriverApi {
|
|
|
555
569
|
return Promise.resolve(this.browserAndOS);
|
|
556
570
|
}
|
|
557
571
|
|
|
572
|
+
// eslint-disable-next-line prefer-arrow-callback
|
|
558
573
|
return this.executeJS(function () {
|
|
559
574
|
if (typeof window === 'undefined' || !window.navigator || !window.navigator.userAgent) {
|
|
560
575
|
return 'unknown';
|
|
@@ -644,15 +659,16 @@ class WebDriver extends WebDriverApi {
|
|
|
644
659
|
`, eventData.timeout, eventParam);
|
|
645
660
|
}
|
|
646
661
|
|
|
662
|
+
// eslint-disable-next-line default-param-last
|
|
647
663
|
getClickActions(types = [], button) {
|
|
648
664
|
return types.map(type => ({ type: type, button }));
|
|
649
665
|
}
|
|
650
|
-
|
|
666
|
+
// eslint-disable-next-line default-param-last
|
|
651
667
|
getClickActionList(types = [], button) {
|
|
652
668
|
return [{
|
|
653
669
|
type: 'pointer',
|
|
654
670
|
id: 'mouse',
|
|
655
|
-
actions: this.getClickActions(types, button)
|
|
671
|
+
actions: this.getClickActions(types, button),
|
|
656
672
|
}];
|
|
657
673
|
}
|
|
658
674
|
|
|
@@ -747,7 +763,7 @@ class WebDriver extends WebDriverApi {
|
|
|
747
763
|
return this.actions([{
|
|
748
764
|
type: 'pointer',
|
|
749
765
|
id: 'mouse',
|
|
750
|
-
actions
|
|
766
|
+
actions,
|
|
751
767
|
}]);
|
|
752
768
|
}
|
|
753
769
|
|
|
@@ -790,7 +806,7 @@ class WebDriver extends WebDriverApi {
|
|
|
790
806
|
return this.actions([{
|
|
791
807
|
type: 'pointer',
|
|
792
808
|
id: 'mouse',
|
|
793
|
-
actions: goToDrag.concat(startDrag).concat(doDrag).concat(endDrag)
|
|
809
|
+
actions: goToDrag.concat(startDrag).concat(doDrag).concat(endDrag),
|
|
794
810
|
}]);
|
|
795
811
|
}
|
|
796
812
|
|
|
@@ -826,12 +842,10 @@ class WebDriver extends WebDriverApi {
|
|
|
826
842
|
|
|
827
843
|
/* generate move events array */
|
|
828
844
|
const moves = Array.apply([], new Array(eventCount))
|
|
829
|
-
.map(() => {
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
};
|
|
834
|
-
});
|
|
845
|
+
.map(() => ({
|
|
846
|
+
x: Math.round((to.x - from.x) / eventCount),
|
|
847
|
+
y: Math.round((to.y - from.y) / eventCount)
|
|
848
|
+
}));
|
|
835
849
|
return [{ x: 1, y: 1 }].concat(moves);
|
|
836
850
|
}
|
|
837
851
|
|
|
@@ -871,7 +885,7 @@ class WebDriver extends WebDriverApi {
|
|
|
871
885
|
return this.actions([{
|
|
872
886
|
type: 'pointer',
|
|
873
887
|
id: 'mouse',
|
|
874
|
-
actions
|
|
888
|
+
actions,
|
|
875
889
|
}]);
|
|
876
890
|
}
|
|
877
891
|
|
|
@@ -888,7 +902,8 @@ class WebDriver extends WebDriverApi {
|
|
|
888
902
|
}
|
|
889
903
|
return Promise.reject(err);
|
|
890
904
|
});
|
|
891
|
-
}
|
|
905
|
+
}
|
|
906
|
+
if (this.unsupportedActions.move) {
|
|
892
907
|
return this.dragAndDropWithActionsAPI(rectsAndOffsets);
|
|
893
908
|
}
|
|
894
909
|
return this.dragAndDropOldAPI(sourceSeleniumElement, destinationSeleniumElement)
|
|
@@ -943,7 +958,6 @@ class WebDriver extends WebDriverApi {
|
|
|
943
958
|
|
|
944
959
|
getTabIds() {
|
|
945
960
|
return this.windowHandles().get('value');
|
|
946
|
-
|
|
947
961
|
}
|
|
948
962
|
|
|
949
963
|
isVisible(el) {
|
|
@@ -955,10 +969,10 @@ class WebDriver extends WebDriverApi {
|
|
|
955
969
|
}
|
|
956
970
|
|
|
957
971
|
getElementRect(target) {
|
|
958
|
-
|
|
972
|
+
const defaultLocation = { width: 0, height: 0, top: 0, left: 0 };
|
|
959
973
|
return this.getElementLocation(target).catch((err) => logger.error('error getting element location', { err }))
|
|
960
974
|
.then(loc => {
|
|
961
|
-
if (loc
|
|
975
|
+
if (loc?.value) {
|
|
962
976
|
return {
|
|
963
977
|
top: loc.value.y,
|
|
964
978
|
left: loc.value.x,
|
|
@@ -986,7 +1000,7 @@ class WebDriver extends WebDriverApi {
|
|
|
986
1000
|
return {
|
|
987
1001
|
x: rectangle.width / 2,
|
|
988
1002
|
y: rectangle.height / 2,
|
|
989
|
-
}
|
|
1003
|
+
};
|
|
990
1004
|
}
|
|
991
1005
|
}
|
|
992
1006
|
|
package/processHandler.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const { promiseTimeout, promiseMap } = require('./utils');
|
|
6
6
|
const logger = require('./commons/logger').getLogger('process-handler');
|
|
7
7
|
|
|
8
8
|
const exitHooks = [];
|
|
@@ -10,7 +10,7 @@ const exitHooks = [];
|
|
|
10
10
|
module.exports = function (onExit, _process = process) {
|
|
11
11
|
async function cleanup(err) {
|
|
12
12
|
// give cleanup and socket reports a chance to run
|
|
13
|
-
await
|
|
13
|
+
await promiseTimeout(promiseMap(exitHooks, hook => hook()), 10000).catch(() => null);
|
|
14
14
|
onExit(err);
|
|
15
15
|
}
|
|
16
16
|
_process.on('uncaughtException', async (err) => {
|
|
@@ -29,7 +29,7 @@ module.exports = function (onExit, _process = process) {
|
|
|
29
29
|
// rollout manages promises incorrectly and generates unhandled rejections from within their code
|
|
30
30
|
logger.fatal('Caught unhandled promise rejection', reason);
|
|
31
31
|
//TODO(benji) - this is a pretty shitty way to detect this error since rollout can change their API endpoint
|
|
32
|
-
if (reason
|
|
32
|
+
if (reason?.message?.includes('ENOTFOUND x-api.rollout.io')) {
|
|
33
33
|
// this is not a fatal error - we recover from this in feature-flags service
|
|
34
34
|
return;
|
|
35
35
|
}
|
package/processHandler.test.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const chalk = require('chalk');
|
|
3
3
|
const _ = require('lodash');
|
|
4
4
|
|
|
5
|
-
const utils = require('../utils
|
|
5
|
+
const utils = require('../utils');
|
|
6
6
|
const constants = require('../commons/constants');
|
|
7
7
|
const featureAvailabilityService = require('../commons/featureAvailabilityService');
|
|
8
8
|
const { getAbortedTests, getFailedTests, getPassedTests, getFailureEvaluatingCount, getSkippedCount } = require('./reporterUtils');
|
|
@@ -120,7 +120,8 @@ class ConsoleReporter {
|
|
|
120
120
|
if (isCodeMode) {
|
|
121
121
|
console.log(`Run test plan, Project: ${this.options.project} (Execution ID: ${executionId}):`);
|
|
122
122
|
} else {
|
|
123
|
-
|
|
123
|
+
const sfdcCredentialLog = this.options.sfdcCredential ? ` SfdcCredential: ${this.options.sfdcCredential}` : '';
|
|
124
|
+
console.log(`Run${this.buildTestPlanName(isAnonymous, testPlanName)} test plan with ${configString}, Project: ${this.options.project}, Branch: ${this.branchToUse}${sfdcCredentialLog} (${executionId})`);
|
|
124
125
|
}
|
|
125
126
|
this.printWorkerDivider();
|
|
126
127
|
|