@testim/testim-cli 3.213.0 → 3.214.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/commons/httpRequest.js +4 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +1 -1
- package/player/seleniumTestPlayer.js +4 -2
- package/player/services/frameLocator.js +106 -102
- package/testRunHandler.js +8 -5
- package/workers/WorkerExtension.js +2 -5
- package/workers/WorkerSelenium.js +5 -10
- package/workers/workerUtils.js +0 -39
package/commons/httpRequest.js
CHANGED
|
@@ -232,7 +232,10 @@ function download(url) {
|
|
|
232
232
|
}
|
|
233
233
|
|
|
234
234
|
return Promise.fromCallback((callback) => request.end(callback))
|
|
235
|
-
.
|
|
235
|
+
.then(response => {
|
|
236
|
+
logger.info('finished to download', { url });
|
|
237
|
+
return response;
|
|
238
|
+
})
|
|
236
239
|
.catch(logErrorAndRethrow('failed to download', { url }));
|
|
237
240
|
}
|
|
238
241
|
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -2337,9 +2337,9 @@
|
|
|
2337
2337
|
"dev": true
|
|
2338
2338
|
},
|
|
2339
2339
|
"caniuse-lite": {
|
|
2340
|
-
"version": "1.0.
|
|
2341
|
-
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.
|
|
2342
|
-
"integrity": "sha512-
|
|
2340
|
+
"version": "1.0.30001294",
|
|
2341
|
+
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001294.tgz",
|
|
2342
|
+
"integrity": "sha512-LiMlrs1nSKZ8qkNhpUf5KD0Al1KCBE3zaT7OLOwEkagXMEDij98SiOovn9wxVGQpklk9vVC/pUSqgYmkmKOS8g==",
|
|
2343
2343
|
"dev": true
|
|
2344
2344
|
},
|
|
2345
2345
|
"caseless": {
|
|
@@ -2509,9 +2509,9 @@
|
|
|
2509
2509
|
},
|
|
2510
2510
|
"dependencies": {
|
|
2511
2511
|
"@types/node": {
|
|
2512
|
-
"version": "17.0.
|
|
2513
|
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.
|
|
2514
|
-
"integrity": "sha512-
|
|
2512
|
+
"version": "17.0.5",
|
|
2513
|
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.5.tgz",
|
|
2514
|
+
"integrity": "sha512-w3mrvNXLeDYV1GKTZorGJQivK6XLCoGwpnyJFbJVK/aTBQUxOCaa/GlFAAN3OTDFcb7h5tiFG+YXCO2By+riZw=="
|
|
2515
2515
|
},
|
|
2516
2516
|
"mkdirp": {
|
|
2517
2517
|
"version": "0.5.5",
|
|
@@ -3501,9 +3501,9 @@
|
|
|
3501
3501
|
"integrity": "sha512-GJCAeDBKfREgkBtgrYSf9hQy9kTb3helv0zGdzqhM7iAkW8FA/ZF97VQDbwFiwIT8MQLLOe5VlPZOEvZAqtUAQ=="
|
|
3502
3502
|
},
|
|
3503
3503
|
"electron-to-chromium": {
|
|
3504
|
-
"version": "1.4.
|
|
3505
|
-
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.
|
|
3506
|
-
"integrity": "sha512-
|
|
3504
|
+
"version": "1.4.29",
|
|
3505
|
+
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.29.tgz",
|
|
3506
|
+
"integrity": "sha512-N2Jbwxo5Rum8G2YXeUxycs1sv4Qme/ry71HG73bv8BvZl+I/4JtRgK/En+ST/Wh/yF1fqvVCY4jZBgMxnhjtBA==",
|
|
3507
3507
|
"dev": true
|
|
3508
3508
|
},
|
|
3509
3509
|
"emoji-regex": {
|
|
@@ -5860,9 +5860,9 @@
|
|
|
5860
5860
|
},
|
|
5861
5861
|
"dependencies": {
|
|
5862
5862
|
"acorn": {
|
|
5863
|
-
"version": "8.
|
|
5864
|
-
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.
|
|
5865
|
-
"integrity": "sha512-
|
|
5863
|
+
"version": "8.7.0",
|
|
5864
|
+
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
|
5865
|
+
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
|
|
5866
5866
|
},
|
|
5867
5867
|
"acorn-globals": {
|
|
5868
5868
|
"version": "6.0.0",
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@ const TabService = require('./services/tabService');
|
|
|
4
4
|
const PortSelector = require('./services/portSelector');
|
|
5
5
|
const windowCreationListener = require('./services/windowCreationListener');
|
|
6
6
|
const CookieUtils = require('./utils/cookieUtils');
|
|
7
|
-
const
|
|
7
|
+
const frameLocatorFactory = require('./services/frameLocator');
|
|
8
8
|
const Promise = require('bluebird');
|
|
9
9
|
const { isDebuggerConnected } = require('../commons/detectDebugger');
|
|
10
10
|
|
|
@@ -45,12 +45,14 @@ class SeleniumTestPlayer {
|
|
|
45
45
|
|
|
46
46
|
this.tabService.createSesion(id);
|
|
47
47
|
|
|
48
|
+
const FrameLocator = frameLocatorFactory(this.driver);
|
|
49
|
+
|
|
48
50
|
this.sessionPlayer = new player(
|
|
49
51
|
id,
|
|
50
52
|
this.tabService,
|
|
51
53
|
CookieUtils(this.driver),
|
|
52
54
|
windowCreationListener,
|
|
53
|
-
FrameLocator
|
|
55
|
+
FrameLocator,
|
|
54
56
|
PortSelector,
|
|
55
57
|
null,
|
|
56
58
|
null /* Not in use, placeholder for the order of arguments */,
|
|
@@ -8,123 +8,127 @@ const featureFlags = require('../../commons/featureFlags');
|
|
|
8
8
|
const SELENIUM_ELEMENT_KEY = 'ELEMENT';
|
|
9
9
|
const SELENIUM_GUID_KEY = 'element-6066-11e4-a52e-4f735466cecf';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this._cache = {};
|
|
16
|
-
};
|
|
11
|
+
const _getGuidFromSeleniumElement = (seleniumElement) => {
|
|
12
|
+
if (!seleniumElement) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
16
|
+
return seleniumElement[SELENIUM_ELEMENT_KEY] || seleniumElement[SELENIUM_GUID_KEY];
|
|
17
|
+
};
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
/** @param {import('../webdriver')} driver*/
|
|
20
|
+
module.exports = function frameLocatorFactory(driver) {
|
|
21
|
+
class FrameLocator {
|
|
22
|
+
constructor(frameManager, locateElementPlayer) {
|
|
23
|
+
this.frameManager = frameManager;
|
|
24
|
+
this.locateElementPlayer = locateElementPlayer;
|
|
25
|
+
this._cache = {};
|
|
26
|
+
}
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
cacheResults(seleniumGuid, resultsUrl) {
|
|
29
|
+
this._cache[seleniumGuid] = resultsUrl;
|
|
30
|
+
}
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
getResultsFromCache(seleniumGuid) {
|
|
33
|
+
return this._cache[seleniumGuid];
|
|
34
|
+
}
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
cacheFrameLocateResults(frameHandler) {
|
|
37
|
+
if (frameHandler && frameHandler.seleniumFrameElement && frameHandler.frameLocateResultUrl) {
|
|
38
|
+
const guid = _getGuidFromSeleniumElement(frameHandler.seleniumFrameElement);
|
|
39
|
+
if (guid) {
|
|
40
|
+
this.cacheResults(guid, frameHandler.frameLocateResultUrl);
|
|
41
|
+
}
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
|
-
};
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
foundFrameCallback(result, frameTree, testimFrameId) {
|
|
46
|
+
const { frameOffset, locatedElement } = result;
|
|
47
|
+
if (locatorBuilderUtils.isEmptyResult(locatedElement)) {
|
|
48
|
+
logger.error('got empty result in frame result, not rejected from locate element player');
|
|
49
|
+
return Promise.reject();
|
|
50
|
+
}
|
|
51
|
+
return driver.switchToLocatedFrame(locatedElement)
|
|
52
|
+
.then(el => {
|
|
53
|
+
const guid = _getGuidFromSeleniumElement(el.value);
|
|
54
|
+
const frameLocateResultUrl = this.getResultsFromCache(guid);
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
frameId: -1,
|
|
58
|
+
frameOffset,
|
|
59
|
+
tabInfo: frameTree.tabInfo,
|
|
60
|
+
tabId: frameTree.tabId,
|
|
61
|
+
testimFrameId,
|
|
62
|
+
testimFullFrameId: `${this.currentFrameHandler.testimFullFrameId}-${testimFrameId}`,
|
|
63
|
+
seleniumFrameElement: el.value,
|
|
64
|
+
frameLocateResultUrl,
|
|
65
|
+
};
|
|
66
|
+
});
|
|
48
67
|
}
|
|
49
|
-
return driver.switchToLocatedFrame(locatedElement)
|
|
50
|
-
.then(el => {
|
|
51
|
-
const guid = _getGuidFromSeleniumElement(el.value);
|
|
52
|
-
const frameLocateResultUrl = this.getResultsFromCache(guid);
|
|
53
68
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
locate(frameLocator, frameDepth, currentFrame, context, frameTree, stepData) {
|
|
70
|
+
// eslint-disable-next-line new-cap
|
|
71
|
+
const locateElementPlayer = new this.locateElementPlayer(context);
|
|
72
|
+
frameLocator.targetId = `frameLocator_${frameDepth}`;
|
|
73
|
+
return locateElementPlayer.locate(frameLocator, currentFrame, frameLocator.targetId)
|
|
74
|
+
.then(result => {
|
|
75
|
+
result.isVisible = true; // frame visibility check is done on the target element
|
|
76
|
+
return locateElementPlayer.handleLocateResult(result, stepData, frameLocator)
|
|
77
|
+
.catch(() => { throw new Error(); }); // silence [object object] errors;
|
|
78
|
+
})
|
|
79
|
+
.then(result => {
|
|
80
|
+
const { locatedElement } = context.data[frameLocator.targetId];
|
|
81
|
+
return driver.getElementLocationWithPadding(locatedElement)
|
|
82
|
+
.then(location => {
|
|
83
|
+
const value = location.value || { top: 0, left: 0 };
|
|
84
|
+
result.frameOffset = {
|
|
85
|
+
top: currentFrame.frameOffset.top + value.top,
|
|
86
|
+
left: currentFrame.frameOffset.left + value.left,
|
|
87
|
+
};
|
|
88
|
+
return result;
|
|
89
|
+
});
|
|
90
|
+
})
|
|
91
|
+
.then(result => {
|
|
92
|
+
if (locateElementPlayer.addFrameDataToContext) {
|
|
93
|
+
locateElementPlayer.addFrameDataToContext(result.targetId, result.locateResult);
|
|
94
|
+
}
|
|
95
|
+
return this.foundFrameCallback(result, frameTree, frameLocator.testimFrameId);
|
|
96
|
+
})
|
|
97
|
+
.then(frameHandler => {
|
|
98
|
+
this.currentFrameHandler = frameHandler;
|
|
99
|
+
return frameHandler;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
66
102
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const { locatedElement } = context.data[frameLocator.targetId];
|
|
79
|
-
return driver.getElementLocationWithPadding(locatedElement)
|
|
80
|
-
.then(location => {
|
|
81
|
-
const value = location.value || { top: 0, left: 0 };
|
|
82
|
-
result.frameOffset = {
|
|
83
|
-
top: currentFrame.frameOffset.top + value.top,
|
|
84
|
-
left: currentFrame.frameOffset.left + value.left,
|
|
85
|
-
};
|
|
86
|
-
return result;
|
|
87
|
-
});
|
|
88
|
-
})
|
|
89
|
-
.then(result => {
|
|
90
|
-
if (locateElementPlayer.addFrameDataToContext) {
|
|
91
|
-
locateElementPlayer.addFrameDataToContext(result.targetId, result.locateResult);
|
|
103
|
+
findFrame(stepData, frameLocators, context, frameTree) {
|
|
104
|
+
const allowNoFrameSwitch = featureFlags.flags.enableFrameSwitchOptimization.isEnabled();
|
|
105
|
+
const chronologicalResults = context.playback.resultsHandler.resultsByChronologicOrder;
|
|
106
|
+
const lastResult = chronologicalResults[chronologicalResults.length - 1];
|
|
107
|
+
const allowedRetries = 1;
|
|
108
|
+
const moreThanAllowedRetries = Boolean(lastResult) && lastResult.stepId === stepData.id && lastResult.results.length > allowedRetries;
|
|
109
|
+
if (allowNoFrameSwitch && !moreThanAllowedRetries && this.currentFrameHandler) {
|
|
110
|
+
const currentFramePos = frameLocators.findIndex(x => x.testimFrameId === this.currentFrameHandler.testimFrameId);
|
|
111
|
+
if (currentFramePos > -1) {
|
|
112
|
+
const shorterPath = frameLocators.slice(currentFramePos + 1);
|
|
113
|
+
return Promise.reduce(shorterPath, (currentFrame, frameLocator, index) => this.locate(frameLocator, index, currentFrame, context, frameTree, stepData), this.currentFrameHandler);
|
|
92
114
|
}
|
|
93
|
-
return this.foundFrameCallback(result, frameTree, frameLocator.testimFrameId);
|
|
94
|
-
})
|
|
95
|
-
.tap(frameHandler => {
|
|
96
|
-
this.currentFrameHandler = frameHandler;
|
|
97
|
-
});
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
FrameLocator.prototype.findFrame = function (stepData, frameLocators, context, frameTree) {
|
|
101
|
-
const allowNoFrameSwitch = featureFlags.flags.enableFrameSwitchOptimization.isEnabled();
|
|
102
|
-
const chronologicalResults = context.playback.resultsHandler.resultsByChronologicOrder;
|
|
103
|
-
const lastResult = chronologicalResults[chronologicalResults.length - 1];
|
|
104
|
-
const allowedRetries = 1;
|
|
105
|
-
const moreThanAllowedRetries = Boolean(lastResult) && lastResult.stepId === stepData.id && lastResult.results.length > allowedRetries;
|
|
106
|
-
if (allowNoFrameSwitch && !moreThanAllowedRetries && this.currentFrameHandler) {
|
|
107
|
-
const currentFramePos = frameLocators.findIndex(x => x.testimFrameId === this.currentFrameHandler.testimFrameId);
|
|
108
|
-
if (currentFramePos > -1) {
|
|
109
|
-
const shorterPath = frameLocators.slice(currentFramePos + 1);
|
|
110
|
-
return Promise.reduce(shorterPath, (currentFrame, frameLocator, index) => this.locate(frameLocator, index, currentFrame, context, frameTree, stepData), this.currentFrameHandler);
|
|
111
115
|
}
|
|
112
|
-
}
|
|
113
116
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
117
|
+
return frameTree.getTopFrameHandler()
|
|
118
|
+
.then(topFrameHandler => {
|
|
119
|
+
topFrameHandler.frameOffset = { top: 0, left: 0 };
|
|
120
|
+
const switchToTop = (allowNoFrameSwitch && this.currentFrameHandler === topFrameHandler) ?
|
|
121
|
+
Promise.resolve(this.currentFrameHandler) :
|
|
122
|
+
driver.switchToTopFrame();
|
|
123
|
+
return switchToTop.then(() => {
|
|
124
|
+
this.cacheFrameLocateResults(this.currentFrameHandler);
|
|
125
|
+
this.currentFrameHandler = topFrameHandler;
|
|
126
|
+
return Promise.reduce(frameLocators, (currentFrame, frameLocator, index) =>
|
|
127
|
+
this.locate(frameLocator, index, currentFrame, context, frameTree, stepData), topFrameHandler);
|
|
128
|
+
});
|
|
125
129
|
});
|
|
126
|
-
|
|
127
|
-
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
128
132
|
|
|
129
133
|
return FrameLocator;
|
|
130
134
|
};
|
package/testRunHandler.js
CHANGED
|
@@ -18,7 +18,7 @@ const { SeleniumPerfStats } = require('./commons/SeleniumPerfStats');
|
|
|
18
18
|
const { preloadTests } = require('./commons/preloadTests');
|
|
19
19
|
|
|
20
20
|
const RETRIES_ON_TIMEOUT = 3;
|
|
21
|
-
const MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE =
|
|
21
|
+
const MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE = 20 * 1000; // max size, in characters, of stringified run data sent over URL params. Chosen arbitrarily, this value should be changed according to data.
|
|
22
22
|
const canSendRunDataOverUrl = (runData) => JSON.stringify(runData).length < MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE;
|
|
23
23
|
|
|
24
24
|
const TestRun = function (executionId, executionName, test, options, branchToUse, testRunStatus) {
|
|
@@ -181,8 +181,9 @@ TestRun.prototype.getRunRequestParams = async function () {
|
|
|
181
181
|
runRequestParams.lightweightMode.isRunDataSentInUrl = canSendRunDataOverUrl(runData);
|
|
182
182
|
if (runRequestParams.lightweightMode.isRunDataSentInUrl) {
|
|
183
183
|
runRequestParams.runData = runData;
|
|
184
|
+
logger.info(`Run data sent as URL param, test id: ${this.getTestId()} run data length: ${JSON.stringify(runData).length}`);
|
|
184
185
|
} else {
|
|
185
|
-
logger.warn(`Run data is too big to be sent as a URL param (
|
|
186
|
+
logger.warn(`Run data is too big to be sent as a URL param. Test id: ${this.getTestId()}, run data size: ${JSON.stringify(runData).length} (limit: ${MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE} characters)`);
|
|
186
187
|
}
|
|
187
188
|
runRequestParams.isLocalRun = Boolean(this._options.useLocalChromeDriver || this._options.useChromeLauncher);
|
|
188
189
|
}
|
|
@@ -203,9 +204,11 @@ TestRun.prototype.getRunRequestParams = async function () {
|
|
|
203
204
|
return runRequestParams;
|
|
204
205
|
};
|
|
205
206
|
|
|
206
|
-
TestRun.prototype.getRunTestUrl = function () {
|
|
207
|
-
|
|
208
|
-
|
|
207
|
+
TestRun.prototype.getRunTestUrl = async function () {
|
|
208
|
+
const runRequestParams = await this.getRunRequestParams();
|
|
209
|
+
const url = `https://run.testim.io/?params=${encodeURIComponent(JSON.stringify(runRequestParams))}`;
|
|
210
|
+
logger.info(`Test (${this.getTestId()}) run URL length: ${url.length}`);
|
|
211
|
+
return url;
|
|
209
212
|
};
|
|
210
213
|
|
|
211
214
|
TestRun.prototype.setSessionId = function (sessionId) {
|
|
@@ -110,14 +110,11 @@ class WorkerExtension extends BaseWorker {
|
|
|
110
110
|
};
|
|
111
111
|
driver.registerToClosedBrowser(onBrowserClosed);
|
|
112
112
|
return testRunHandler.onCompleted().timeout(this.testRunTimeout, timeoutMessages.TEST_COMPLETE_TIMEOUT_MSG)
|
|
113
|
-
.
|
|
113
|
+
.then(async testResult => {
|
|
114
114
|
driver.unregisterToClosedBrowser(onBrowserClosed);
|
|
115
115
|
if (this.lambdatestService.isLambdatestRun()) {
|
|
116
|
-
|
|
116
|
+
await driver.executeJS(`lambda-status=${!testResult.success ? 'failed' : 'passed'}`).catch(() => { });
|
|
117
117
|
}
|
|
118
|
-
return undefined;
|
|
119
|
-
})
|
|
120
|
-
.then(testResult => {
|
|
121
118
|
if (!driver.isAlive()) {
|
|
122
119
|
logger.warn(`possible grid unresponsive for test ${this.testId}, result ${this.testResultId} (execution: ${this.executionId})`);
|
|
123
120
|
testResult.gridIssues = 'could not validate grid is alive';
|
|
@@ -168,13 +168,10 @@ class WorkerSelenium extends BaseWorker {
|
|
|
168
168
|
}
|
|
169
169
|
throw err;
|
|
170
170
|
})
|
|
171
|
-
.
|
|
171
|
+
.then(async testResult => {
|
|
172
172
|
if (sessionPlayerInit.localAssetService) {
|
|
173
|
-
|
|
173
|
+
await sessionPlayerInit.localAssetService.drain();
|
|
174
174
|
}
|
|
175
|
-
return undefined;
|
|
176
|
-
})
|
|
177
|
-
.then(testResult => {
|
|
178
175
|
testResult.stepsResults = null;
|
|
179
176
|
testResult.resultId = this.testResultId;
|
|
180
177
|
if (!driver.isAlive()) {
|
|
@@ -187,13 +184,11 @@ class WorkerSelenium extends BaseWorker {
|
|
|
187
184
|
logger.warn(`possible browser keep alive issue ${this.testId}, result ${this.testResultId} (execution: ${this.executionId})`);
|
|
188
185
|
testResult.keepAliveIssue = maxKeepAliveGap;
|
|
189
186
|
}
|
|
190
|
-
|
|
191
|
-
})
|
|
192
|
-
.tap(testResult => {
|
|
187
|
+
const resultWithStats = { ...testResult, ...testRunHandler.seleniumPerfStats.getStats() };
|
|
193
188
|
if (this.lambdatestService.isLambdatestRun()) {
|
|
194
|
-
|
|
189
|
+
await driver.executeJS(`lambda-status=${!resultWithStats.success ? 'failed' : 'passed'}`).catch(() => { });
|
|
195
190
|
}
|
|
196
|
-
return
|
|
191
|
+
return resultWithStats;
|
|
197
192
|
});
|
|
198
193
|
}
|
|
199
194
|
|
package/workers/workerUtils.js
CHANGED
|
@@ -1,19 +1,6 @@
|
|
|
1
1
|
const Promise = require('bluebird');
|
|
2
|
-
const utils = require('../utils');
|
|
3
2
|
const gridService = require('../services/gridService');
|
|
4
3
|
const logger = require('../commons/logger').getLogger('worker-utils');
|
|
5
|
-
const { timeoutMessages } = require('../commons/constants');
|
|
6
|
-
const { GetBrowserError, PageNotAvailableError } = require('../errors');
|
|
7
|
-
|
|
8
|
-
const waitUntilBrowserTimeout = (err, startTime, interval, projectId, workerId, player, releaseSlotOnTestFinished) => {
|
|
9
|
-
logger.warn('failed getting browser from grid', { err });
|
|
10
|
-
return releasePlayer(workerId, releaseSlotOnTestFinished, projectId, player)
|
|
11
|
-
.then(() => {
|
|
12
|
-
const requestTime = Date.now() - startTime;
|
|
13
|
-
const timeDiff = interval - requestTime;
|
|
14
|
-
return Promise.delay(timeDiff).then(() => Promise.reject(err));
|
|
15
|
-
});
|
|
16
|
-
};
|
|
17
4
|
|
|
18
5
|
const releaseGridSlot = (workerId, releaseSlotOnTestFinished, projectId) => {
|
|
19
6
|
if (!releaseSlotOnTestFinished) {
|
|
@@ -29,29 +16,3 @@ const releasePlayer = (workerId, releaseSlotOnTestFinished, projectId, player) =
|
|
|
29
16
|
};
|
|
30
17
|
|
|
31
18
|
module.exports.releasePlayer = releasePlayer;
|
|
32
|
-
|
|
33
|
-
module.exports.getBrowserWithRetries = ({ getBrowserOnce, testPlayerFactory, releaseSlotOnTestFinished }, { totalTimeoutDuration, singleGetBrowserDuration, projectId, workerId, reporter }) => {
|
|
34
|
-
const maxGetBrowserAttempts = totalTimeoutDuration / singleGetBrowserDuration;
|
|
35
|
-
let failedAttempts = 0;
|
|
36
|
-
|
|
37
|
-
return utils.runWithRetries(() => {
|
|
38
|
-
const startTime = Date.now();
|
|
39
|
-
const player = testPlayerFactory();
|
|
40
|
-
return getBrowserOnce(player)
|
|
41
|
-
.then((getBrowserRes) => player || getBrowserRes)
|
|
42
|
-
.timeout(singleGetBrowserDuration, timeoutMessages.GET_BROWSER_TIMEOUT_MSG)
|
|
43
|
-
.catch(err => {
|
|
44
|
-
reporter.onGetBrowserFailure(workerId, projectId, ++failedAttempts);
|
|
45
|
-
throw err;
|
|
46
|
-
})
|
|
47
|
-
.tap(() => reporter.onGetBrowserSuccess(workerId, projectId))
|
|
48
|
-
.catch(err => waitUntilBrowserTimeout(err, startTime, singleGetBrowserDuration, projectId, workerId, player, releaseSlotOnTestFinished));
|
|
49
|
-
}, maxGetBrowserAttempts).catch(err => {
|
|
50
|
-
if (err instanceof PageNotAvailableError) {
|
|
51
|
-
throw err;
|
|
52
|
-
}
|
|
53
|
-
throw new GetBrowserError(err);
|
|
54
|
-
});
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
module.exports.isGetBrowserError = err => err && err.constructor && err.constructor.name === 'GetBrowserError';
|