@testim/testim-cli 3.285.0 → 3.287.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 (47) hide show
  1. package/agent/routers/cliJsCode/service.js +32 -9
  2. package/agent/routers/codim/service.js +10 -7
  3. package/cli/writeStackTrace.js +14 -13
  4. package/cli.js +12 -15
  5. package/commons/featureFlags.js +1 -0
  6. package/commons/getSessionPlayerRequire.js +23 -8
  7. package/commons/httpRequestCounters.js +2 -2
  8. package/commons/initializeUserWithAuth.js +1 -1
  9. package/commons/testimDesiredCapabilitiesBuilder.js +6 -1
  10. package/npm-shrinkwrap.json +2128 -964
  11. package/package.json +2 -2
  12. package/player/appiumTestPlayer.js +8 -20
  13. package/player/seleniumTestPlayer.js +10 -21
  14. package/player/services/frameLocator.js +4 -2
  15. package/player/services/tabService.js +13 -14
  16. package/player/stepActions/apiStepAction.js +6 -8
  17. package/player/stepActions/baseCliJsStepAction.js +3 -6
  18. package/player/stepActions/baseJsStepAction.js +10 -8
  19. package/player/stepActions/dropFileStepAction.js +5 -3
  20. package/player/stepActions/evaluateExpressionStepAction.js +6 -7
  21. package/player/stepActions/hoverStepAction.js +1 -3
  22. package/player/stepActions/inputFileStepAction.js +7 -6
  23. package/player/stepActions/locateStepAction.js +5 -6
  24. package/player/stepActions/mouseStepAction.js +9 -10
  25. package/player/stepActions/scrollStepAction.js +5 -7
  26. package/player/stepActions/selectOptionStepAction.js +3 -4
  27. package/player/stepActions/sfdcRecordedStepAction.js +1 -1
  28. package/player/stepActions/sfdcStepAction.js +1 -1
  29. package/player/stepActions/stepAction.js +7 -2
  30. package/player/stepActions/textStepAction.js +4 -7
  31. package/player/stepActions/textValidationStepAction.js +3 -10
  32. package/player/stepActions/wheelStepAction.js +1 -2
  33. package/player/utils/eyeSdkService.js +4 -3
  34. package/player/utils/stepActionUtils.js +9 -4
  35. package/player/webdriver.js +3 -3
  36. package/processHandler.js +3 -2
  37. package/processHandler.test.js +3 -4
  38. package/reports/debugReporter.js +1 -1
  39. package/runOptions.d.ts +2 -0
  40. package/runOptions.js +17 -8
  41. package/runners/TestPlanRunner.js +1 -1
  42. package/stepPlayers/hybridStepPlayback.js +23 -21
  43. package/stepPlayers/remoteStepPlayback.js +8 -6
  44. package/stepPlayers/tdkHybridStepPlayback.js +20 -17
  45. package/workers/BaseWorker.js +7 -6
  46. package/workers/WorkerAppium.js +8 -6
  47. package/workers/WorkerSelenium.js +16 -12
@@ -1,23 +1,23 @@
1
1
  'use strict';
2
2
 
3
3
  const _ = require('lodash');
4
- const sessionPlayerInit = require('../commons/getSessionPlayerRequire');
5
4
  const perfLogger = require('../commons/performance-logger');
6
5
  const { guid } = require('../utils');
6
+ const { AbortError } = require('../commons/AbortError');
7
7
  const { getArgumentsFromContext } = require('../codim/hybrid-utils');
8
- const { AbortError } = require("../commons/AbortError");
8
+ const { getSessionPlayer } = require('../commons/getSessionPlayerRequire');
9
9
 
