@testim/testim-cli 3.196.0 → 3.200.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/README.md +1 -1
- package/cli/onExit.js +12 -1
- package/cli.js +5 -1
- package/commons/constants.js +0 -25
- package/commons/featureFlags.js +2 -0
- package/commons/npmWrapper.js +46 -14
- package/commons/npmWrapper.test.js +182 -6
- package/commons/socket/testResultService.js +4 -14
- package/commons/testimAnalytics.js +0 -1
- package/commons/testimDesiredCapabilitiesBuilder.js +0 -94
- package/commons/testimServicesApi.js +9 -79
- package/executionQueue.js +7 -4
- package/npm-shrinkwrap.json +960 -524
- package/package.json +3 -1
- package/player/stepActions/baseJsStepAction.js +5 -1
- package/player/stepActions/pixelValidationStepAction.js +28 -0
- package/player/stepActions/salesforceAutoLoginStepAction.js +5 -3
- package/player/stepActions/stepActionRegistrar.js +4 -48
- package/player/utils/eyeSdkService.js +230 -0
- package/reports/consoleReporter.js +29 -44
- package/reports/reporter.js +0 -21
- package/runOptions.js +13 -89
- package/runner.js +3 -44
- package/runners/{strategies/LocalStrategy.js → ParallelWorkerManager.js} +59 -68
- package/runners/TestPlanRunner.js +288 -67
- package/runners/runnerUtils.js +73 -0
- package/services/analyticsService.js +94 -0
- package/services/gridService.js +24 -20
- package/services/gridService.test.js +21 -21
- package/stepPlayers/hybridStepPlayback.js +4 -1
- package/stepPlayers/tdkHybridStepPlayback.js +1 -0
- package/testRunHandler.js +23 -5
- package/testRunStatus.js +18 -27
- package/utils.js +5 -5
- package/workers/BaseWorker.js +39 -39
- package/workers/BaseWorker.test.js +1 -1
- package/workers/WorkerExtensionSingleBrowser.js +6 -3
- package/commons/apkUploader/apkUploader.js +0 -46
- package/commons/apkUploader/apkUploaderFactory.js +0 -68
- package/commons/apkUploader/deviceFarmApkUploader.js +0 -41
- package/commons/apkUploader/saucelabsApkUploader.js +0 -36
- package/commons/apkUploader/testObjectApkUploader.js +0 -34
- package/player/mobile/mobileTestPlayer.js +0 -80
- package/player/mobile/mobileWebDriver.js +0 -155
- package/player/mobile/services/frameLocatorMock.js +0 -18
- package/player/mobile/services/mobilePortSelector.js +0 -22
- package/player/mobile/services/mobileTabService.js +0 -241
- package/player/mobile/utils/mobileScreenshotUtils.js +0 -46
- package/player/mobile/utils/mobileWindowUtils.js +0 -84
- package/player/stepActions/mobile/android/androidLocateStepAction.js +0 -122
- package/player/stepActions/mobile/android/androidLongClickStepAction.js +0 -12
- package/player/stepActions/mobile/android/androidScrollStepAction.js +0 -134
- package/player/stepActions/mobile/android/androidSpecialKeyStepAction.js +0 -22
- package/player/stepActions/mobile/android/androidSwipeStepAction.js +0 -32
- package/player/stepActions/mobile/androidGlobalActionStepAction.js +0 -12
- package/player/stepActions/mobile/androidTapStepAction.js +0 -19
- package/player/stepActions/mobile/androidTextChangeStepAction.js +0 -23
- package/player/stepActions/mobile/ios/iosLocateStepAction.js +0 -124
- package/player/stepActions/mobile/ios/iosScrollStepAction.js +0 -76
- package/runners/AnonymousTestPlanRunner.js +0 -106
- package/runners/BaseRunner.js +0 -42
- package/runners/BaseTestPlanRunner.js +0 -194
- package/runners/DeviceFarmRemoteRunner.js +0 -50
- package/runners/SchedulerRemoteRunner.js +0 -47
- package/runners/strategies/BaseStrategy.js +0 -86
- package/runners/strategies/DeviceFarmStrategy.js +0 -195
- package/runners/strategies/LocalDeviceFarmStrategy.js +0 -12
- package/runners/strategies/LocalTestStrategy.js +0 -14
- package/runners/strategies/Strategy.js +0 -17
- package/workers/WorkerAppium.js +0 -70
package/runOptions.js
CHANGED
|
@@ -72,11 +72,9 @@ const printUsage = () => {
|
|
|
72
72
|
return line.includes('--player-path') || line.includes('--player-require-path');
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
function
|
|
75
|
+
function isScheduler(line) {
|
|
76
76
|
return (
|
|
77
|
-
line.includes('--testObject') ||
|
|
78
77
|
line.includes('--executionId') ||
|
|
79
|
-
line.includes('--testObject2') ||
|
|
80
78
|
line.includes('--source') ||
|
|
81
79
|
line.includes('--resultId') ||
|
|
82
80
|
line.includes('--remoteRunId') ||
|
|
@@ -84,15 +82,6 @@ const printUsage = () => {
|
|
|
84
82
|
);
|
|
85
83
|
}
|
|
86
84
|
|
|
87
|
-
function isAwsDF(line) {
|
|
88
|
-
return (
|
|
89
|
-
line.includes('--aws-project-arn') ||
|
|
90
|
-
line.includes('--aws-region') ||
|
|
91
|
-
line.includes('--aws-access-key-id') ||
|
|
92
|
-
line.includes('--aws-secret-access-key')
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
85
|
function isWebdriverTimeout(line) {
|
|
97
86
|
return (
|
|
98
87
|
line.includes('--get-browser-timeout') ||
|
|
@@ -116,6 +105,10 @@ const printUsage = () => {
|
|
|
116
105
|
return line.includes('--save-rca-locally');
|
|
117
106
|
}
|
|
118
107
|
|
|
108
|
+
function isExitCodeIgnoreFailingTests(line) {
|
|
109
|
+
return line.includes('--exit-code-ignore-failing-tests');
|
|
110
|
+
}
|
|
111
|
+
|
|
119
112
|
program.help((txt) => {
|
|
120
113
|
const lines = txt.split('\n');
|
|
121
114
|
return lines
|
|
@@ -125,12 +118,12 @@ const printUsage = () => {
|
|
|
125
118
|
!isParamsJsonOption(ln) &&
|
|
126
119
|
!isDefaultHelpLine(ln) &&
|
|
127
120
|
!isPlayerOption(ln) &&
|
|
128
|
-
!
|
|
121
|
+
!isScheduler(ln) &&
|
|
129
122
|
!isMonitorPerformance(ln) &&
|
|
130
123
|
!isUserId(ln) &&
|
|
131
|
-
!isAwsDF(ln) &&
|
|
132
124
|
!isWebdriverTimeout(ln) &&
|
|
133
|
-
!isSaveRCALocally(ln)
|
|
125
|
+
!isSaveRCALocally(ln) &&
|
|
126
|
+
!isExitCodeIgnoreFailingTests(ln)
|
|
134
127
|
)
|
|
135
128
|
.join('\n');
|
|
136
129
|
});
|
|
@@ -304,9 +297,6 @@ program
|
|
|
304
297
|
.option('--disable-sockets', 'Disable CLI sockets', false)
|
|
305
298
|
|
|
306
299
|
// Remote run options
|
|
307
|
-
.option('--testObject [test-object]', '', '')
|
|
308
|
-
.option('--remoteRunObject [remote-run-object]', '', '')
|
|
309
|
-
.option('--testObject2 [test-object]', '', '')
|
|
310
300
|
.option('--executionId [execution-id]', '', '')
|
|
311
301
|
.option('--remoteRunId [remote-run-id]', '', '')
|
|
312
302
|
.option('--schedulerId [scheduler-id]', '', '')
|
|
@@ -319,17 +309,6 @@ program
|
|
|
319
309
|
.option('--agent-port [agent-port]', 'set agent port', Number, 42543)
|
|
320
310
|
.option('--agent-bind [agent-host-bind]', 'set agent host bind', '127.0.0.1')
|
|
321
311
|
|
|
322
|
-
// Mobile options
|
|
323
|
-
.option('--apk-location [apk-local-location]', 'application apk location')
|
|
324
|
-
.option('--ipa-location [ipa-local-location]', 'application ipa location')
|
|
325
|
-
.option('--apk-timeout [apk-upload-timeout]', 'upload apk timeout in milliseconds', 15 * 60 * 1000)
|
|
326
|
-
.option('--ipa-timeout [ipa-upload-timeout]', 'upload ipa timeout in milliseconds', 15 * 60 * 1000)
|
|
327
|
-
.option('--disable-window-animation [disable-window-animation]', 'disable window animation by setting Appium capability', false)
|
|
328
|
-
|
|
329
|
-
.option('--device-udid [device-udid]', 'device udid')
|
|
330
|
-
.option('--device-name [device-name]', 'device name', 'mobile')
|
|
331
|
-
.option('--vendor-app-id [vendor-app-id]', 'use existing application id instead of upload new app')
|
|
332
|
-
|
|
333
312
|
.option('--chrome-extra-prefs [chrome-extra-prefs]', 'add extra chrome preferences', '')
|
|
334
313
|
.option('--chrome-extra-args [chrome-extra-args]', 'add extra chrome arguments separated by \',\'', '')
|
|
335
314
|
.option('--chrome-block-location [chrome-block-location]', 'block chrome geolocation', false)
|
|
@@ -342,17 +321,13 @@ program
|
|
|
342
321
|
.option('--version [version]', 'print the current version of the Testim CLI and exit', false)
|
|
343
322
|
.option('--monitor-performance', 'collect test playback performance data')
|
|
344
323
|
|
|
345
|
-
// AWS DF
|
|
346
|
-
.option('--aws-project-arn [projectArn]', 'projectArn', '')
|
|
347
|
-
.option('--aws-region [region]', 'region', 'us-west-2')
|
|
348
|
-
.option('--aws-access-key-id [accessKeyId]', 'accessKeyId', '')
|
|
349
|
-
.option('--aws-secret-access-key [secretAccessKey]', 'secretAccessKey', '')
|
|
350
|
-
|
|
351
324
|
.option('--high-speed', 'run in high speed mode')
|
|
352
325
|
.option('--lightweight-mode [settings]', 'run lightweight mode')
|
|
353
326
|
.option('--create-prefeched-data [location]', 'prefech data into local cache file')
|
|
354
327
|
.option('--use-prefeched-data [location]', 'use prefeched data from local cache file, and force using only cached data')
|
|
355
328
|
.option('--save-rca-locally [path]', 'save root cause analysis assets locally')
|
|
329
|
+
|
|
330
|
+
.option('--exit-code-ignore-failing-tests', 'dont return non zero exit code when tests fail. non zero exit code will mean a real error occurred')
|
|
356
331
|
.parse(process.argv);
|
|
357
332
|
|
|
358
333
|
module.exports = {
|
|
@@ -814,7 +789,7 @@ module.exports = {
|
|
|
814
789
|
return Promise.reject(new ArgError('parallel could not be a negative number or not number, --parallel <number-of-tests>'));
|
|
815
790
|
}
|
|
816
791
|
|
|
817
|
-
if ([CLI_MODE.EXTENSION, CLI_MODE.SELENIUM
|
|
792
|
+
if ([CLI_MODE.EXTENSION, CLI_MODE.SELENIUM].indexOf(program.mode) === -1) {
|
|
818
793
|
return Promise.reject(new ArgError(`runner mode <${program.mode}> is not supported`));
|
|
819
794
|
}
|
|
820
795
|
|
|
@@ -825,38 +800,11 @@ module.exports = {
|
|
|
825
800
|
if (
|
|
826
801
|
!program.browser &&
|
|
827
802
|
!isTestConfigSpecified &&
|
|
828
|
-
!isTestPlanSpecified
|
|
829
|
-
!program.testObject2
|
|
803
|
+
!isTestPlanSpecified
|
|
830
804
|
) {
|
|
831
805
|
program.browser = 'chrome';
|
|
832
806
|
}
|
|
833
807
|
|
|
834
|
-
if (program.testObject) {
|
|
835
|
-
try {
|
|
836
|
-
program.testObject = JSON.parse(program.testObject);
|
|
837
|
-
} catch (err) {
|
|
838
|
-
return Promise.reject(new ArgError(`failed to parse testObject string error: ${err.message}`));
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
if (program.testObject2) {
|
|
843
|
-
try {
|
|
844
|
-
const obj = decodeURIComponent(program.testObject2);
|
|
845
|
-
program.testObject = JSON.parse(obj);
|
|
846
|
-
} catch (err) {
|
|
847
|
-
return Promise.reject(new ArgError(`failed to parse testObject string error: ${err.message}`));
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
if (program.remoteRunObject) {
|
|
852
|
-
try {
|
|
853
|
-
const obj = decodeURIComponent(program.remoteRunObject);
|
|
854
|
-
program.remoteRunObject = JSON.parse(obj);
|
|
855
|
-
} catch (err) {
|
|
856
|
-
return Promise.reject(new ArgError(`failed to parse remoteRunObject string error: ${err.message}`));
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
|
|
860
808
|
if (program.testPlan && program.testPlan.length === 0 && program.testPlanId && program.testPlanId.length === 0) {
|
|
861
809
|
if (
|
|
862
810
|
typeof program.host !== 'string' &&
|
|
@@ -950,9 +898,6 @@ module.exports = {
|
|
|
950
898
|
} else {
|
|
951
899
|
program.files = [];
|
|
952
900
|
}
|
|
953
|
-
if (program.apkLocation && program.ipaLocation) {
|
|
954
|
-
return Promise.reject(new ArgError('cannot set --apk-location and --ipa-location. please choose the one compatible with your project type'));
|
|
955
|
-
}
|
|
956
901
|
|
|
957
902
|
if (program.setRetention && !_.inRange(_.parseInt(program.setRetention), 1, 11)) {
|
|
958
903
|
return Promise.reject(new ArgError('Please provide the number of days that the test results will be retained for (--set-retention must be a whole number between 1 to 10)'));
|
|
@@ -1119,7 +1064,6 @@ module.exports = {
|
|
|
1119
1064
|
testobjectSauce: program.testobjectSauce,
|
|
1120
1065
|
gridUsername: program.gridUsername,
|
|
1121
1066
|
gridPassword: program.gridPassword,
|
|
1122
|
-
vendorAppId: program.vendorAppId,
|
|
1123
1067
|
overrideExecutionName: program.overrideExecutionName,
|
|
1124
1068
|
|
|
1125
1069
|
tmsSuppressReporting: Boolean(program.suppressTmsReporting) || Boolean(program.tmsSuppressReporting),
|
|
@@ -1186,9 +1130,7 @@ module.exports = {
|
|
|
1186
1130
|
codeCoverageInclude: program.codeCoverageInclude,
|
|
1187
1131
|
|
|
1188
1132
|
// Remote run options
|
|
1189
|
-
testObject: program.testObject,
|
|
1190
1133
|
executionId: program.executionId,
|
|
1191
|
-
remoteRunObject: program.remoteRunObject,
|
|
1192
1134
|
remoteRunId: program.remoteRunId,
|
|
1193
1135
|
schedulerId: program.schedulerId,
|
|
1194
1136
|
source: program.source,
|
|
@@ -1200,19 +1142,6 @@ module.exports = {
|
|
|
1200
1142
|
w3cCapabilities: program.w3cCapabilities,
|
|
1201
1143
|
oldCapabilities: program.oldCapabilities,
|
|
1202
1144
|
|
|
1203
|
-
//APK options
|
|
1204
|
-
apkLocation: program.apkLocation,
|
|
1205
|
-
apkTimeout: program.apkTimeout,
|
|
1206
|
-
|
|
1207
|
-
// IPA options
|
|
1208
|
-
ipaLocation: program.ipaLocation,
|
|
1209
|
-
ipaTimeout: program.ipaTimeout,
|
|
1210
|
-
|
|
1211
|
-
disableWindowAnimation: program.disableWindowAnimation,
|
|
1212
|
-
|
|
1213
|
-
deviceUdid: program.deviceUdid,
|
|
1214
|
-
deviceName: program.deviceName,
|
|
1215
|
-
|
|
1216
1145
|
chromeBlockLocation: program.chromeBlockLocation,
|
|
1217
1146
|
chromeUserDataDir: program.chromeUserDataDir,
|
|
1218
1147
|
retries: program.retries,
|
|
@@ -1226,16 +1155,11 @@ module.exports = {
|
|
|
1226
1155
|
|
|
1227
1156
|
user: program.user,
|
|
1228
1157
|
|
|
1229
|
-
awsProjectArn: program.awsProjectArn,
|
|
1230
|
-
awsRegion: program.awsRegion,
|
|
1231
|
-
|
|
1232
|
-
awsAccessKeyId: program.awsAccessKeyId,
|
|
1233
|
-
awsSecretAccessKey: program.awsSecretAccessKey,
|
|
1234
|
-
|
|
1235
1158
|
lightweightMode: program.lightweightMode,
|
|
1236
1159
|
createPrefechedData: program.createPrefechedData,
|
|
1237
1160
|
|
|
1238
1161
|
saveRCALocally: program.saveRcaLocally,
|
|
1162
|
+
exitCodeIgnoreFailingTests: program.exitCodeIgnoreFailingTests,
|
|
1239
1163
|
|
|
1240
1164
|
disableSockets: program.disableSockets,
|
|
1241
1165
|
});
|
package/runner.js
CHANGED
|
@@ -15,16 +15,13 @@ const npmDriver = require('./testimNpmDriver.js');
|
|
|
15
15
|
const analytics = require('./commons/testimAnalytics');
|
|
16
16
|
const branchService = require('./services/branchService');
|
|
17
17
|
const gridService = require('./services/gridService');
|
|
18
|
-
const strategySelector = require('./runners/strategies/Strategy');
|
|
19
18
|
const { ArgError, QuotaDepletedError } = require('./errors');
|
|
20
19
|
const featureFlags = require('./commons/featureFlags');
|
|
21
20
|
const perf = require('./commons/performance-logger');
|
|
22
21
|
const { prepareMockNetwork, initializeUserWithAuth } = require('./commons/prepareRunner');
|
|
23
|
-
const { hasTestPlanFlag } = require('./utils');
|
|
24
22
|
|
|
25
23
|
const FREE_PLAN_MINIMUM_BROWSER_TIMEOUT = 30 * 60 * 1000;
|
|
26
24
|
|
|
27
|
-
const AnonymousTestPlanRunner = require('./runners/AnonymousTestPlanRunner');
|
|
28
25
|
const TestPlanRunner = require('./runners/TestPlanRunner');
|
|
29
26
|
const labFeaturesService = require('./services/labFeaturesService');
|
|
30
27
|
const featureAvailabilityService = require('./commons/featureAvailabilityService');
|
|
@@ -85,17 +82,6 @@ function validateCliAccount(options) {
|
|
|
85
82
|
});
|
|
86
83
|
}
|
|
87
84
|
|
|
88
|
-
function validateRemoteRunAccount(options) {
|
|
89
|
-
return validateProjectQuotaNotDepleted(options)
|
|
90
|
-
.catch(err => {
|
|
91
|
-
if (err instanceof QuotaDepletedError) {
|
|
92
|
-
return Promise.reject(err);
|
|
93
|
-
}
|
|
94
|
-
logger.error('could not validate remote run account', { err });
|
|
95
|
-
return undefined;
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
85
|
function analyticsIdentify(projectId) {
|
|
100
86
|
const authData = testimCustomToken.getTokenV3UserData();
|
|
101
87
|
return analytics.identify({
|
|
@@ -138,7 +124,7 @@ function setCompany(options, company) {
|
|
|
138
124
|
const { onprem, id, storageBaseUrl, storageType, name, activePlan = {} } = company;
|
|
139
125
|
if (onprem) {
|
|
140
126
|
const { mode, extensionPath, ext, playerPath } = options;
|
|
141
|
-
if ([CLI_MODE.SELENIUM
|
|
127
|
+
if ([CLI_MODE.SELENIUM].includes(mode) && !playerPath) {
|
|
142
128
|
return Promise.reject(new ArgError('in selenium on prem mode --player-path must be provided'));
|
|
143
129
|
}
|
|
144
130
|
if (mode === 'extension' && !extensionPath && !ext) {
|
|
@@ -214,32 +200,13 @@ async function setMockNetworkRules(options) {
|
|
|
214
200
|
|
|
215
201
|
function runRunner(options, customExtensionLocalLocation) {
|
|
216
202
|
perf.log('in runner.js runRunner');
|
|
217
|
-
const branchToUse = branchService.getCurrentBranch();
|
|
218
203
|
|
|
219
|
-
const
|
|
220
|
-
const {
|
|
221
|
-
remoteRunObject, testObject, executionId, project, remoteRunId, useLocalChromeDriver, useChromeLauncher,
|
|
222
|
-
} = options;
|
|
223
|
-
|
|
224
|
-
if (testObject && executionId) {
|
|
225
|
-
const SchedulerRemoteRunner = require('./runners/SchedulerRemoteRunner');
|
|
226
|
-
const schedulerRemoteRunner = new SchedulerRemoteRunner(selectedStrategy);
|
|
227
|
-
return validateRemoteRunAccount(options)
|
|
228
|
-
.then(() => schedulerRemoteRunner.runTest(options, branchToUse));
|
|
229
|
-
}
|
|
204
|
+
const { project, remoteRunId, useLocalChromeDriver, useChromeLauncher } = options;
|
|
230
205
|
|
|
231
206
|
if (!remoteRunId) {
|
|
232
207
|
options.source = (useLocalChromeDriver || useChromeLauncher) ? 'cli-local' : 'cli';
|
|
233
208
|
}
|
|
234
209
|
|
|
235
|
-
if (remoteRunObject && executionId) {
|
|
236
|
-
const { testList, gridInfo } = remoteRunObject;
|
|
237
|
-
const DeviceFarmRemoteRunner = require('./runners/DeviceFarmRemoteRunner');
|
|
238
|
-
const deviceFarmRemoteRunner = new DeviceFarmRemoteRunner(selectedStrategy);
|
|
239
|
-
return validateRemoteRunAccount(options)
|
|
240
|
-
.then(() => deviceFarmRemoteRunner.runTest(executionId, testList, gridInfo, branchToUse, options));
|
|
241
|
-
}
|
|
242
|
-
|
|
243
210
|
npmDriver.checkNpmVersion();
|
|
244
211
|
perf.log('in runner.js after checkNpmVersion');
|
|
245
212
|
|
|
@@ -247,15 +214,7 @@ function runRunner(options, customExtensionLocalLocation) {
|
|
|
247
214
|
.log('in runRunner before tunnel.connect')
|
|
248
215
|
.then(() => tunnel.connect(options, testimCustomToken.getTokenV3UserData()))
|
|
249
216
|
.log('in runRunner after tunnel.connect')
|
|
250
|
-
.then(() =>
|
|
251
|
-
if (hasTestPlanFlag(options)) {
|
|
252
|
-
const testPlanRunner = new TestPlanRunner(selectedStrategy);
|
|
253
|
-
return testPlanRunner.runTestPlans(options, branchToUse);
|
|
254
|
-
}
|
|
255
|
-
const anonymousTestPlanRunner = new AnonymousTestPlanRunner(selectedStrategy);
|
|
256
|
-
perf.log('right before runAnonymousTestPlan');
|
|
257
|
-
return anonymousTestPlanRunner.runAnonymousTestPlan(options, branchToUse);
|
|
258
|
-
})
|
|
217
|
+
.then(() => new TestPlanRunner(customExtensionLocalLocation).run(options))
|
|
259
218
|
.log('before tunnel.disconnect')
|
|
260
219
|
.tap(() => tunnel.disconnect(options))
|
|
261
220
|
.tap(() => gridService.keepAlive.end(project))
|
|
@@ -1,53 +1,43 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class LocalStrategy extends BaseStrategy {
|
|
3
|
+
const utils = require('../utils');
|
|
4
|
+
const logger = require('../commons/logger').getLogger('parallel-worker-manager');
|
|
5
|
+
const { CLI_MODE } = require('../commons/constants');
|
|
6
|
+
const analyticsService = require('../services/analyticsService');
|
|
7
|
+
const config = require('../commons/config');
|
|
8
|
+
const ExecutionQueue = require('../executionQueue');
|
|
9
|
+
|
|
10
|
+
const testimCustomToken = require('../commons/testimCustomToken');
|
|
11
|
+
const testimServicesApi = require('../commons/testimServicesApi');
|
|
12
|
+
const labFeaturesService = require('../services/labFeaturesService');
|
|
13
|
+
const perf = require('../commons/performance-logger');
|
|
14
|
+
const { StopRunOnError } = require('../errors');
|
|
15
|
+
|
|
16
|
+
require('../player/webdriver'); // preload
|
|
17
|
+
|
|
18
|
+
class ParallelWorkerManager {
|
|
21
19
|
constructor(customExtensionLocalLocation) {
|
|
22
|
-
super();
|
|
23
20
|
this.customExtensionLocalLocation = customExtensionLocalLocation;
|
|
24
21
|
}
|
|
25
22
|
|
|
26
|
-
startWorker(worker, options, onTestStarted, onTestCompleted, executionId, onGridSlot, onTestIgnored) {
|
|
27
|
-
throw new Error('need to implement');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
23
|
getWorkerType(mode) {
|
|
31
24
|
switch (mode) {
|
|
32
25
|
case CLI_MODE.SELENIUM:
|
|
33
|
-
return require('
|
|
34
|
-
case CLI_MODE.APPIUM:
|
|
35
|
-
case CLI_MODE.DEVICE_FARM_APPIUM:
|
|
36
|
-
return require('../../workers/WorkerAppium');
|
|
26
|
+
return require('../workers/WorkerSelenium');
|
|
37
27
|
default:
|
|
38
28
|
if (labFeaturesService.isFeatureAvailableForProject('useSameBrowserForMultiTests')) {
|
|
39
|
-
return require('
|
|
29
|
+
return require('../workers/WorkerExtensionSingleBrowser');
|
|
40
30
|
}
|
|
41
|
-
return require('
|
|
31
|
+
return require('../workers/WorkerExtension');
|
|
42
32
|
}
|
|
43
33
|
}
|
|
44
34
|
|
|
45
|
-
createWorkers(count, queue, mode) {
|
|
35
|
+
createWorkers(count, queue, mode, ...args) {
|
|
46
36
|
const Worker = this.getWorkerType(mode);
|
|
47
37
|
const createWorker = () => {
|
|
48
38
|
try {
|
|
49
39
|
perf.log('before new Worker', mode);
|
|
50
|
-
return new Worker(queue,
|
|
40
|
+
return new Worker(queue, ...args);
|
|
51
41
|
} finally {
|
|
52
42
|
perf.log('after new Worker', mode);
|
|
53
43
|
}
|
|
@@ -56,9 +46,9 @@ class LocalStrategy extends BaseStrategy {
|
|
|
56
46
|
return Array.from(new Array(count), createWorker);
|
|
57
47
|
}
|
|
58
48
|
|
|
59
|
-
runTests(testList, testStatus, executionId, options, branchToUse, authData, workerCount, stopOnError) {
|
|
49
|
+
async runTests(testList, testStatus, executionId, options, branchToUse, authData, workerCount, stopOnError) {
|
|
60
50
|
if (testList && testList.length === 0) {
|
|
61
|
-
return
|
|
51
|
+
return undefined;
|
|
62
52
|
}
|
|
63
53
|
|
|
64
54
|
const runAndWaitToComplete = token => new Promise((resolve, reject) => {
|
|
@@ -72,13 +62,13 @@ class LocalStrategy extends BaseStrategy {
|
|
|
72
62
|
const companyName = options.company && options.company.name;
|
|
73
63
|
const source = options.source || 'cli';
|
|
74
64
|
const user = options.user;
|
|
75
|
-
const
|
|
65
|
+
const companyPlan = options.company && options.company.planType;
|
|
76
66
|
const projectName = options.projectData && options.projectData.name;
|
|
77
67
|
const lightweightMode = options.lightweightMode;
|
|
78
68
|
const sessionType = utils.getSessionType(options);
|
|
79
69
|
|
|
80
70
|
const onTestStarted = (wid, testId, resultId, isRerun, testRetryKey) => {
|
|
81
|
-
|
|
71
|
+
analyticsService.analyticsTestStart({
|
|
82
72
|
authData,
|
|
83
73
|
executionId,
|
|
84
74
|
projectId,
|
|
@@ -87,7 +77,7 @@ class LocalStrategy extends BaseStrategy {
|
|
|
87
77
|
companyId,
|
|
88
78
|
companyName,
|
|
89
79
|
projectName,
|
|
90
|
-
|
|
80
|
+
companyPlan,
|
|
91
81
|
sessionType,
|
|
92
82
|
source,
|
|
93
83
|
user,
|
|
@@ -95,13 +85,8 @@ class LocalStrategy extends BaseStrategy {
|
|
|
95
85
|
});
|
|
96
86
|
return testStatus.testStartAndReport(wid, executionId, resultId, isRerun, testRetryKey);
|
|
97
87
|
};
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}).then(() => {
|
|
101
|
-
const isLocalRun = Boolean(options.useLocalChromeDriver || options.useChromeLauncher);
|
|
102
|
-
if (lightweightMode && lightweightMode.disableResults && isLocalRun) {
|
|
103
|
-
return undefined;
|
|
104
|
-
}
|
|
88
|
+
|
|
89
|
+
const onTestCompleted = async (wid, testId, testResult, sessionId, isRerun) => {
|
|
105
90
|
const update = {};
|
|
106
91
|
if (lightweightMode && lightweightMode.onlyTestIdsNoSuite) {
|
|
107
92
|
update.show = true;
|
|
@@ -137,18 +122,15 @@ class LocalStrategy extends BaseStrategy {
|
|
|
137
122
|
} else if (options.saucelabs) {
|
|
138
123
|
update.gridName = 'saucelabs-from-options';
|
|
139
124
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
return undefined;
|
|
146
|
-
}).then(() => {
|
|
125
|
+
|
|
126
|
+
await testStatus.testEndAndReport(wid, testResult, executionId, sessionId, isRerun, update)
|
|
127
|
+
.catch(err => logger.error('testEndAndReport threw an error', { err }));
|
|
128
|
+
|
|
147
129
|
if (isRerun) {
|
|
148
130
|
return undefined;
|
|
149
131
|
}
|
|
150
132
|
combinedTestResults[testResult.resultId] = testResult;
|
|
151
|
-
|
|
133
|
+
analyticsService.analyticsTestEnd({
|
|
152
134
|
authData,
|
|
153
135
|
executionId,
|
|
154
136
|
projectId,
|
|
@@ -158,7 +140,7 @@ class LocalStrategy extends BaseStrategy {
|
|
|
158
140
|
companyId,
|
|
159
141
|
companyName,
|
|
160
142
|
projectName,
|
|
161
|
-
|
|
143
|
+
companyPlan,
|
|
162
144
|
sessionType,
|
|
163
145
|
source,
|
|
164
146
|
user,
|
|
@@ -167,15 +149,15 @@ class LocalStrategy extends BaseStrategy {
|
|
|
167
149
|
});
|
|
168
150
|
if (stopOnError && !testResult.success) {
|
|
169
151
|
reject(new StopRunOnError());
|
|
170
|
-
|
|
152
|
+
throw new StopRunOnError();
|
|
171
153
|
}
|
|
172
154
|
const completedTests = Object.keys(combinedTestResults).length;
|
|
173
155
|
if (completedTests === testCount) {
|
|
174
156
|
resolve(combinedTestResults);
|
|
175
157
|
return undefined;
|
|
176
158
|
}
|
|
177
|
-
return
|
|
178
|
-
}
|
|
159
|
+
return undefined;
|
|
160
|
+
};
|
|
179
161
|
|
|
180
162
|
const onTestIgnored = (wid, testResult) => {
|
|
181
163
|
combinedTestResults[testResult.resultId] = testResult;
|
|
@@ -185,6 +167,7 @@ class LocalStrategy extends BaseStrategy {
|
|
|
185
167
|
resolve(combinedTestResults);
|
|
186
168
|
}
|
|
187
169
|
};
|
|
170
|
+
|
|
188
171
|
const onGridSlot = (executionId, resultId, gridInfo) => testStatus.onGridSlot(executionId, resultId, gridInfo);
|
|
189
172
|
|
|
190
173
|
options.userData = {
|
|
@@ -198,25 +181,33 @@ class LocalStrategy extends BaseStrategy {
|
|
|
198
181
|
servicesUrl: config.SERVICES_HOST,
|
|
199
182
|
};
|
|
200
183
|
perf.log('in localStrategy before createWorker');
|
|
201
|
-
this.createWorkers(workerCount, executionQueue, options.mode)
|
|
184
|
+
this.createWorkers(workerCount, executionQueue, options.mode, options, this.customExtensionLocalLocation, executionId, onTestStarted, onTestCompleted, onGridSlot, onTestIgnored)
|
|
202
185
|
.forEach((worker, index) => {
|
|
203
|
-
perf.log('before schedule
|
|
186
|
+
perf.log('before schedule worker.run after createWorkers');
|
|
204
187
|
schedule(() => {
|
|
205
|
-
|
|
188
|
+
perf.log('right before worker.run');
|
|
189
|
+
worker.run();
|
|
206
190
|
}, index);
|
|
207
191
|
});
|
|
208
|
-
function schedule(fn, index) {
|
|
209
|
-
if (index === 0) {
|
|
210
|
-
fn();
|
|
211
|
-
} else {
|
|
212
|
-
setTimeout(fn, index * config.START_WORKER_DELAY_MS);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
192
|
});
|
|
216
193
|
|
|
217
|
-
|
|
218
|
-
|
|
194
|
+
try {
|
|
195
|
+
const token = await testimCustomToken.getCustomTokenV3();
|
|
196
|
+
return await runAndWaitToComplete(token);
|
|
197
|
+
} catch (err) {
|
|
198
|
+
logger.error('failed running parallel workers', { executionId, err });
|
|
199
|
+
throw err;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
function schedule(fn, index) {
|
|
206
|
+
if (index === 0) {
|
|
207
|
+
fn();
|
|
208
|
+
} else {
|
|
209
|
+
setTimeout(fn, index * config.START_WORKER_DELAY_MS);
|
|
219
210
|
}
|
|
220
211
|
}
|
|
221
212
|
|
|
222
|
-
module.exports =
|
|
213
|
+
module.exports = ParallelWorkerManager;
|