@testim/testim-cli 3.251.0 → 3.253.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 (34) hide show
  1. package/agent/routers/index.js +2 -1
  2. package/agent/routers/playground/router.js +1 -1
  3. package/commons/chrome-launcher.js +6 -6
  4. package/commons/constants.js +2 -0
  5. package/commons/getSessionPlayerRequire.js +2 -20
  6. package/commons/initializeUserWithAuth.js +2 -2
  7. package/commons/mockNetworkRuleFileSchema.json +40 -38
  8. package/commons/testimDesiredCapabilitiesBuilder.js +43 -0
  9. package/commons/testimServicesApi.js +11 -2
  10. package/credentialsManager.js +17 -20
  11. package/npm-shrinkwrap.json +2104 -444
  12. package/package.json +4 -2
  13. package/player/WebdriverioWebDriverApi.js +7 -2
  14. package/player/appiumTestPlayer.js +102 -0
  15. package/player/seleniumTestPlayer.js +3 -2
  16. package/player/services/frameLocator.js +2 -1
  17. package/player/services/mobileFrameLocatorMock.js +32 -0
  18. package/player/services/playbackTimeoutCalculator.js +1 -0
  19. package/player/services/portSelector.js +10 -8
  20. package/player/services/tabService.js +29 -0
  21. package/player/stepActions/sfdcRecordedStepAction.js +2 -2
  22. package/player/stepActions/sfdcStepAction.js +2 -2
  23. package/player/stepActions/stepAction.js +15 -1
  24. package/player/utils/stepActionUtils.js +4 -2
  25. package/player/utils/windowUtils.js +138 -125
  26. package/player/webdriver.js +39 -25
  27. package/reports/debugReporter.js +41 -39
  28. package/reports/jsonReporter.js +53 -50
  29. package/reports/reporter.js +135 -136
  30. package/runOptions.js +2 -1
  31. package/runners/ParallelWorkerManager.js +2 -0
  32. package/testRunStatus.js +457 -459
  33. package/workers/BaseWorker.js +13 -6
  34. package/workers/WorkerAppium.js +123 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testim/testim-cli",
3
- "version": "3.251.0",
3
+ "version": "3.253.0",
4
4
  "description": "Command line interface for running Testing on your CI",
5
5
  "author": "Oren Rubin",
6
6
  "contributors": [{
@@ -68,6 +68,7 @@
68
68
  "form-data": "3.0.0",
69
69
  "fs-extra": "10.0.1",
70
70
  "glob": "7.2.0",
71
+ "https-proxy-agent": "5.0.0",
71
72
  "istanbul-lib-report": "3.0.0",
72
73
  "istanbul-reports": "3.0.2",
73
74
  "jimp": "0.16.1",
@@ -98,6 +99,7 @@
98
99
  "threads": "0.12.0",
99
100
  "ua-parser-js": "0.7.28",
100
101
  "validate-npm-package-name": "3.0.0",
102
+ "webdriverio": "7.24.0",
101
103
  "winston": "3.6.0",
102
104
  "winston-transport": "4.5.0",
103
105
  "ws": "8.5.0",
@@ -119,6 +121,6 @@
119
121
  "pack-serve": "yarn pack-onprem && http-server deploy/"
120
122
  },
121
123
  "engines": {
122
- "node": ">= 12.0.0"
124
+ "node": ">= 14.0.0"
123
125
  }
124
126
  }
@@ -5,7 +5,7 @@ const Queue = require('promise-queue');
5
5
  const Promise = require('bluebird');
6
6
  const config = require('../commons/config');
7
7
  const {
8
- UNICODE_CHARACTERS, W3C_ELEMENT_ID, EDGE_LAST_VERSION, EDGE_CHROMIUM_MIN_VERSION,
8
+ UNICODE_CHARACTERS, W3C_ELEMENT_ID,
9
9
  } = require('./constants');
10
10
  const isElementDisplayed = require('./scripts/isElementDisplayed');
11
11
  const logger = require('../commons/logger').getLogger('WebDriverApi');
@@ -59,6 +59,7 @@ class WebdriverioWebDriverApi {
59
59
  this.queue = new Queue(maxConcurrent, maxQueue);
60
60
  }