10
10
  module.exports.execute = async function executeTdkFunction(player, hybridFunction, context, loginData, frameManager, step, source, abortSignal) {
11
11
  function onAbort() {
12
12
  player.sessionPlayer.stopPlaying();
13
13
  }
14
14
 
15
- abortSignal.addEventListener("abort", onAbort);
15
+ abortSignal.addEventListener('abort', onAbort);
16
16
 
17
17
  function getLocator(arg) {
18
18
  if (step.parameterValues) { // tdk is all grown up and can run real locators
19
19
  const locateStep = step.parameterValues.find(param => param.type === 'locate' && param.id === arg.locatorId);
20
- return { elementLocator: locateStep.elementLocator , id: locateStep.id, name: 'Hybrid Step Locator' };
20
+ return { elementLocator: locateStep.elementLocator, id: locateStep.id, name: 'Hybrid Step Locator' };
21
21
  }
22
22
  if (!arg.locatedElement.shadowPath) {
23
23
  return arg; // wat
@@ -36,6 +36,7 @@ module.exports.execute = async function executeTdkFunction(player, hybridFunctio
36
36
  const baseUrl = context.config.baseUrl;
37
37
  const userData = _.cloneDeep(context); // the context contains everything needed as userData except login data
38
38
  userData.loginData = loginData;
39
+ const sessionPlayerInit = getSessionPlayer();
39
40
  const version = sessionPlayerInit.manifestVersion || 'runner';
40
41
  const isLocalRun = false;
41
42
  const overrideTestConfigId = null;
@@ -52,13 +53,14 @@ module.exports.execute = async function executeTdkFunction(player, hybridFunctio
52
53
  sourceCode: fn.toString(),
53
54
  sourceName: fn.name,
54
55
  testId,
55
- resultId: guid() // we don't want to reuse the resultId of the parent for the child - we need a new resultId
56
+ resultId: guid(), // we don't want to reuse the resultId of the parent for the child - we need a new resultId
56
57
  };
57
58
  const onlyLocalReporting = typeof hybridFunction.results === 'boolean' && !hybridFunction.results;
58
59
  try {
59
60
  perfLogger.log('tdkHybridStepPlayback before addAllTabs');
60
61
  if (frameManager) { // we have a frameManager we can reuse
61
- player.sessionPlayer.playbackAutUtils.frameManager = player.sessionPlayer.frameManager = frameManager;
62
+ player.sessionPlayer.playbackAutUtils.frameManager = frameManager;
63
+ player.sessionPlayer.frameManager = frameManager;
62
64
  } else {
63
65
  // otherwise, we have to tell the session player about them tabs
64
66
  //TODO(benji) call getEditorUrl?
@@ -73,37 +75,38 @@ module.exports.execute = async function executeTdkFunction(player, hybridFunctio
73
75
  }
74
76
  function onAbort() {
75
77
  reject(new AbortError());
76
- abortSignal.removeEventListener("abort", onAbort);
78
+ abortSignal.removeEventListener('abort', onAbort);
77
79
  }
78
80
 
79
- abortSignal.addEventListener("abort", onAbort);
81
+ abortSignal.addEventListener('abort', onAbort);
80
82
 
81
- player.sessionPlayer.playTestByCode(testId, executionId, resultId, baseUrl, userData, version, resolve, isLocalRun, overrideTestConfigId, branch, [codeTest], testName, ignoreNavigation).catch(reject);
82
-
83
+ player.sessionPlayer.playTestByCode(
84
+ testId, executionId, resultId, baseUrl, userData, version, resolve, isLocalRun, overrideTestConfigId, branch, [codeTest], testName, ignoreNavigation,
85
+ ).catch(reject);
83
86
  });
84
87
  perfLogger.log('tdkHybridStepPlayback after playTestByCode');
85
88
  // testResult.status?
86
89
  return { success: testResult.success, shouldRetry: false, resultInfo: { testId, executionId, resultId: codeTest.resultId } };
87
90
  } catch (e) {
88
- return { success: false, error: e, shouldRetry: false }
91
+ return { success: false, error: e, shouldRetry: false };
89
92
  } finally {
90
- abortSignal.removeEventListener("abort", onAbort);
93
+ abortSignal.removeEventListener('abort', onAbort);
91
94
  }
92
95
  };
93
96
 
94
97
  function resolveOnTestResultAndNotAssetsUploaded(player, resolve) {
95
- const { commonConstants } = require('../commons/getSessionPlayerRequire');
96
- player.sessionPlayer.playbackManager.on(commonConstants.playback.START, ({testResult}) => {
98
+ const { commonConstants } = getSessionPlayer();
99
+ player.sessionPlayer.playbackManager.on(commonConstants.playback.START, ({ testResult }) => {
97
100
  let runnerStatus = testResult.runnerStatus;
98
101
  Object.defineProperty(testResult, 'runnerStatus', {
99
- get() { return runnerStatus },
100
- set(value) {
102
+ get() { return runnerStatus; },
103
+ set(value) {
101
104
  runnerStatus = value;
102
105
  if (value === 'FINISHED') {
103
106
  // resolve as soon as the runner is finished, before assets are uploaded
104
107
  resolve(testResult);
105
108
  }
106
- }
109
+ },
107
110
  });
108
111
  });
109
112
  }
@@ -207,8 +207,8 @@ class BaseWorker {
207
207
  return player || getBrowserRes;
208
208
  } catch (error) {
209
209
  const grid = { provider: gridInfo.provider, host: gridInfo.host, failedGetBrowserAttempts, id: this.options.gridData.gridId, type: gridInfo.type };
210
- logger.error('error getting browser from grid',
211
- { error, testId: this.testId, testResultId: this.testResultId, executionId: this.executionId, grid });
210
+ const instanceType = this.options.mode === CLI_MODE.APPIUM ? 'device' : 'browser';
211
+ logger.error(`error getting ${instanceType} from grid`, { error, testId: this.testId, testResultId: this.testResultId, executionId: this.executionId, grid });
212
212
  reporter.onGetBrowserFailure(this.id, projectId, ++failedGetBrowserAttempts);
213
213
  player.onDone();
214
214
 
@@ -333,6 +333,7 @@ class BaseWorker {
333
333
  * @param {boolean} wasNetworkHealthy
334
334
  */
335
335
  const buildError = (err, wasNetworkHealthy) => {
336
+ const instanceType = this.options.mode === CLI_MODE.APPIUM ? 'device' : 'browser';
336
337
  if (!wasNetworkHealthy && featureFlags.flags.errorMessageOnBadNetwork.isEnabled()) {
337
338
  return {
338
339
  errorType: NETWORK_ERROR,
@@ -342,7 +343,7 @@ class BaseWorker {
342
343
 
343
344
  const msg = err instanceof Error ? err.message : err;
344
345
  if (msg.includes(GET_BROWSER_TIMEOUT_MSG)) {
345
- return { errorType: SETUP_TIMEOUT, reason: "Test couldn't get browser" };
346
+ return { errorType: SETUP_TIMEOUT, reason: `Test couldn't get ${instanceType}` };
346
347
  }
347
348
  if (msg.includes(TEST_START_TIMEOUT_MSG)) {
348
349
  return { errorType: SETUP_TIMEOUT, reason: "Test couldn't be started" };
@@ -361,7 +362,7 @@ class BaseWorker {
361
362
 
362
363
  if (err instanceof GetBrowserError && err.type) {
363
364
  if (err.type === GRID_ERROR) {
364
- return { errorType: GRID_ERROR, reason: `Test couldn't get browser from grid - ${err.message}` };
365
+ return { errorType: GRID_ERROR, reason: `Test couldn't get ${instanceType} from grid - ${err.message}` };
365
366
  }
366
367
  if (err.type === SELENIUM_ERROR) {
367
368
  return { errorType: SELENIUM_ERROR, reason: `Failed to create new session - ${err.message}` };
@@ -372,7 +373,7 @@ class BaseWorker {
372
373
  return { errorType: SELENIUM_ERROR, reason: 'Session terminated, it is possible that the cli could not connect to the grid to send keep-alive requests for a prolonged period' };
373
374
  }
374
375
  if (err.failure && err.failure instanceof SeleniumError) {
375
- return { errorType: SELENIUM_ERROR, reason: `Test couldn't get browser from grid - ${err.failure.message}` };
376
+ return { errorType: SELENIUM_ERROR, reason: `Test couldn't get ${instanceType} from grid - ${err.failure.message}` };
376
377
  }
377
378
  if (/SeleniumError: connect ECONNREFUSED/.test(err.message) || /Couldn't connect to selenium server/.test(err.message)) {
378
379
  return { errorType: SELENIUM_ERROR, reason: 'Failed to connect to the grid, please check if the grid is accessible from your network' };
@@ -384,7 +385,7 @@ class BaseWorker {
384
385
  return { errorType: SELENIUM_ERROR, reason: 'Session terminated, it is likely that the grid is not responding, please try to rerun the test' };
385
386
  }
386
387
  if (/forwarding the new session cannot find : Capabilities/.test(err.message)) {
387
- return { errorType: SELENIUM_ERROR, reason: 'Session could not be created, please check that the browser you requested is supported in your plan' };
388
+ return { errorType: SELENIUM_ERROR, reason: `Session could not be created, please check that the ${instanceType} you requested is supported in your plan` };
388
389
  }
389
390
  return { errorType: UNKNOWN_ERROR, reason: msg };
390
391
  };
@@ -2,14 +2,15 @@
2
2
 
3
3
  const jsdom = require('jsdom');
4
4
  const BaseWorker = require('./BaseWorker');
5
- const logger = require('../commons/logger').getLogger('worker-appium');
5
+ const config = require('../commons/config');
6
6
  const reporter = require('../reports/reporter');
7
7
  const AppiumTestPlayer = require('../player/appiumTestPlayer');
8
- const sessionPlayerInit = require('../commons/getSessionPlayerRequire');
9
- const AppiumApi = require('../commons/getSessionPlayerRequire').AppiumApi;
10
- const desiredCapabilitiesBuilder = require('../commons/testimDesiredCapabilitiesBuilder');
11
8
  const testimServicesApi = require('../commons/testimServicesApi');
12
- const config = require('../commons/config');
9
+ const desiredCapabilitiesBuilder = require('../commons/testimDesiredCapabilitiesBuilder');
10
+ const { getSessionPlayer } = require('../commons/getSessionPlayerRequire');
11
+ const { getLogger } = require('../commons/logger');
12
+
13
+ const logger = getLogger('worker-appium');
13
14
 
14
15
  class WorkerAppium extends BaseWorker {
15
16
  /**
@@ -113,6 +114,7 @@ class WorkerAppium extends BaseWorker {
113
114
  * @param {import('../player/appiumTestPlayer')} appiumTestPlayer
114
115
  */
115
116
  async runTestOnce(testRunHandler, appiumTestPlayer) {
117
+ const sessionPlayerInit = getSessionPlayer();
116
118
  const { driver, sessionPlayer } = appiumTestPlayer;
117
119
  const version = sessionPlayerInit.manifestVersion || 'runner';
118
120
 
@@ -123,7 +125,7 @@ class WorkerAppium extends BaseWorker {
123
125
 
124
126
  const serverAddress = this.getDirectAddressConnection(driver.activeSession.capabilities) || this.getServerAddressFromGrid(testRunHandler);
125
127
  const DOMParser = new jsdom.JSDOM('').window.DOMParser;
126
- sessionPlayer.playbackManager.appiumApi = new AppiumApi(serverAddress, driver.activeSession.sessionId, DOMParser);
128
+ sessionPlayer.playbackManager.appiumApi = new sessionPlayerInit.AppiumApi(serverAddress, driver.activeSession.sessionId, DOMParser);
127
129
  if (sessionPlayerInit.localAssetService) {
128
130
  sessionPlayerInit.localAssetService.initialize({ serverUrl: this.options.localRCASaver });
129
131
  }
@@ -1,16 +1,18 @@
1
1
  'use strict';
2
2
 
3
+ const utils = require('../utils');
3
4
  const BaseWorker = require('./BaseWorker');
4
- const logger = require('../commons/logger').getLogger('worker-selenium');
5
5
  const reporter = require('../reports/reporter');
6
- const SeleniumTestPlayer = require('../player/seleniumTestPlayer');
7
- const WindowUtils = require('../player/utils/windowUtils');
8
- const sessionPlayerInit = require('../commons/getSessionPlayerRequire');
9
6
  const perf = require('../commons/performance-logger');
10
- const utils = require('../utils');
11
- const { timeoutMessages } = require('../commons/constants');
7
+ const WindowUtils = require('../player/utils/windowUtils');
8
+ const SeleniumTestPlayer = require('../player/seleniumTestPlayer');
9
+ const { getLogger } = require('../commons/logger');
12
10
  const { PageNotAvailableError } = require('../errors');
13
11
  const { preloadTests } = require('../commons/preloadTests');
12
+ const { timeoutMessages } = require('../commons/constants');
13
+ const { getSessionPlayer } = require('../commons/getSessionPlayerRequire');
14
+
15
+ const logger = getLogger('worker-selenium');
14
16
 
15
17
  // this navigation timeout is handled from outside the worker, so don't pass a small timeout to navigate
16
18
  const NO_NAVIGATION_TIME_LIMIT = 1e9;
@@ -62,7 +64,7 @@ class WorkerSelenium extends BaseWorker {
62
64
  this.testResultId,
63
65
  testRunHandler.seleniumPerfStats,
64
66
  fastInit,
65
- this.lambdatestService
67
+ this.lambdatestService,
66
68
  );
67
69
  perf.log('in WorkerSelenium after driver.init');
68
70
  await seleniumTestPlayer.addTab(undefined, { skipLoadInfo: fastInit });
@@ -93,7 +95,9 @@ class WorkerSelenium extends BaseWorker {
93
95
  * @param {import('../player/seleniumTestPlayer')} seleniumTestPlayer
94
96
  */
95
97
  async runTestOnce(testRunHandler, seleniumTestPlayer) {
98
+ const sessionPlayerInit = getSessionPlayer();
96
99
  const { driver, sessionPlayer } = seleniumTestPlayer;
100
+
97
101
  const version = sessionPlayerInit.manifestVersion || 'runner';
98
102
 
99
103
  reporter.onWaitToTestComplete(this.id, this.isCodeMode);
@@ -126,7 +130,7 @@ class WorkerSelenium extends BaseWorker {
126
130
  sessionPlayer.callOrderScheduler.schedule(
127
131
  () => testRunHandler.waitForExecutionStartedFinished(),
128
132
  // this key is shared by clickim and this ensures that we do wait for the execution to be created before we do this.
129
- { key: `test-result:${this.userData.projectId}:${this.testResultId}` }
133
+ { key: `test-result:${this.userData.projectId}:${this.testResultId}` },
130
134
  );
131
135
  }
132
136
  perf.log('right before playTestByCode');
@@ -144,7 +148,7 @@ class WorkerSelenium extends BaseWorker {
144
148
  this.overrideTestConfigId,
145
149
  this.branch,
146
150
  testRunHandler.code,
147
- testRunHandler.testName
151
+ testRunHandler.testName,
148
152
  ).catch(reject);
149
153
  });
150
154
  return utils
@@ -154,7 +158,7 @@ class WorkerSelenium extends BaseWorker {
154
158
  return testResult;
155
159
  }),
156
160
  this.testRunTimeout,
157
- timeoutMessages.TEST_COMPLETE_TIMEOUT_MSG
161
+ timeoutMessages.TEST_COMPLETE_TIMEOUT_MSG,
158
162
  )
159
163
  .catch(err => {
160
164
  if (err instanceof utils.TimeoutError) {
@@ -187,7 +191,7 @@ class WorkerSelenium extends BaseWorker {
187
191
  testRunHandler.remoteRunId,
188
192
  undefined,
189
193
  undefined,
190
- preloadedTest
194
+ preloadedTest,
191
195
  ).catch(reject);
192
196
  }),
193
197
  this.testRunTimeout,
@@ -238,7 +242,7 @@ class WorkerSelenium extends BaseWorker {
238
242
  }
239
243
  }
240
244
  function setupCliPerformanceMonitoring(sessionPlayer) {
241
- const { playback } = sessionPlayerInit.commonConstants;
245
+ const { playback } = getSessionPlayer().commonConstants;
242
246
  function monitorEvent(event) {
243
247
  sessionPlayer.playbackManager.on(event, () => {
244
248
  perf.log(`Got event ${event}`);