@testim/testim-cli 3.207.0 → 3.213.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/agent/routers/codim/service.js +24 -9
- package/commons/httpRequest.js +17 -8
- package/commons/httpRequestCounters.js +41 -10
- package/commons/httpRequestCounters.test.js +9 -9
- package/commons/testimNgrok.js +30 -1
- package/commons/testimTunnel.js +1 -1
- package/npm-shrinkwrap.json +115 -328
- package/package.json +3 -5
- package/player/seleniumTestPlayer.js +15 -6
- package/player/services/tabService.js +5 -3
- package/player/stepActions/inputFileStepAction.js +4 -1
- package/player/stepActions/pixelValidationStepAction.js +8 -1
- package/player/utils/imageCaptureUtils.js +1 -1
- package/player/utils/screenshotUtils.js +6 -6
- package/player/utils/stepActionUtils.js +2 -2
- package/runOptions.js +5 -6
- package/runners/ParallelWorkerManager.js +3 -0
- package/services/analyticsService.js +4 -2
- package/testRunHandler.js +10 -2
- package/workers/BaseWorker.js +10 -10
- package/workers/WorkerExtension.js +5 -2
- package/workers/workerUtils.js +4 -1
- package/player/utils/downloadsApiUtils.js +0 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testim/testim-cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.213.0",
|
|
4
4
|
"description": "Command line interface for running Testing on your CI",
|
|
5
5
|
"author": "Oren Rubin",
|
|
6
6
|
"contributors": [{
|
|
@@ -60,8 +60,6 @@
|
|
|
60
60
|
"bluebird": "3.7.2",
|
|
61
61
|
"bluebird-retry": "0.11.0",
|
|
62
62
|
"body-parser": "1.19.0",
|
|
63
|
-
"winston": "3.3.3",
|
|
64
|
-
"winston-transport": "4.4.0",
|
|
65
63
|
"chalk": "4.1.0",
|
|
66
64
|
"chrome-launcher": "0.13.4",
|
|
67
65
|
"combine-source-map": "0.8.0",
|
|
@@ -89,7 +87,6 @@
|
|
|
89
87
|
"moment": "2.25.3",
|
|
90
88
|
"ms": "2.1.2",
|
|
91
89
|
"npm": "6.14.11",
|
|
92
|
-
"npm-registry-client": "8.6.0",
|
|
93
90
|
"object-hash": "2.0.3",
|
|
94
91
|
"ora": "4.0.4",
|
|
95
92
|
"pako": "1.0.11",
|
|
@@ -107,6 +104,8 @@
|
|
|
107
104
|
"threads": "0.12.0",
|
|
108
105
|
"ua-parser-js": "0.7.28",
|
|
109
106
|
"validate-npm-package-name": "3.0.0",
|
|
107
|
+
"winston": "3.3.3",
|
|
108
|
+
"winston-transport": "4.4.0",
|
|
110
109
|
"ws": "8.2.3",
|
|
111
110
|
"xml2js": "0.4.23",
|
|
112
111
|
"yaml": "1.10.0"
|
|
@@ -116,7 +115,6 @@
|
|
|
116
115
|
"testim": "cli.js"
|
|
117
116
|
},
|
|
118
117
|
"scripts": {
|
|
119
|
-
"postpublish": "scripts/publish-docker.js",
|
|
120
118
|
"test": "IS_UNIT_TEST=1 ./node_modules/mocha/bin/_mocha --timeout 2000 --reporter spec --exit --recursive \"./src/**/*.test.js\" --exclude ./src/codim/template.js/tests/examples/**/*.test.js",
|
|
121
119
|
"test:watch": "IS_UNIT_TEST=1 ./node_modules/mocha/bin/_mocha --timeout 2000 --exit --recursive \"./src/**/*.test.js\" --exclude ./src/codim/template.js/tests/examples/**/*.test.js --watch",
|
|
122
120
|
"test:cov": "nyc --reporter=lcov --reporter=text yarn test",
|
|
@@ -4,7 +4,6 @@ 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 downloadsApiUtils = require('./utils/downloadsApiUtils');
|
|
8
7
|
const FrameLocator = require('./services/frameLocator');
|
|
9
8
|
const Promise = require('bluebird');
|
|
10
9
|
const { isDebuggerConnected } = require('../commons/detectDebugger');
|
|
@@ -46,11 +45,21 @@ class SeleniumTestPlayer {
|
|
|
46
45
|
|
|
47
46
|
this.tabService.createSesion(id);
|
|
48
47
|
|
|
49
|
-
this.sessionPlayer = new player(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
this.
|
|
53
|
-
|
|
48
|
+
this.sessionPlayer = new player(
|
|
49
|
+
id,
|
|
50
|
+
this.tabService,
|
|
51
|
+
CookieUtils(this.driver),
|
|
52
|
+
windowCreationListener,
|
|
53
|
+
FrameLocator(this.driver),
|
|
54
|
+
PortSelector,
|
|
55
|
+
null,
|
|
56
|
+
null /* Not in use, placeholder for the order of arguments */,
|
|
57
|
+
stepActionUtils,
|
|
58
|
+
this.stepActionFactory,
|
|
59
|
+
this.playbackTimeoutCalculator,
|
|
60
|
+
testResultService.getSocket(),
|
|
61
|
+
automationMode,
|
|
62
|
+
);
|
|
54
63
|
|
|
55
64
|
if (this.sessionPlayer.setShouldMonitorPerformance) {
|
|
56
65
|
this.sessionPlayer.setShouldMonitorPerformance(shouldMonitorPerformance);
|
|
@@ -350,14 +350,16 @@ class TabService {
|
|
|
350
350
|
mainTabPromise = this.driver.executeJS('return window.__isMainTestimTab').get('value');
|
|
351
351
|
}
|
|
352
352
|
|
|
353
|
-
return Promise.
|
|
354
|
-
|
|
353
|
+
return Promise.all([this.driver.getTitle(), this.driver.getUrl(), mainTabPromise]).then(
|
|
354
|
+
([title, url, isMainTab]) => ({ title, url, isMainTab }),
|
|
355
|
+
err => {
|
|
355
356
|
logger.error('failed to get url or title', { err });
|
|
356
357
|
return {
|
|
357
358
|
title: '',
|
|
358
359
|
url: '',
|
|
359
360
|
};
|
|
360
|
-
}
|
|
361
|
+
},
|
|
362
|
+
);
|
|
361
363
|
})
|
|
362
364
|
.catch(err => {
|
|
363
365
|
logger.error('failed to switch to tab', { tabId, err });
|
|
@@ -34,7 +34,10 @@ class InputFileStepAction extends StepAction {
|
|
|
34
34
|
top: '10px',
|
|
35
35
|
};
|
|
36
36
|
return this.forceInputToBeVisible(target, options)
|
|
37
|
-
.
|
|
37
|
+
.catch(err => {
|
|
38
|
+
logger.error('failed to set input file in Safari recovery', { err });
|
|
39
|
+
throw err;
|
|
40
|
+
});
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
uploadFilesAndForceVisibility(gridLocalFiles, target) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const _ = require('lodash');
|
|
3
4
|
const StepAction = require('./stepAction');
|
|
4
5
|
const { eyeSdkService } = require('../utils/eyeSdkService');
|
|
5
6
|
const logger = require('../../commons/logger').getLogger('pixel-validation-step-action');
|
|
@@ -9,6 +10,7 @@ class PixelValidationStepAction extends StepAction {
|
|
|
9
10
|
async performAction() {
|
|
10
11
|
const { shouldUseVisualGrid, applitoolsSdkConfig: config, testResultId } = this.context;
|
|
11
12
|
this.runContext = this.context.getRunContext(undefined);
|
|
13
|
+
const finalParams = (this.runContext.incomingParams && this.runContext.incomingParams.final) || {};
|
|
12
14
|
const batchId = (config.batch && config.batch.id) || testResultId;
|
|
13
15
|
const eyeManager = await eyeSdkService.getManager(shouldUseVisualGrid, this.context.config.applitoolsConcurrency || 5, batchId, this.runContext.applitoolsIntegrationData);
|
|
14
16
|
const targetElementData = this.getTarget() || {};
|
|
@@ -16,7 +18,12 @@ class PixelValidationStepAction extends StepAction {
|
|
|
16
18
|
try {
|
|
17
19
|
const openedEye = await eyeManager.openEyes({ driver: this.driver.client, config });
|
|
18
20
|
const region = (this.step.action === 'element' && targetElementData.seleniumElement) || undefined;
|
|
19
|
-
|
|
21
|
+
const settings = { region, fully: this.step.action === 'stitched' };
|
|
22
|
+
if (finalParams.applitoolsStepSettings && _.isPlainObject(finalParams.applitoolsStepSettings)) {
|
|
23
|
+
Object.assign(settings, finalParams.applitoolsStepSettings);
|
|
24
|
+
logger.info('Applitools SDK step executed with applitoolsStepSettings parameter', { applitoolsStepSettings: finalParams.applitoolsStepSettings });
|
|
25
|
+
}
|
|
26
|
+
await openedEye.check({ settings });
|
|
20
27
|
const eyesResults = await openedEye.close();
|
|
21
28
|
|
|
22
29
|
result = { isApplitoolsSdkResult: true, success: true, eyesResults };
|
|
@@ -290,7 +290,7 @@ ImageCaptureUtils.prototype = {
|
|
|
290
290
|
}
|
|
291
291
|
|
|
292
292
|
return Promise.all([windowUtil.getFullPageSize(), windowUtil.getViewportSize()])
|
|
293
|
-
.
|
|
293
|
+
.then(([fullPageSize, viewPortSize]) => createStitchImage(fullPageSize, viewPortSize));
|
|
294
294
|
},
|
|
295
295
|
};
|
|
296
296
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
3
|
const Promise = require('bluebird');
|
|
4
4
|
const utils = require('../../utils');
|
|
5
5
|
|
|
6
6
|
class ScreenshotUtils {
|
|
7
|
-
constructor(tabId, driver, options = { takeScreenshots: true}){
|
|
7
|
+
constructor(tabId, driver, options = { takeScreenshots: true }) {
|
|
8
8
|
this.tabId = tabId;
|
|
9
9
|
this.driver = driver;
|
|
10
10
|
this.options = options;
|
|
@@ -30,12 +30,12 @@ class ScreenshotUtils {
|
|
|
30
30
|
const devicePixelRatioPromise = this.currentDevicePixelRatio ? Promise.resolve(this.currentDevicePixelRatio) : this.getDevicePixelRatio();
|
|
31
31
|
const getScreenshot = () => Promise.all([devicePixelRatioPromise, this.driver.takeScreenshot()]);
|
|
32
32
|
return utils.runWithRetries(getScreenshot, MAX_RETRY_COUNT, SCREENSHOT_RETRY_DELAY)
|
|
33
|
-
.
|
|
33
|
+
.then(([devicePixelRatio, image]) => {
|
|
34
34
|
const base64 = image ? image.value : '';
|
|
35
|
-
const dataUrl =
|
|
35
|
+
const dataUrl = `data:image/png;base64,${this.base64AddPadding(base64.replace(/[\r\n]/g, ''))}`;
|
|
36
36
|
return {
|
|
37
37
|
image: dataUrl,
|
|
38
|
-
devicePixelRatio
|
|
38
|
+
devicePixelRatio,
|
|
39
39
|
};
|
|
40
40
|
});
|
|
41
41
|
}
|
|
@@ -52,7 +52,7 @@ class ScreenshotUtils {
|
|
|
52
52
|
return this.driver.executeJS(devicePixelRatioJS).then(result => Promise.resolve(result.value));
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
forcePixelRatio(forceRatio = 1){
|
|
55
|
+
forcePixelRatio(forceRatio = 1) {
|
|
56
56
|
this.currentDevicePixelRatio = forceRatio;
|
|
57
57
|
return Promise.resolve();
|
|
58
58
|
}
|
|
@@ -74,8 +74,8 @@ class StepActionUtils {
|
|
|
74
74
|
return this.cookieUtils.set(cookieObject).then(cookie => [cookie]);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
getNextDynamicParent(frameHandler,
|
|
78
|
-
const code = `return ${codeSnippets.getNextDynamicParent(
|
|
77
|
+
getNextDynamicParent(frameHandler, dynamicParentOptions) {
|
|
78
|
+
const code = `return ${codeSnippets.getNextDynamicParent(dynamicParentOptions)}`;
|
|
79
79
|
return this.driver.executeJS(code).then(res => res.value);
|
|
80
80
|
}
|
|
81
81
|
}
|
package/runOptions.js
CHANGED
|
@@ -287,6 +287,8 @@ program
|
|
|
287
287
|
.option('--tunnel [tunnel]', 'enable tunnel')
|
|
288
288
|
.option('--tunnel-port [tunnel-port]', 'tunnel port address')
|
|
289
289
|
.option('--tunnel-host-header [tunnel-host-header]', 'tunnel host header')
|
|
290
|
+
.option('--tunnel-region [tunnel-region]', 'ngrok tunnel region')
|
|
291
|
+
.option('--tunnel-diagnostics', 'collect ngrok tunnel diagnostics')
|
|
290
292
|
.option('--tunnel-use-http-address [tunnel-use-http-address]', 'use http:// address instead of https://', false)
|
|
291
293
|
.option('--external-lambdatest-tunnel-id [tunnel-id]', 'use existing lambdatest tunnel id')
|
|
292
294
|
.option('--external-lambdatest-use-wss', 'use wss instead of ssh for LT', false)
|
|
@@ -527,14 +529,9 @@ module.exports = {
|
|
|
527
529
|
return Promise.reject(new ArgError('missing --tunnel parameter'));
|
|
528
530
|
}
|
|
529
531
|
|
|
530
|
-
if (!program.tunnel && program.tunnelPort) {
|
|
532
|
+
if (!program.tunnel && [program.tunnelPort, program.tunnelHostHeader, program.tunnelRegion, program.tunnelDiagnostics].some(Boolean)) {
|
|
531
533
|
return Promise.reject(new ArgError('missing --tunnel parameter'));
|
|
532
534
|
}
|
|
533
|
-
|
|
534
|
-
if (!program.tunnel && program.tunnelHostHeader) {
|
|
535
|
-
return Promise.reject(new ArgError('missing --tunnel parameter'));
|
|
536
|
-
}
|
|
537
|
-
|
|
538
535
|
if (program.chromeExtraPrefs) {
|
|
539
536
|
try {
|
|
540
537
|
chromeExtraPrefs = require(path.join(process.cwd(), program.chromeExtraPrefs));
|
|
@@ -1089,6 +1086,8 @@ module.exports = {
|
|
|
1089
1086
|
tunnel: program.tunnel,
|
|
1090
1087
|
tunnelPort: program.tunnelPort,
|
|
1091
1088
|
tunnelHostHeader: program.tunnelHostHeader,
|
|
1089
|
+
tunnelRegion: program.tunnelRegion,
|
|
1090
|
+
tunnelDiagnostics: program.tunnelDiagnostics,
|
|
1092
1091
|
tunnelUseHttpAddress: program.tunnelUseHttpAddress,
|
|
1093
1092
|
externalLambdatestTunnelId: program.externalLambdatestTunnelId,
|
|
1094
1093
|
externalLambdatestUseWss: program.externalLambdatestUseWss || false,
|
|
@@ -63,6 +63,7 @@ class ParallelWorkerManager {
|
|
|
63
63
|
const source = options.source || 'cli';
|
|
64
64
|
const user = options.user;
|
|
65
65
|
const companyPlan = options.company && options.company.planType;
|
|
66
|
+
const isStartUp = options.company && options.company.isStartUp;
|
|
66
67
|
const projectName = options.projectData && options.projectData.name;
|
|
67
68
|
const lightweightMode = options.lightweightMode;
|
|
68
69
|
const sessionType = utils.getSessionType(options);
|
|
@@ -82,6 +83,7 @@ class ParallelWorkerManager {
|
|
|
82
83
|
source,
|
|
83
84
|
user,
|
|
84
85
|
lightweightMode,
|
|
86
|
+
isStartUp,
|
|
85
87
|
});
|
|
86
88
|
return testStatus.testStartAndReport(wid, executionId, resultId, isRerun, testRetryKey);
|
|
87
89
|
};
|
|
@@ -146,6 +148,7 @@ class ParallelWorkerManager {
|
|
|
146
148
|
user,
|
|
147
149
|
lightweightMode,
|
|
148
150
|
logger,
|
|
151
|
+
isStartUp,
|
|
149
152
|
});
|
|
150
153
|
if (stopOnError && !testResult.success) {
|
|
151
154
|
reject(new StopRunOnError());
|
|
@@ -31,7 +31,7 @@ function setLightweightAnalytics(properties, lightweightMode) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function analyticsTestStart({
|
|
34
|
-
executionId, projectId, testId, resultId, companyId, companyName, projectName, companyPlan, sessionType, source, user, lightweightMode,
|
|
34
|
+
executionId, projectId, testId, resultId, companyId, companyName, projectName, companyPlan, sessionType, source, user, lightweightMode, isStartUp,
|
|
35
35
|
}) {
|
|
36
36
|
const properties = setLightweightAnalytics({
|
|
37
37
|
executionId,
|
|
@@ -44,13 +44,14 @@ function analyticsTestStart({
|
|
|
44
44
|
companyPlan,
|
|
45
45
|
sessionType,
|
|
46
46
|
source: calcSource(source, user),
|
|
47
|
+
isStartUp,
|
|
47
48
|
}, lightweightMode);
|
|
48
49
|
analytics.trackWithCIUser('test-run-ci', properties);
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
function analyticsTestEnd({
|
|
52
53
|
executionId, projectId, testId, resultId, result, companyId, companyName, projectName, companyPlan, sessionType, source, user, lightweightMode,
|
|
53
|
-
logger,
|
|
54
|
+
logger, isStartUp,
|
|
54
55
|
}) {
|
|
55
56
|
try {
|
|
56
57
|
const properties = setLightweightAnalytics({
|
|
@@ -65,6 +66,7 @@ function analyticsTestEnd({
|
|
|
65
66
|
sessionType,
|
|
66
67
|
mockNetworkEnabled: result.wasMockNetworkActivated,
|
|
67
68
|
source: calcSource(source, user),
|
|
69
|
+
isStartUp,
|
|
68
70
|
}, lightweightMode);
|
|
69
71
|
|
|
70
72
|
if (result.success) {
|
package/testRunHandler.js
CHANGED
|
@@ -18,6 +18,8 @@ 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 = 50 * 1000; // max size, in characters, of stringified run data sent over URL params. Chosen arbitrarily, this value should be changed according to data.
|
|
22
|
+
const canSendRunDataOverUrl = (runData) => JSON.stringify(runData).length < MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE;
|
|
21
23
|
|
|
22
24
|
const TestRun = function (executionId, executionName, test, options, branchToUse, testRunStatus) {
|
|
23
25
|
this._executionId = executionId;
|
|
@@ -175,7 +177,13 @@ TestRun.prototype.getRunRequestParams = async function () {
|
|
|
175
177
|
|
|
176
178
|
if (this._options.lightweightMode && this._options.lightweightMode.general) {
|
|
177
179
|
runRequestParams.company = this._options.company;
|
|
178
|
-
|
|
180
|
+
const runData = this.getRunData();
|
|
181
|
+
runRequestParams.lightweightMode.isRunDataSentInUrl = canSendRunDataOverUrl(runData);
|
|
182
|
+
if (runRequestParams.lightweightMode.isRunDataSentInUrl) {
|
|
183
|
+
runRequestParams.runData = runData;
|
|
184
|
+
} else {
|
|
185
|
+
logger.warn(`Run data is too big to be sent as a URL param (lightweight mode). Run data size: ${JSON.stringify(runData).length} (limit: ${MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE} characters)`);
|
|
186
|
+
}
|
|
179
187
|
runRequestParams.isLocalRun = Boolean(this._options.useLocalChromeDriver || this._options.useChromeLauncher);
|
|
180
188
|
}
|
|
181
189
|
|
|
@@ -240,7 +248,7 @@ TestRun.prototype.clearTestResult = function () {
|
|
|
240
248
|
const mustClearPreviousStepResults = !this.isAllowReportTestResultRetries() && (this._timeoutRetryCount > 1 || this._retryCount > 1);
|
|
241
249
|
|
|
242
250
|
if (this._options.lightweightMode && this._options.lightweightMode.disableResults &&
|
|
243
|
-
|
|
251
|
+
!mustClearPreviousStepResults && canSendRunDataOverUrl(runData)) {
|
|
244
252
|
return Promise.resolve();
|
|
245
253
|
}
|
|
246
254
|
|
package/workers/BaseWorker.js
CHANGED
|
@@ -8,7 +8,7 @@ const { timeoutMessages, testRunStatus, stepResult, runnerTestStatus } = require
|
|
|
8
8
|
const logger = require('../commons/logger').getLogger('base-worker');
|
|
9
9
|
const testResultService = require('../commons/socket/testResultService');
|
|
10
10
|
const remoteStepService = require('../commons/socket/remoteStepService');
|
|
11
|
-
const { isNetworkHealthy } = require('../commons/httpRequest');
|
|
11
|
+
const { isNetworkHealthy, didNetworkConnectivityTestFail } = require('../commons/httpRequest');
|
|
12
12
|
const testimServicesApi = require('../commons/testimServicesApi');
|
|
13
13
|
const gridService = require('../services/gridService');
|
|
14
14
|
const LambdatestService = require('../services/lambdatestService');
|
|
@@ -264,13 +264,14 @@ class BaseWorker {
|
|
|
264
264
|
return undefined;
|
|
265
265
|
}
|
|
266
266
|
};
|
|
267
|
+
const getNetworkErrorMessage = () => 'Due to network connectivity issues, Testim CLI has been unable to connect to the grid.\n' +
|
|
268
|
+
`Please make sure the CLI has stable access to the internet. ${didNetworkConnectivityTestFail() ? '(Internal: network connectivity test failed)' : ''}`;
|
|
267
269
|
|
|
268
|
-
const buildError = (err) => {
|
|
269
|
-
if (!
|
|
270
|
+
const buildError = (err, wasNetworkHealthy) => {
|
|
271
|
+
if (!wasNetworkHealthy && featureFlags.flags.errorMessageOnBadNetwork.isEnabled()) {
|
|
270
272
|
return {
|
|
271
273
|
errorType: NETWORK_ERROR,
|
|
272
|
-
reason:
|
|
273
|
-
'Please make sure the CLI has stable access to the internet.',
|
|
274
|
+
reason: getNetworkErrorMessage(),
|
|
274
275
|
};
|
|
275
276
|
}
|
|
276
277
|
|
|
@@ -324,17 +325,16 @@ class BaseWorker {
|
|
|
324
325
|
};
|
|
325
326
|
|
|
326
327
|
const onRunError = async (err, testRunHandler) => {
|
|
327
|
-
|
|
328
|
+
const wasNetworkHealthy = await isNetworkHealthy();
|
|
329
|
+
if (!wasNetworkHealthy && featureFlags.flags.warnOnBadNetwork.isEnabled()) {
|
|
328
330
|
// intentional, we want to log to stderr:
|
|
329
331
|
// eslint-disable-next-line no-console
|
|
330
|
-
console.warn(
|
|
331
|
-
// eslint-disable-next-line no-console
|
|
332
|
-
console.warn('Please make sure the CLI has stable access to the internet.');
|
|
332
|
+
console.warn(getNetworkErrorMessage());
|
|
333
333
|
}
|
|
334
334
|
logger.warn('error on run', { err });
|
|
335
335
|
|
|
336
336
|
const projectId = this.userData && this.userData.projectId;
|
|
337
|
-
const { errorType, reason } = buildError(err);
|
|
337
|
+
const { errorType, reason } = buildError(err, wasNetworkHealthy);
|
|
338
338
|
testimServicesApi.updateTestResult(projectId, this.testResultId, this.testId, {
|
|
339
339
|
status: testRunStatus.COMPLETED,
|
|
340
340
|
success: false,
|
|
@@ -87,7 +87,10 @@ class WorkerExtension extends BaseWorker {
|
|
|
87
87
|
.then(url => {
|
|
88
88
|
reporter.onWaitToTestStart(this.id);
|
|
89
89
|
return Promise.all([
|
|
90
|
-
driver.url(url).tap(() => { startStausDetails.driverUrlFinished = true; }).
|
|
90
|
+
driver.url(url).tap(() => { startStausDetails.driverUrlFinished = true; }).catch(err => {
|
|
91
|
+
logger.error('error from driver.url', { err, testResultId, executionId, testId, url, urlLength: url.length });
|
|
92
|
+
throw err;
|
|
93
|
+
}),
|
|
91
94
|
testRunHandler.onStarted(TEST_START_TIMEOUT_MS).tap(() => { startStausDetails.testRunHandlerStartedFinished = true; }),
|
|
92
95
|
])
|
|
93
96
|
.timeout(TEST_START_TIMEOUT_MS, timeoutMessages.TEST_START_TIMEOUT_MSG)
|
|
@@ -110,7 +113,7 @@ class WorkerExtension extends BaseWorker {
|
|
|
110
113
|
.tap(testResult => {
|
|
111
114
|
driver.unregisterToClosedBrowser(onBrowserClosed);
|
|
112
115
|
if (this.lambdatestService.isLambdatestRun()) {
|
|
113
|
-
return driver.executeJS(`lambda-status=${!testResult.success ? 'failed' : 'passed'}`).catch(() => {});
|
|
116
|
+
return driver.executeJS(`lambda-status=${!testResult.success ? 'failed' : 'passed'}`).catch(() => { });
|
|
114
117
|
}
|
|
115
118
|
return undefined;
|
|
116
119
|
})
|
package/workers/workerUtils.js
CHANGED
|
@@ -40,7 +40,10 @@ module.exports.getBrowserWithRetries = ({ getBrowserOnce, testPlayerFactory, rel
|
|
|
40
40
|
return getBrowserOnce(player)
|
|
41
41
|
.then((getBrowserRes) => player || getBrowserRes)
|
|
42
42
|
.timeout(singleGetBrowserDuration, timeoutMessages.GET_BROWSER_TIMEOUT_MSG)
|
|
43
|
-
.
|
|
43
|
+
.catch(err => {
|
|
44
|
+
reporter.onGetBrowserFailure(workerId, projectId, ++failedAttempts);
|
|
45
|
+
throw err;
|
|
46
|
+
})
|
|
44
47
|
.tap(() => reporter.onGetBrowserSuccess(workerId, projectId))
|
|
45
48
|
.catch(err => waitUntilBrowserTimeout(err, startTime, singleGetBrowserDuration, projectId, workerId, player, releaseSlotOnTestFinished));
|
|
46
49
|
}, maxGetBrowserAttempts).catch(err => {
|