@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.
Files changed (70) hide show
  1. package/README.md +1 -1
  2. package/cli/onExit.js +12 -1
  3. package/cli.js +5 -1
  4. package/commons/constants.js +0 -25
  5. package/commons/featureFlags.js +2 -0
  6. package/commons/npmWrapper.js +46 -14
  7. package/commons/npmWrapper.test.js +182 -6
  8. package/commons/socket/testResultService.js +4 -14
  9. package/commons/testimAnalytics.js +0 -1
  10. package/commons/testimDesiredCapabilitiesBuilder.js +0 -94
  11. package/commons/testimServicesApi.js +9 -79
  12. package/executionQueue.js +7 -4
  13. package/npm-shrinkwrap.json +960 -524
  14. package/package.json +3 -1
  15. package/player/stepActions/baseJsStepAction.js +5 -1
  16. package/player/stepActions/pixelValidationStepAction.js +28 -0
  17. package/player/stepActions/salesforceAutoLoginStepAction.js +5 -3
  18. package/player/stepActions/stepActionRegistrar.js +4 -48
  19. package/player/utils/eyeSdkService.js +230 -0
  20. package/reports/consoleReporter.js +29 -44
  21. package/reports/reporter.js +0 -21
  22. package/runOptions.js +13 -89
  23. package/runner.js +3 -44
  24. package/runners/{strategies/LocalStrategy.js → ParallelWorkerManager.js} +59 -68
  25. package/runners/TestPlanRunner.js +288 -67
  26. package/runners/runnerUtils.js +73 -0
  27. package/services/analyticsService.js +94 -0
  28. package/services/gridService.js +24 -20
  29. package/services/gridService.test.js +21 -21
  30. package/stepPlayers/hybridStepPlayback.js +4 -1
  31. package/stepPlayers/tdkHybridStepPlayback.js +1 -0
  32. package/testRunHandler.js +23 -5
  33. package/testRunStatus.js +18 -27
  34. package/utils.js +5 -5
  35. package/workers/BaseWorker.js +39 -39
  36. package/workers/BaseWorker.test.js +1 -1
  37. package/workers/WorkerExtensionSingleBrowser.js +6 -3
  38. package/commons/apkUploader/apkUploader.js +0 -46
  39. package/commons/apkUploader/apkUploaderFactory.js +0 -68
  40. package/commons/apkUploader/deviceFarmApkUploader.js +0 -41
  41. package/commons/apkUploader/saucelabsApkUploader.js +0 -36
  42. package/commons/apkUploader/testObjectApkUploader.js +0 -34
  43. package/player/mobile/mobileTestPlayer.js +0 -80
  44. package/player/mobile/mobileWebDriver.js +0 -155
  45. package/player/mobile/services/frameLocatorMock.js +0 -18
  46. package/player/mobile/services/mobilePortSelector.js +0 -22
  47. package/player/mobile/services/mobileTabService.js +0 -241
  48. package/player/mobile/utils/mobileScreenshotUtils.js +0 -46
  49. package/player/mobile/utils/mobileWindowUtils.js +0 -84
  50. package/player/stepActions/mobile/android/androidLocateStepAction.js +0 -122
  51. package/player/stepActions/mobile/android/androidLongClickStepAction.js +0 -12
  52. package/player/stepActions/mobile/android/androidScrollStepAction.js +0 -134
  53. package/player/stepActions/mobile/android/androidSpecialKeyStepAction.js +0 -22
  54. package/player/stepActions/mobile/android/androidSwipeStepAction.js +0 -32
  55. package/player/stepActions/mobile/androidGlobalActionStepAction.js +0 -12
  56. package/player/stepActions/mobile/androidTapStepAction.js +0 -19
  57. package/player/stepActions/mobile/androidTextChangeStepAction.js +0 -23
  58. package/player/stepActions/mobile/ios/iosLocateStepAction.js +0 -124
  59. package/player/stepActions/mobile/ios/iosScrollStepAction.js +0 -76
  60. package/runners/AnonymousTestPlanRunner.js +0 -106
  61. package/runners/BaseRunner.js +0 -42
  62. package/runners/BaseTestPlanRunner.js +0 -194
  63. package/runners/DeviceFarmRemoteRunner.js +0 -50
  64. package/runners/SchedulerRemoteRunner.js +0 -47
  65. package/runners/strategies/BaseStrategy.js +0 -86
  66. package/runners/strategies/DeviceFarmStrategy.js +0 -195
  67. package/runners/strategies/LocalDeviceFarmStrategy.js +0 -12
  68. package/runners/strategies/LocalTestStrategy.js +0 -14
  69. package/runners/strategies/Strategy.js +0 -17
  70. package/workers/WorkerAppium.js +0 -70