61
61
 
62
+ /** @returns {Promise<any>} */
62
63
  addToQueue(func) {
63
64
  const perfId = this.seleniumPerfStats.markStart();
64
65
  return this.queue.add(func)
@@ -247,6 +248,10 @@ class WebdriverioWebDriverApi {
247
248
  .finally(() => this.seleniumPerfStats.markEnd(perfId, SELENIUM_PERF_MARKS.GET_SCREENSHOT));
248
249
  }
249
250
 
251
+ /**
252
+ * @param {string} selector
253
+ * @returns {Promise<{ value: HTMLElement }>}
254
+ */
250
255
  getElementBySelector(selector) {
251
256
  return this.addToQueue(() => this.client.element(selector));
252
257
  }
@@ -506,7 +511,7 @@ class WebdriverioWebDriverApi {
506
511
  return this.addToQueue(() => this.client.getTitle());
507
512
  }
508
513
 
509
-
514
+ // eslint-disable-next-line default-param-last
510
515
  windowHandleSize(windowHandle = 'current', size) {
511
516
  return this.addToQueue(() => {
512
517
  let data = {};
@@ -0,0 +1,102 @@
1
+ 'use strict';
2
+
3
+ const webdriverio = require('webdriverio');
4
+ const TabService = require('./services/tabService');
5
+ const PortSelector = require('./services/portSelector');
6
+ const windowCreationListener = require('./services/windowCreationListener');
7
+ const frameLocatorFactory = require('./services/mobileFrameLocatorMock');
8
+ const { isDebuggerConnected } = require('../commons/detectDebugger');
9
+ const logger = require('../commons/logger').getLogger('appium-test-player');
10
+
11
+ const sessionPlayer = require('../commons/getSessionPlayerRequire');
12
+
13
+ const Player = sessionPlayer.sessionPlayer;
14
+ // delete after https://github.com/testimio/clickim/pull/3430 release to the store
15
+ const assetService = sessionPlayer.assetService;
16
+ const commonConstants = sessionPlayer.commonConstants;
17
+ const StepActionFactory = sessionPlayer.stepActionFactory;
18
+ const mobileLocateElementPlayer = sessionPlayer.MobileLocateElementPlayer;
19
+ const PlaybackTimeoutCalculator = require('./services/playbackTimeoutCalculator');
20
+ const testResultService = require('../commons/socket/testResultService');
21
+
22
+ // delete after https://github.com/testimio/clickim/pull/3430 release to the store
23
+ const CryptoJS = require('crypto-js');
24
+ const StepActionUtils = require('./utils/stepActionUtils');
25
+
26
+ class AppiumTestPlayer {
27
+ //eslint-disable-next-line default-param-last
28
+ constructor(id, userParamsData, shouldMonitorPerformance, automationMode = 'code', driver = webdriverio, testRetryCount, previousTestResultId) {
29
+ this.driver = driver;
30
+ this.id = id;
31
+
32
+ const stepActionUtils = new StepActionUtils(this.driver);
33
+ this.stepActionFactory = new StepActionFactory(stepActionUtils);
34
+ require('./stepActions/stepActionRegistrar')(this.driver, this.stepActionFactory, 'selenium');
35
+
36
+ if (assetService.setMd5) {
37
+ // delete after https://github.com/testimio/clickim/pull/3430 release to the store
38
+ assetService.setMd5(CryptoJS);
39
+ }
40
+ this.tabService = new TabService(this.driver);
41
+ this.windowCreationListener = windowCreationListener;
42
+ this.playbackTimeoutCalculator = new PlaybackTimeoutCalculator(isDebuggerConnected());
43
+
44
+ this.tabService.createSesion(id);
45
+
46
+ const FrameLocator = frameLocatorFactory(this.driver);
47
+
48
+ this.sessionPlayer = new Player(
49
+ id,
50
+ this.tabService,
51
+ null,
52
+ null,
53
+ FrameLocator,
54
+ PortSelector,
55
+ mobileLocateElementPlayer,
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
+ );
63
+
64
+ if (this.sessionPlayer.setShouldMonitorPerformance) {
65
+ this.sessionPlayer.setShouldMonitorPerformance(shouldMonitorPerformance);
66
+ }
67
+ this.sessionPlayer.playbackManager.isRemoteSession = true;
68
+ this.sessionPlayer.playbackManager.isLocalRun = false;
69
+ this.sessionPlayer.playbackManager.testRetryCount = testRetryCount;
70
+ this.sessionPlayer.playbackManager.previousTestResultId = previousTestResultId;
71
+
72
+ this.sessionPlayer.playbackManager.userParamsData = userParamsData || {};
73
+ this.onStepCompleted = this.onStepCompleted.bind(this);
74
+
75
+ this.sessionPlayer.playbackManager.on(commonConstants.playback.RESULT, this.onStepCompleted);
76
+ }
77
+
78
+ onStepCompleted(result, testId, resultId, step) {
79
+ //do nothing for now ...
80
+ }
81
+
82
+
83
+ async onDone() {
84
+ try {
85
+ await this.driver.activeSession.deleteSession();
86
+ } catch (error) {
87
+ logger.error('error while deleting appium session', { error });
88
+ } finally {
89
+ this.sessionPlayer.playbackManager.off(commonConstants.playback.RESULT);
90
+ this.sessionPlayer = null;
91
+ this.tabService = null;
92
+ this.stepActionFactory = null;
93
+ this.driver = null;
94
+ }
95
+ }
96
+
97
+ getSessionId() {
98
+ return this.driver.activeSession.sessionId;
99
+ }
100
+ }
101
+
102
+ module.exports = AppiumTestPlayer;
@@ -10,7 +10,7 @@ const { isDebuggerConnected } = require('../commons/detectDebugger');
10
10
 
11
11
  const sessionPlayer = require('../commons/getSessionPlayerRequire');
12
12
 
13
- const player = sessionPlayer.sessionPlayer;
13
+ const Player = sessionPlayer.sessionPlayer;
14
14
  // delete after https://github.com/testimio/clickim/pull/3430 release to the store
15
15
  const assetService = sessionPlayer.assetService;
16
16
  const commonConstants = sessionPlayer.commonConstants;
@@ -24,6 +24,7 @@ const CryptoJS = require('crypto-js');
24
24
  const StepActionUtils = require('./utils/stepActionUtils');
25
25
 
26
26
  class SeleniumTestPlayer {
27
+ //eslint-disable-next-line default-param-last
27
28
  constructor(id, userParamsData, shouldMonitorPerformance, automationMode = 'code', driver = new WebDriver(), testRetryCount, previousTestResultId) {
28
29
  this.driver = driver;
29
30
  this.id = id;
@@ -47,7 +48,7 @@ class SeleniumTestPlayer {
47
48
 
48
49
  const FrameLocator = frameLocatorFactory(this.driver);
49
50
 
50
- this.sessionPlayer = new player(
51
+ this.sessionPlayer = new Player(
51
52
  id,
52
53
  this.tabService,
53
54
  CookieUtils(this.driver),
@@ -19,6 +19,7 @@ const _getGuidFromSeleniumElement = (seleniumElement) => {
19
19
  /** @param {import('../webdriver')} driver*/
20
20
  module.exports = function frameLocatorFactory(driver) {
21
21
  class FrameLocator {
22
+ /** @type {(...args: ConstructorParameters<typeof import('clickim/src/background/frameLocator').FrameLocator>) => this} */
22
23
  constructor(frameManager, locateElementPlayer) {
23
24
  this.frameManager = frameManager;
24
25
  this.locateElementPlayer = locateElementPlayer;
@@ -34,7 +35,7 @@ module.exports = function frameLocatorFactory(driver) {
34
35
  }
35
36
 
36
37
  cacheFrameLocateResults(frameHandler) {
37
- if (frameHandler && frameHandler.seleniumFrameElement && frameHandler.frameLocateResultUrl) {
38
+ if (frameHandler?.seleniumFrameElement && frameHandler.frameLocateResultUrl) {
38
39
  const guid = _getGuidFromSeleniumElement(frameHandler.seleniumFrameElement);
39
40
  if (guid) {
40
41
  this.cacheResults(guid, frameHandler.frameLocateResultUrl);
@@ -0,0 +1,32 @@
1
+ 'use strict';
2
+
3
+ const logger = require('../../commons/logger').getLogger('mobile-frame-locator-mock');
4
+
5
+ /** @param {import('../webdriver')} driver*/
6
+ module.exports = function frameLocatorFactory(driver) {
7
+ class FrameLocator {
8
+ /** @type {(...args: ConstructorParameters<typeof import('clickim/src/background/frameLocator').FrameLocator>) => this} */
9
+ constructor(frameManager, locateElementPlayer) {
10
+ this.frameManager = frameManager;
11
+ this.locateElementPlayer = locateElementPlayer;
12
+ }
13
+
14
+ foundFrameCallback(result, frameTree, testimFrameId) {
15
+ logger.info('foundFrameCallback-mock invoked');
16
+ return {};
17
+ }
18
+
19
+
20
+ locate(frameLocator, frameDepth, currentFrame, context, frameTree, stepData) {
21
+ logger.info('locate-mock invoked');
22
+ return {};
23
+ }
24
+
25
+ findFrame(stepData, frameLocators, context, frameTree) {
26
+ logger.info('findFrame-mock invoked');
27
+ return {};
28
+ }
29
+ }
30
+
31
+ return FrameLocator;
32
+ };
@@ -18,6 +18,7 @@ const FULL_TIMEOUT_STEP_TYPES = [
18
18
  'sfdc-step-launchapp',
19
19
  'sfdc-step-closeconsoletabs',
20
20
  'sfdc-step-sobjectedit',
21
+ 'sfdc-step-relatedlistaction',
21
22
  ];
22
23
 
23
24
  class PlaybackTimeoutCalculator {
@@ -1,16 +1,18 @@
1
- "use strict";
1
+ 'use strict';
2
+
2
3
  const Promise = require('bluebird');
3
4
 
4
5
  // Legacy code not supported in selenium mode
5
6
  class PortSelector {
6
- constructor(){}
7
- select(){
8
- console.log("\n\t\t\tinternal error - cant use port selector in selenium!!!!\n");
9
- return Promise.reject({
10
- reason: "cant use port selector in selenium!"
11
- });
7
+ // eslint-disable-next-line no-useless-constructor, no-empty-function
8
+ constructor() { }
9
+ select() {
10
+ // eslint-disable-next-line no-console
11
+ console.log('\n\t\t\tinternal error - cant use port selector in selenium!!!!\n');
12
+ // eslint-disable-next-line prefer-promise-reject-errors
13
+ return Promise.reject({ reason: 'cant use port selector in selenium!' });
12
14
  }
13
- prepare(){}
15
+ prepare() {}
14
16
  handleLegacyDataCaching() {}
15
17
  }
16
18
 
@@ -15,12 +15,41 @@ const constants = sessionPlayer.commonConstants.stepResult;
15
15
  const tabMatcher = sessionPlayer.tabMatcher;
16
16
  const logger = require('../../commons/logger').getLogger('tab-service');
17
17
 
18
+ /**
19
+ * @typedef {{
20
+ * attachDebugger(): Promise<any>,
21
+ * detachDebugger(): Promise<any>,
22
+ * onDebuggerDetached(): {},
23
+ * tabId: string,
24
+ * domUtils: { getDOM(): Promise<any> },
25
+ * windowUtils: WindowUtils,
26
+ * imageCaptureUtils: ImageCaptureUtils
27
+ * }} TabUtil
28
+ * */
29
+ /**
30
+ * @typedef {{
31
+ * infoId: any;
32
+ * url: any;
33
+ * title: any;
34
+ * favIconUrl: any;
35
+ * order: any;
36
+ * from: any;
37
+ * isMain: any;
38
+ * openerStepId: any;
39
+ * }} TabInfo
40
+ */
41
+
18
42
  class TabService {
43
+ /** @param {import('../webdriver')} driver */
19
44
  constructor(driver) {
20
45
  this.driver = driver;
46
+ /** @type {Record<string, TabUtil>} */
21
47
  this._utils = {};
48
+ /** @type {Record<string, { tabCount: number; tabInfos: Record<string, TabInfo> }>} */
22
49
  this.sessionTabs = {};
50
+ /** @type {Record<string, string>} */
23
51
  this.pendingTabs = {};
52
+ /** @type {Record<string, Set<any>>} */
24
53
  this.addedTabs = {};
25
54
  }
26
55
 
@@ -5,8 +5,8 @@ class SfdcRecordedStepAction extends StepAction {
5
5
  async performAction() {
6
6
  const page = sfdc.sfdcNewSePage(this.driver);
7
7
  try {
8
- await sfdc.sfdcExecuteRecordedStep(page, this.step.recordedData);
9
- return { success: true };
8
+ const warnings = await sfdc.sfdcExecuteRecordedStep(page, this.step.recordedData, this.context);
9
+ return { success: true, reason: warnings };
10
10
  } catch (err) {
11
11
  return {
12
12
  success: false,
@@ -9,8 +9,8 @@ class SfdcStepAction extends StepAction {
9
9
  if (actions === undefined) {
10
10
  throw new Error('No test actions were compiled');
11
11
  }
12
- await sfdc.sfdcExecute(page, actions);
13
- return { success: true };
12
+ const warnings = await sfdc.sfdcExecute(page, actions, this.context);
13
+ return { success: true, reason: warnings };
14
14
  } catch (err) {
15
15
  return {
16
16
  success: false,
@@ -3,8 +3,21 @@
3
3
  const { commonConstants } = require('../../commons/getSessionPlayerRequire');
4
4
  const Promise = require('bluebird');
5
5
 
6
+ /** @typedef {typeof import('clickim/src/background/stepActions/stepAction').StepAction} ClickimStepActionCtor */
7
+ /** @typedef {ConstructorParameters<ClickimStepActionCtor>} ClickimStepActionCtorParams */
8
+ /** @typedef {InstanceType<ClickimStepActionCtor>} ClickimStepAction */
9
+
6
10
  class StepAction {
7
- constructor(step, context, frameHandler, exportsGlobal = {}, stepActionUtils, locateElementPlayer, exportsTest = {}) {
11
+ /** @type {(...args: ClickimStepActionCtorParams) => this} */
12
+ constructor(
13
+ step,
14
+ context,
15
+ frameHandler,
16
+ exportsGlobal = {},
17
+ stepActionUtils = undefined,
18
+ locateElementPlayer = undefined,
19
+ exportsTest = {},
20
+ ) {
8
21
  this.step = step;
9
22
  this.context = context;
10
23
  this.frameHandler = frameHandler;
@@ -28,6 +41,7 @@ class StepAction {
28
41
  return this.context.data[targetId];
29
42
  }
30
43
 
44
+ /** @type {ClickimStepAction['execute']} */
31
45
  execute(stepActionFactory, step) {
32
46
  return Promise.resolve(this.performAction(stepActionFactory, step))
33
47
  .then(res => Promise.resolve(Object.assign({}, { success: true }, res)))
@@ -4,6 +4,7 @@ const { locatorBuilderUtils, utils, codeSnippets } = sessionPlayer;
4
4
  const CookieUtils = require('./cookieUtils');
5
5
 
6
6
  class StepActionUtils {
7
+ /** @param {import('../webdriver')} driver */
7
8
  constructor(driver, cookieUtils) {
8
9
  this.driver = driver;
9
10
  this._abortedSteps = [];
@@ -63,8 +64,9 @@ class StepActionUtils {
63
64
  return this.driver.getElementTextJS(locatedElement);
64
65
  }
65
66
 
66
- markDynamicParent(target, id) {
67
- return this.driver.markDynamicParent(target, id);
67
+ /** @type {import('clickim/src/background/stepActions/stepActionUtils').StepActionUtils['markDynamicParent']} */
68
+ async markDynamicParent(target, id, frameHandler) {
69
+ return this.driver.markDynamicParent(target, id, frameHandler);
68
70
  }
69
71
 
70
72
  getCookie(name) {