@@ -1,47 +0,0 @@
1
- "use strict";
2
-
3
- const utils = require('../utils');
4
- const config = require('../commons/config');
5
- const testimCustomToken = require('../commons/testimCustomToken');
6
- const BaseRunner = require('./BaseRunner');
7
- const TestRunStatus = require('../testRunStatus');
8
- const reporter = require("../reports/reporter");
9
- const guid = require('../utils').guid;
10
- const Logger = require('../commons/logger');
11
- const logger = Logger.getLogger('remote-test-runner');
12
-
13
- class SchedulerRemoteRunner extends BaseRunner {
14
- runExecution(testList, testStatus, executionId, options, branchToUse) {
15
- const sessionType = utils.getSessionType(options);
16
- const projectId = options.project;
17
- // report exec start analytics
18
- const authData = testimCustomToken.getTokenV3UserData();
19
- this.analyticsExecsStart({authData, executionId, projectId, sessionType});
20
- const workerCount = config.TESTIM_CONCURRENT_WORKER_COUNT || options.parallel;
21
-
22
- return this.strategy.runTests(testList, testStatus, executionId, options, branchToUse, authData, workerCount);
23
- }
24
-
25
- runTest(options, branchToUse) {
26
- const executionId = options.executionId || guid();
27
- const test = options.testObject;
28
- Logger.setExecutionId(executionId);
29
-
30
- logger.info("start to run test", {
31
- executionId: executionId,
32
- options: Object.assign({}, options, {token: undefined}),
33
- branchToUse: branchToUse,
34
- test: test
35
- });
36
-
37
- const testArray = [test];
38
- const testPlanName = options.overrideExecutionName || "remote run";
39
- const testStatus = new TestRunStatus(testArray, options, null, branchToUse);
40
- reporter.onTestPlanStarted([], testArray, [], testPlanName, executionId);
41
- return this.runExecution(testArray, testStatus, executionId, options, branchToUse)
42
- .tap(results => reporter.onTestPlanFinished(results, testPlanName, this.startTime, executionId))
43
- .then(combinedTestResults => combinedTestResults);
44
- }
45
- }
46
-
47
- module.exports = SchedulerRemoteRunner;
@@ -1,86 +0,0 @@
1
- 'use strict';
2
-
3
- const analytics = require('../../commons/testimAnalytics');
4
- const { isCi } = require('../../cli/isCiRun');
5
-
6
- const calcSource = (source, user) => {
7
- if (source !== 'cli' && source !== 'cli-local') {
8
- return source;
9
- }
10
-
11
- if (isCi && user) {
12
- return 'ci-with-user';
13
- }
14
-
15
- if (isCi) {
16
- return 'ci';
17
- }
18
-
19
- if (user) {
20
- return 'cli-with-user';
21
- }
22
-
23
- return source;
24
- };
25
-
26
- function setLightweightAnalytics(properties, lightweightMode) {
27
- if (lightweightMode && lightweightMode.type) {
28
- properties[`${lightweightMode.type}Mode`] = true;
29
- }
30
- return properties;
31
- }
32
-
33
- class BaseStrategy {
34
- analyticsTestStart({
35
- executionId, projectId, testId, resultId, companyId, companyName, projectName, companyPlanType, sessionType, source, user, lightweightMode,
36
- }) {
37
- const properties = setLightweightAnalytics({
38
- executionId,
39
- projectId,
40
- testId,
41
- resultId,
42
- companyId,
43
- companyName,
44
- projectName,
45
- companyPlanType,
46
- sessionType,
47
- source: calcSource(source, user),
48
- }, lightweightMode);
49
- analytics.trackWithCIUser('test-run-ci', properties);
50
- }
51
-
52
- analyticsTestEnd({
53
- executionId, projectId, testId, resultId, result, companyId, companyName, projectName, companyPlanType, sessionType, source, user, lightweightMode,
54
- logger,
55
- }) {
56
- try {
57
- const properties = setLightweightAnalytics({
58
- executionId,
59
- projectId,
60
- testId,
61
- resultId,
62
- companyId,
63
- companyName,
64
- projectName,
65
- companyPlanType,
66
- sessionType,
67
- mockNetworkEnabled: result.wasMockNetworkActivated,
68
- source: calcSource(source, user),
69
- }, lightweightMode);
70
-
71
- if (result.success) {
72
- analytics.trackWithCIUser('test-run-ci-success', properties);
73
- return;
74
- }
75
- analytics.trackWithCIUser('test-run-ci-fail', Object.assign({}, properties, { failureReason: result.failureReason }));
76
- } catch (err) {
77
- logger.error('failed to update test end analytics', { err });
78
- }
79
- }
80
-
81
- runTests(testList, testStatus, executionId, options, branchToUse, authData, workerCount, stopOnError) {
82
- throw new Error('need to implement on child');
83
- }
84
- }
85
-
86
- module.exports = BaseStrategy;
@@ -1,195 +0,0 @@
1
- 'use strict';
2
-
3
- const Promise = require('bluebird');
4
- const _ = require('lodash');
5
- const { CLI_MODE, runnerTestStatus } = require('../../commons/constants');
6
- const BaseStrategy = require('./BaseStrategy');
7
- const config = require('../../commons/config');
8
- const { deviceFarm, testRunStatus } = require('../../commons/constants');
9
- const logger = require('../../commons/logger').getLogger('deviceFarm-strategy');
10
- const utils = require('../../utils');
11
- const RealDataService = require('../../commons/socket/realDataService');
12
- const { getBrowserWithRetries: getDeviceWithRetries } = require('../../workers/workerUtils');
13
- const { GetBrowserError, ArgError } = require('../../errors');
14
- const { getAppCaps } = require('../../commons/apkUploader/apkUploaderFactory');
15
- const reporter = require('../../reports/reporter');
16
- const BaseWorker = require('../../workers/BaseWorker');
17
-
18
- const testimServicesApi = require('../../commons/testimServicesApi');
19
- const gridService = require('../../services/gridService');
20
-
21
- const MAX_EXECUTION_TIMEOUT = 150 * 60 * 1000; //150 min is the maximum allowed by device farm
22
- const STATUS_CHECK_INTERVAL = 20000;
23
-
24
- const DF_RUN_STATUS = deviceFarm.status;
25
- const DF_RUN_RESULT = deviceFarm.result;
26
- const TESTIM_RUN_STATUS = testRunStatus;
27
-
28
- class DeviceFarmStrategy extends BaseStrategy {
29
- constructor() {
30
- super();
31
- this.lastDeviceFarmStatus = DF_RUN_STATUS.INITIALIZING;
32
- }
33
-
34
- getDeviceFarmRunStatus(projectId, runArn) {
35
- return testimServicesApi.getDeviceFarmRun(projectId, runArn)
36
- .then(runInfo => {
37
- if (this.lastDeviceFarmStatus !== runInfo.status) {
38
- logger.info(`DeviceFarm run status changed from: ${this.lastDeviceFarmStatus} to ${runInfo.status}`);
39
- this.lastDeviceFarmStatus = runInfo.status;
40
- }
41
- if ([DF_RUN_STATUS.COMPLETED, DF_RUN_STATUS.STOPPING].includes(runInfo.status)) {
42
- return runInfo;
43
- }
44
- throw new Error('still running');
45
- });
46
- }
47
-
48
- convertTestResultObjectStatusToReportFormat(executionResults) {
49
- Object.keys(executionResults).forEach(resultId => {
50
- executionResults[resultId].status = executionResults[resultId].success ? runnerTestStatus.PASSED : runnerTestStatus.FAILED;
51
- });
52
- return executionResults;
53
- }
54
-
55
- convertTestResultArrayStatusToReportFormat(executionResults) {
56
- executionResults.forEach(result => {
57
- result.status = result.success ? runnerTestStatus.PASSED : runnerTestStatus.FAILED;
58
- });
59
- return executionResults;
60
- }
61
-
62
- buildConfiguration(testList) {
63
- const { overrideTestConfig } = _.uniqBy(testList, 'overrideTestConfig.name')[0];
64
- if (_.isEmpty(overrideTestConfig)) {
65
- return {};
66
- }
67
- const configuration = Object.assign({}, overrideTestConfig);
68
- const [platformName, platformVersion] = configuration.os.split(' ');
69
-
70
- return {
71
- platformName,
72
- deviceName: configuration.browser,
73
- platformVersion,
74
- };
75
- }
76
-
77
- buildDeviceFarmConfiguration(options) {
78
- const validateOptionKeys = (option) => {
79
- const { deviceName, platformVersion /*platformName, appiumVersion,*/ } = option;
80
- return deviceName && platformVersion;
81
- };
82
- const mapOptionToConfig = (option) => ({
83
- deviceName: option.deviceName,
84
- platformVersion: option.platformVersion,
85
- });
86
-
87
- if (_.isArray(options)) {
88
- return options.filter(validateOptionKeys).map(mapOptionToConfig);
89
- }
90
- return validateOptionKeys(options) ? mapOptionToConfig(options) : {};
91
- }
92
-
93
- runTests(testList, testStatus, executionId, options, branchToUse, authData, workerCount, stopOnError) {
94
- if (testList && testList.length === 0) {
95
- return Promise.resolve();
96
- }
97
- const executionResults = {};
98
- const projectId = options.project;
99
- const companyId = options.company.companyId;
100
- const workerId = BaseWorker.getWorkerId();
101
- const testResultId = '';
102
-
103
- const getBrowserTimeout = options.browserTimeout;
104
- const newBrowserWaitTimeout = options.newBrowserWaitTimeout;
105
-
106
- const configuration = this.buildConfiguration(testList);
107
- if (_.isEmpty(configuration)) {
108
- return Promise.reject(new ArgError('--test-config is missing or not properly used'));
109
- }
110
-
111
- const realDataService = new RealDataService();
112
- const releaseSlotOnTestFinished = true;
113
- const callbacksForGetDeviceRetryLogic = {
114
- getBrowserOnce() {
115
- reporter.onGetSession(workerId, `for execution ${executionId}`, CLI_MODE.APPIUM);
116
- return gridService.getGridSlot(configuration.platformName, executionId, testResultId, () => {}, options, workerId);
117
- },
118
- testPlayerFactory: () => {}, // no factory since this is a remote run
119
- releaseSlotOnTestFinished,
120
- };
121
- const deviceFetchConfig = {
122
- totalTimeoutDuration: newBrowserWaitTimeout,
123
- singleGetBrowserDuration: getBrowserTimeout,
124
- projectId,
125
- workerId,
126
- reporter,
127
- };
128
- return realDataService.init(projectId)
129
- .then(() => getDeviceWithRetries(callbacksForGetDeviceRetryLogic, deviceFetchConfig)).then(gridInfo => {
130
- const allowedRemoteRunEnv = Object.keys(config);
131
- const env = _.reduce(process.env, (envObj, value, key) => {
132
- if (allowedRemoteRunEnv.includes(key)) {
133
- envObj[key] = value;
134
- }
135
- return envObj;
136
- }, {});
137
-
138
- const remoteRunObject = {
139
- gridInfo,
140
- testList,
141
- echoedOptions: {
142
- disableWindowAnimation: options.disableWindowAnimation,
143
- baseUrl: options.baseUrl,
144
- },
145
- };
146
- const projectArn = gridInfo.arn;
147
- const { appArn } = getAppCaps(gridInfo);
148
- reporter.onWaitForDevice(workerId, executionId);
149
- realDataService.joinToTestResultsByRunId(executionId, projectId);
150
- return testimServicesApi.createDeviceFarmRun(companyId, projectId, projectArn, appArn, configuration, branchToUse, executionId, env, remoteRunObject);
151
- }).then(run => {
152
- realDataService.listenToTestResultsByRunId(executionId, testResult => {
153
- const prevTestResult = executionResults[testResult.id];
154
- const mergedTestResult = _.merge({}, prevTestResult, testResult, { resultId: testResult.id });
155
- if (!prevTestResult || prevTestResult.status !== testResult.status) {
156
- if ([TESTIM_RUN_STATUS.RUNNING].includes(testResult.status)) {
157
- testStatus.testStart(workerId, executionId, mergedTestResult.id);
158
- }
159
- if ([TESTIM_RUN_STATUS.COMPLETED].includes(testResult.status)) {
160
- testStatus.testEnd(workerId, Object.assign({}, mergedTestResult), executionId);
161
- }
162
- }
163
- executionResults[testResult.id] = mergedTestResult;
164
- });
165
- return utils.runWithRetries(
166
- () => this.getDeviceFarmRunStatus(projectId, run.arn), MAX_EXECUTION_TIMEOUT, STATUS_CHECK_INTERVAL);
167
- })
168
- .then(runInfo => {
169
- if ([DF_RUN_RESULT.SKIPPED].includes(runInfo.result) &&
170
- runInfo.deviceSelectionResult &&
171
- runInfo.deviceSelectionResult.matchedDevicesCount === 0) {
172
- console.log('Device Farm Error: The device in your configuration is not supported');
173
- }
174
- if ([DF_RUN_RESULT.STOPPED].includes(runInfo.result)) {
175
- console.log('Device Farm Error: The test has been stopped. Please try running it again in a few minutes');
176
- }
177
- if ([DF_RUN_RESULT.ERRORED].includes(runInfo.result)) {
178
- console.log(`Device Farm Error: ${runInfo.message}`);
179
- return testStatus.markAllQueuedTests(executionId, runnerTestStatus.ABORTED, 'aborted', false);
180
- }
181
- // Results from socket (currently unused).
182
- this.convertTestResultObjectStatusToReportFormat(executionResults);
183
- // Results from server.
184
- return testimServicesApi.getRealData(projectId, 'testResult', `runId=${executionId}&sort=runOrder`)
185
- .then(res => this.convertTestResultArrayStatusToReportFormat(res.data.docs));
186
- })
187
- .catch(GetBrowserError, err => testStatus.markAllQueuedTests(executionId, runnerTestStatus.FAILED, err.message, false))
188
- .finally(() => {
189
- realDataService.stopListenToTestResultsByRunId();
190
- return gridService.releaseGridSlot(workerId, projectId);
191
- });
192
- }
193
- }
194
-
195
- module.exports = DeviceFarmStrategy;
@@ -1,12 +0,0 @@
1
- 'use strict';
2
-
3
- const LocalStrategy = require('./LocalStrategy');
4
-
5
- class LocalDeviceFarmStrategy extends LocalStrategy {
6
- startWorker(worker, options, onTestStarted, onTestCompleted, executionId, onGridSlot, onTestIgnored) {
7
- const releaseSlotOnTestFinished = false;
8
- worker.start(options, onTestStarted, onTestCompleted, executionId, onGridSlot, onTestIgnored, releaseSlotOnTestFinished);
9
- }
10
- }
11
-
12
- module.exports = LocalDeviceFarmStrategy;
@@ -1,14 +0,0 @@
1
- 'use strict';
2
-
3
- const LocalStrategy = require('./LocalStrategy');
4
- const perf = require('../../commons/performance-logger');
5
-
6
- class LocalTestStrategy extends LocalStrategy {
7
- startWorker(worker, options, onTestStarted, onTestCompleted, executionId, onGridSlot, onTestIgnored) {
8
- const releaseSlotOnTestFinished = true;
9
- perf.log('right before worker.start in startWorker');
10
- worker.start(options, onTestStarted, onTestCompleted, executionId, onGridSlot, onTestIgnored, releaseSlotOnTestFinished);
11
- }
12
- }
13
-
14
- module.exports = LocalTestStrategy;
@@ -1,17 +0,0 @@
1
- const LocalDeviceFarmStrategy = require('./LocalDeviceFarmStrategy');
2
- const LocalTestStrategy = require('./LocalTestStrategy');
3
- const DeviceFarmStrategy = require('./DeviceFarmStrategy');
4
- const {CLI_MODE} = require('../../commons/constants');
5
-
6
- module.exports = (options, customExtensionLocalLocation) => {
7
- const {projectData, gridData, mode} = options;
8
- if (["android", "ios"].includes(projectData.type) && gridData.type === "testimMobile") {
9
- options.mode = CLI_MODE.APPIUM;
10
- return new DeviceFarmStrategy();
11
- }
12
- if (["android", "ios"].includes(projectData.type) && mode === CLI_MODE.DEVICE_FARM_APPIUM) {
13
- return new LocalDeviceFarmStrategy();
14
- }
15
-
16
- return new LocalTestStrategy(customExtensionLocalLocation);
17
- };
@@ -1,70 +0,0 @@
1
- "use strict";
2
-
3
- const {CLI_MODE} = require('../commons/constants');
4
- const BaseWorker = require('./BaseWorker');
5
- const {timeoutMessages} = require('../commons/constants');
6
- const logger = require('../commons/logger').getLogger("worker-selenium");
7
- const Promise = require('bluebird');
8
- const exec = Promise.promisify(require('child_process').exec);
9
- const reporter = require("../reports/reporter");
10
- const MobileTestPlayer = require('../player/mobile/mobileTestPlayer');
11
- const { manifestVersion } = require('../commons/getSessionPlayerRequire');
12
-
13
- class WorkerAppium extends BaseWorker {
14
- initPlayer(testRunHandler) {
15
- const { projectData } = this.options;
16
- return new MobileTestPlayer(this.id, testRunHandler.getRunParams(), projectData.type);
17
- }
18
-
19
- async getBrowserOnce(testRunHandler, customExtensionLocalLocation, player, gridInfo) {
20
- reporter.onGetSession(this.id, this.testName, testRunHandler.getRunMode());
21
- player.clearSessionTabs();
22
- const { driver } = player;
23
-
24
- try {
25
- await driver.init(this.options, gridInfo, testRunHandler.getNativeAppData(), this.testName, this.testResultId);
26
- return player.addTab();
27
- } catch (err) {
28
- logger.error(`failed to get device/app (message=${err.message})`, { err });
29
- throw err;
30
- }
31
- }
32
-
33
- runTestCleanup() {
34
- const { mode } = this.options;
35
-
36
- if(mode === CLI_MODE.DEVICE_FARM_APPIUM) {
37
- return exec("adb shell pm clear $DEVICEFARM_APP_NAME");
38
- }
39
- return Promise.resolve();
40
- }
41
-
42
- runTestOnce(testRunHandler, player) {
43
- const version = manifestVersion || "runner";
44
- let that = this;
45
-
46
- reporter.onWaitToTestComplete(this.id, this.isCodeMode);
47
-
48
- function runSeleniumTest() {
49
- return new Promise(resolve => player.sessionPlayer.playByTestId(that.testId, that.executionId, that.testResultId, that.baseUrl, that.userData, version, resolve, false, that.overrideTestConfigId, that.branch))
50
- .timeout(that.testRunTimeout, timeoutMessages.TEST_COMPLETE_TIMEOUT_MSG)
51
- .catch(Promise.TimeoutError, err => {
52
- player.sessionPlayer.stopPlayingOnTestTimeout && player.sessionPlayer.stopPlayingOnTestTimeout();
53
- throw err;
54
- })
55
- .then(testResult => {
56
- testResult.stepsResults = null;
57
- return Promise.resolve(testResult);
58
- });
59
- }
60
-
61
- return super.runTestOnce(testRunHandler, player)
62
- .then(() => runSeleniumTest())
63
- .catch(err => {
64
- logger.error("failed to run test once", {err: err});
65
- return Promise.reject(err);
66
- });
67
- }
68
- }
69
-
70
- module.exports = WorkerAppium;