@testim/testim-cli 3.259.0 → 3.260.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.
@@ -41,6 +41,7 @@ const DEFAULT_CHROME_OPTIONS_ARGS = [
41
41
  '--mute-audio',
42
42
  // Skip first run wizards
43
43
  '--no-first-run',
44
+ '--disable-back-forward-cache',
44
45
  ];
45
46
 
46
47
  const getHash = (...str) => crypto.createHash('sha256').update(str.join('')).digest('hex');
@@ -603,7 +604,10 @@ function buildSeleniumOptions(browserOptions, testName, testRunConfig, gridInfo,
603
604
  }
604
605
 
605
606
  //testRunConfig not in used for now
606
- function buildAppiumOptions({ projectType, gridInfo, testRunConfig, nativeApp }) {
607
+ function buildAppiumOptions({ projectType, gridInfo, testRunConfig, nativeApp, options }) {
608
+ const { deviceModel, osVersion, deviceUdid } = options;
609
+ const headspinSelector = {};
610
+
607
611
  if (!nativeApp) {
608
612
  throw Error('missing mobile app!');
609
613
  }
@@ -637,6 +641,21 @@ function buildAppiumOptions({ projectType, gridInfo, testRunConfig, nativeApp })
637
641
  default:
638
642
  throw Error(`unsupported mobile project ${projectType}`);
639
643
  }
644
+ if (deviceModel) {
645
+ headspinSelector.model = deviceModel;
646
+ }
647
+ if (osVersion) {
648
+ headspinSelector.os_version = osVersion;
649
+ }
650
+ if (deviceUdid) {
651
+ headspinSelector.device_id = deviceUdid;
652
+ delete headspinSelector.model;
653
+ delete headspinSelector.os_version;
654
+ }
655
+
656
+ if (!_.isEmpty(headspinSelector)) {
657
+ appCaps['headspin:selector'] = headspinSelector;
658
+ }
640
659
  return {
641
660
  ...connection,
642
661
  desiredCapabilities: appCaps,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@testim/testim-cli",
3
- "version": "3.259.0",
3
+ "version": "3.260.0",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@testim/testim-cli",
9
- "version": "3.259.0",
9
+ "version": "3.260.0",
10
10
  "license": "Proprietary",
11
11
  "dependencies": {
12
12
  "@applitools/eyes-sdk-core": "13.6.23",
@@ -12773,9 +12773,9 @@
12773
12773
  }
12774
12774
  },
12775
12775
  "node_modules/query-selector-shadow-dom": {
12776
- "version": "1.0.0",
12777
- "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.0.tgz",
12778
- "integrity": "sha512-bK0/0cCI+R8ZmOF1QjT7HupDUYCxbf/9TJgAmSXQxZpftXmTAeil9DRoCnTDkWbvOyZzhcMBwKpptWcdkGFIMg=="
12776
+ "version": "1.0.1",
12777
+ "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz",
12778
+ "integrity": "sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw=="
12779
12779
  },
12780
12780
  "node_modules/querystring": {
12781
12781
  "version": "0.2.0",
@@ -13026,9 +13026,9 @@
13026
13026
  }
13027
13027
  },
13028
13028
  "node_modules/regenerator-runtime": {
13029
- "version": "0.13.10",
13030
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz",
13031
- "integrity": "sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw=="
13029
+ "version": "0.13.11",
13030
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
13031
+ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
13032
13032
  },
13033
13033
  "node_modules/regex-not": {
13034
13034
  "version": "1.0.2",
@@ -26027,9 +26027,9 @@
26027
26027
  "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ=="
26028
26028
  },
26029
26029
  "query-selector-shadow-dom": {
26030
- "version": "1.0.0",
26031
- "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.0.tgz",
26032
- "integrity": "sha512-bK0/0cCI+R8ZmOF1QjT7HupDUYCxbf/9TJgAmSXQxZpftXmTAeil9DRoCnTDkWbvOyZzhcMBwKpptWcdkGFIMg=="
26030
+ "version": "1.0.1",
26031
+ "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz",
26032
+ "integrity": "sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw=="
26033
26033
  },
26034
26034
  "querystring": {
26035
26035
  "version": "0.2.0",
@@ -26235,9 +26235,9 @@
26235
26235
  }
26236
26236
  },
26237
26237
  "regenerator-runtime": {
26238
- "version": "0.13.10",
26239
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz",
26240
- "integrity": "sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw=="
26238
+ "version": "0.13.11",
26239
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
26240
+ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
26241
26241
  },
26242
26242
  "regex-not": {
26243
26243
  "version": "1.0.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testim/testim-cli",
3
- "version": "3.259.0",
3
+ "version": "3.260.0",
4
4
  "description": "Command line interface for running Testing on your CI",
5
5
  "author": "Oren Rubin",
6
6
  "contributors": [{
@@ -119,7 +119,8 @@
119
119
  "prepare-version": "rm -rf ./deploy && mkdir -p deploy && gulp prepare-version-on-prem",
120
120
  "make-onprem-deps": "cp ../../yarn.lock deploy && cd deploy && yarn install --production && bundle-deps",
121
121
  "pack-onprem": "yarn prepare-version && yarn make-onprem-deps && cd deploy && npm pack && zip -r testim-cli.zip testim-cli-*.tgz",
122
- "pack-serve": "yarn pack-onprem && http-server deploy/"
122
+ "pack-serve": "yarn pack-onprem && http-server deploy/",
123
+ "self-test": "cd /tmp && cross-env DEBUG=self-test BUILD_MAX_MEMORY=4096 node /home/circleci/testimio/apps/runner/scripts/selfTest.js"
123
124
  },
124
125
  "engines": {
125
126
  "node": ">= 14.0.0"
@@ -45,7 +45,7 @@ class BaseJsStepAction extends StepAction {
45
45
 
46
46
  executeGetStatus(transactionId) {
47
47
  // TODO: Cleanup after dropping IE11/Edge support
48
- /* eslint-disable prefer-arrow-callback, no-undef, unicorn/prefer-includes */
48
+ /* eslint-disable prefer-arrow-callback, no-undef, unicorn/prefer-includes, no-shadow */
49
49
  return this.driver.executeJS(function (transactionId) {
50
50
  const sessionItem = 'data-testim-' + transactionId;
51
51
  try {
@@ -63,7 +63,7 @@ class BaseJsStepAction extends StepAction {
63
63
  throw err;
64
64
  }
65
65
  }, transactionId);
66
- /* eslint-enable prefer-arrow-callback, no-undef, unicorn/prefer-includes */
66
+ /* eslint-enable prefer-arrow-callback, no-undef, unicorn/prefer-includes, no-shadow */
67
67
  }
68
68
 
69
69
  constructJSFunParams(eventData) {
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  const BaseCliJsStepAction = require('./baseCliJsStepAction');
4
4
 
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  const BaseCliJsStepAction = require('./baseCliJsStepAction');
4
4
 
@@ -5,7 +5,7 @@ class ExtensionOnlyStepAction extends StepAction {
5
5
  performAction() {
6
6
  return Promise.resolve({
7
7
  success: 'skipped',
8
- reason: "This step can run only on Chrome"
8
+ reason: 'This step can run only on Chrome',
9
9
  });
10
10
  }
11
11
  }
@@ -1,10 +1,8 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  const StepAction = require('./stepAction');
4
- const Promise = require('bluebird');
5
4
 
6
5
  class ExtractTextStepAction extends StepAction {
7
-
8
6
  performAction() {
9
7
  const paramName = this.step.extractTextParamName;
10
8
 
@@ -12,13 +10,12 @@ class ExtractTextStepAction extends StepAction {
12
10
  .then(extractedText => {
13
11
  this.context.data.exports = this.context.data.exports || {};
14
12
  this.context.data.exports[paramName] = extractedText;
15
- return Promise.resolve({
13
+ return {
16
14
  success: true,
17
- data: this.context.data
18
- });
15
+ data: this.context.data,
16
+ };
19
17
  });
20
18
  }
21
-
22
19
  }
23
20
 
24
21
  module.exports = ExtractTextStepAction;
@@ -55,4 +55,3 @@ class HoverStepAction extends StepAction {
55
55
  }
56
56
 
57
57
  module.exports = HoverStepAction;
58
-
@@ -1,7 +1,6 @@
1
1
  'use strict';
2
2
 
3
3
  const StepAction = require('./stepAction');
4
- const _ = require('lodash');
5
4
  const logger = require('../../commons/logger').getLogger('input-file-step-action');
6
5
  const { codeSnippets, utils } = require('../../commons/getSessionPlayerRequire');
7
6
  const { extractElementId, download } = require('../../utils');
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  const BaseJsStepAction = require('./baseJsStepAction');
4
4
 
@@ -9,4 +9,3 @@ class JsCodeStepAction extends BaseJsStepAction {
9
9
  }
10
10
 
11
11
  module.exports = JsCodeStepAction;
12
-
@@ -1,4 +1,4 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  const BaseJsStepAction = require('./baseJsStepAction');
4
4
 
@@ -9,4 +9,3 @@ class JsConditionStepAction extends BaseJsStepAction {
9
9
  }
10
10
 
11
11
  module.exports = JsConditionStepAction;
12
-
@@ -15,26 +15,26 @@ const {
15
15
  const DEFAULT_VISIBILITY_RESULT = { opacity: 1, clientRects: {} };
16
16
 
17
17
  function createUtils(driver) {
18
- return class LocatorUtils {
19
- static getFrameIdByTestimFrameId() { }
18
+ return {
19
+ getFrameIdByTestimFrameId() { },
20
20
 
21
- static setElementResultDataOnContext(target) {
21
+ setElementResultDataOnContext(target) {
22
22
  return driver.getElement(target.locatedElement)
23
23
  .then(seleniumResponse => {
24
24
  target.seleniumElement = seleniumResponse.value;
25
25
  });
26
- }
26
+ },
27
27
 
28
- static getElementRectangle(target) {
28
+ getElementRectangle(target) {
29
29
  return driver.getElementRect(target);
30
- }
30
+ },
31
31
 
32
- static getOffsets(frameHandler) {
32
+ getOffsets(frameHandler) {
33
33
  return Promise.resolve([frameHandler.frameOffset || {}]);
34
- }
34
+ },
35
35
 
36
36
  /** @type {typeof import('clickim/src/background/stepActions/locateStepAction').LocateStepAction['htmlStringToDom']} */
37
- static htmlStringToDom(htmlString, url, nonBodyElements, bodyTagName, setDomTimeout = true) {
37
+ htmlStringToDom(htmlString, url, nonBodyElements, bodyTagName, setDomTimeout = true) {
38
38
  const virtualConsole = new VirtualConsole();
39
39
  const jsdom = new JSDOM(htmlString, {
40
40
  virtualConsole,
@@ -51,9 +51,9 @@ function createUtils(driver) {
51
51
  }
52
52
  window.document.TESTIM_URL = url;
53
53
  return window.document;
54
- }
54
+ },
55
55
 
56
- static shouldUseNativeVisibilityCheck(locateStep, driver, visibilityUtils, positionUtils) {
56
+ shouldUseNativeVisibilityCheck(locateStep, driver, visibilityUtils, positionUtils) {
57
57
  if (locateStep.opacity === 0) {
58
58
  return false;
59
59
  }
@@ -73,10 +73,10 @@ function createUtils(driver) {
73
73
  return featureFlags.flags.useIEWebdriverVisibilityChecks.isEnabled();
74
74
  }
75
75
  return true;
76
- }
76
+ },
77
77
 
78
78
  /** @type {typeof import('clickim/src/background/stepActions/locateStepAction').LocateStepAction['isVisible']} */
79
- static isVisible(target, targetElement, rect, locateStep, frameHandler, allOffsets, dom) {
79
+ isVisible(target, targetElement, rect, locateStep, frameHandler, allOffsets, dom) {
80
80
  const skipVisibilityCheck =
81
81
  featureFlags.flags.disableEdgeVisibilityChecks.isEnabled() && driver.isEdge();
82
82
 
@@ -86,7 +86,7 @@ function createUtils(driver) {
86
86
  return driver.isVisible(target.seleniumElement).catch(() => { }).then(() => true);
87
87
  }
88
88
 
89
- const useNativeVisibilityCheck = LocatorUtils.shouldUseNativeVisibilityCheck(locateStep, driver, visibilityUtils, positionUtils);
89
+ const useNativeVisibilityCheck = this.shouldUseNativeVisibilityCheck(locateStep, driver, visibilityUtils, positionUtils);
90
90
  if (useNativeVisibilityCheck) {
91
91
  return driver.isVisible(target.seleniumElement);
92
92
  }
@@ -120,12 +120,12 @@ function createUtils(driver) {
120
120
  return driver.isVisible(target.seleniumElement)
121
121
  .catch(() => { })
122
122
  .then(handler);
123
- }
123
+ },
124
124
 
125
- static scrollToElement(frameHandler, locatedElement) {
125
+ scrollToElement(frameHandler, locatedElement) {
126
126
  const code = codeSnippets.scrollToElement;
127
127
  return driver.execute(code(locatedElement));
128
- }
128
+ },
129
129
  };
130
130
  }
131
131
 
@@ -5,13 +5,12 @@ const StepAction = require('./stepAction');
5
5
  const { eyeSdkService } = require('../utils/eyeSdkService');
6
6
  const logger = require('../../commons/logger').getLogger('pixel-validation-step-action');
7
7
 
8
-
9
8
  class PixelValidationStepAction extends StepAction {
10
9
  async performAction() {
11
10
  const { shouldUseVisualGrid, applitoolsSdkConfig: config, testResultId } = this.context;
12
11
  this.runContext = this.context.getRunContext(undefined);
13
- const finalParams = (this.runContext.incomingParams && this.runContext.incomingParams.final) || {};
14
- const batchId = (config.batch && config.batch.id) || testResultId;
12
+ const finalParams = this.runContext.incomingParams?.final || {};
13
+ const batchId = config.batch?.id || testResultId;
15
14
  const eyeManager = await eyeSdkService.getManager(shouldUseVisualGrid, this.context.config.applitoolsConcurrency || 5, batchId, this.runContext.applitoolsIntegrationData);
16
15
  const targetElementData = this.getTarget() || {};
17
16
  let result;
@@ -1,16 +1,17 @@
1
- "use strict";
1
+ 'use strict';
2
+
2
3
  const StepAction = require('./stepAction');
3
4
  const { codeSnippets, commonConstants } = require('../../commons/getSessionPlayerRequire');
4
5
  const scroll = require('./scripts/scroll');
6
+
5
7
  const constants = commonConstants.stepResult;
6
8
 
7
9
  class ScrollStepAction extends StepAction {
8
-
9
- getFailureString(step, expectedX, expectedY, actualX, actualY){
10
+ getFailureString(step, expectedX, expectedY, actualX, actualY) {
10
11
  if (!step.isScrollToElement) {
11
12
  return `Scrolling limit reached. Expected:(y: ${expectedY}, x: ${expectedX}); Actual:(y:${actualY}, x: ${actualX})`;
12
13
  }
13
- let failureMessage = "Scrolling limit reached";
14
+ let failureMessage = 'Scrolling limit reached';
14
15
  if (step.shouldScrollTop) {
15
16
  failureMessage += `. Expected top margin: ${expectedY}, actual: ${actualY}`;
16
17
  }
@@ -38,33 +39,41 @@ class ScrollStepAction extends StepAction {
38
39
  return scroll.apply(null, arguments)
39
40
  `;
40
41
 
41
- return this.driver.executeJSWithArray(scrollCode, [elementToScrollOn, elementToScrollTo, Boolean(step.isScrollToElement), Boolean(step.isDynamicScroll), expectedX, expectedY, step.shouldScrollLeft, step.shouldScrollTop])
42
- .then((res) => {
43
- if(!res || !res.value) {
42
+ return this.driver
43
+ .executeJSWithArray(scrollCode, [
44
+ elementToScrollOn,
45
+ elementToScrollTo,
46
+ Boolean(step.isScrollToElement),
47
+ Boolean(step.isDynamicScroll),
48
+ expectedX,
49
+ expectedY,
50
+ step.shouldScrollLeft,
51
+ step.shouldScrollTop,
52
+ ])
53
+ .then(res => {
54
+ if (!res || !res.value) {
44
55
  return {
45
56
  errorType: constants.SCROLL_ACTION_FAILURE,
46
57
  success: false,
47
- }
58
+ };
48
59
  }
49
60
 
50
- const {success, actualX, actualY} = res.value;
61
+ const { success, actualX, actualY } = res.value;
51
62
 
52
- if(success) {
53
- return {success: true};
63
+ if (success) {
64
+ return { success: true };
54
65
  }
55
66
 
56
67
  return {
57
68
  errorType: constants.SCROLL_ACTION_FAILURE,
58
69
  success: false,
59
- resultInfo: {error: this.getFailureString(step, expectedX, expectedY, actualX, actualY)}
70
+ resultInfo: { error: this.getFailureString(step, expectedX, expectedY, actualX, actualY) },
60
71
  };
61
72
  })
62
- .catch(() => {
63
- return {
64
- errorType: constants.SCROLL_ACTION_FAILURE,
65
- success: false,
66
- };
67
- });
73
+ .catch(() => ({
74
+ errorType: constants.SCROLL_ACTION_FAILURE,
75
+ success: false,
76
+ }));
68
77
  }
69
78
 
70
79
  scrollOnDocument(step, elementToScrollTo) {
@@ -84,7 +93,6 @@ class ScrollStepAction extends StepAction {
84
93
  this.scrollOnDocument(step, elementToScrollTo) :
85
94
  this.scrollOnElement(step, elementToScrollTo);
86
95
  }
87
-
88
96
  }
89
97
 
90
98
  module.exports = ScrollStepAction;
@@ -15,7 +15,7 @@ class SelectOptionStepAction extends StepAction {
15
15
 
16
16
  const browserMajor = browserAndOS.browserMajor;
17
17
  const isSafari = this.driver.isSafari();
18
- const isShadowed = Boolean(this.step.element && this.step.element.isShadowed);
18
+ const isShadowed = Boolean(this.step.element?.isShadowed);
19
19
 
20
20
  // TODO: Remove the special handling for safari < 12 after we upgrade our grid to safari 13.
21
21
  // force use js code when element is shadow dom
@@ -40,7 +40,7 @@ class SelectOptionStepAction extends StepAction {
40
40
  `;
41
41
 
42
42
  const result = await this.driver.executeJSWithArray(selectOptionCode, [locatedElement, safariSelectOptionDispatchEventOnSelectElement]);
43
- if (result.value && result.value.success) {
43
+ if (result.value?.success) {
44
44
  return { success: true };
45
45
  }
46
46
  return { success: false };
@@ -1,11 +1,12 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  const { extractElementId } = require('../../utils');
4
4
  const StepAction = require('./stepAction');
5
5
  const Promise = require('bluebird');
6
+
6
7
  const keyMap = {
7
- 8: '\uE008', // (Backspace)
8
- 9: '\uE004', // (tab)
8
+ 8: '\uE008', // (Backspace)
9
+ 9: '\uE004', // (tab)
9
10
  13: '\uE007', // (enter)
10
11
  27: '\uE00C', // (esc)
11
12
  33: '\uE00E', // (page up)
@@ -24,23 +25,22 @@ const keyMap = {
24
25
  120: '\uE039', // (f9)
25
26
  121: '\uE03A', // (f10)
26
27
  122: '\uE03B', // (f11)
27
- 123: '\uE03C' // (f12)
28
+ 123: '\uE03C', // (f12)
28
29
  };
29
30
 
30
31
  class SpecialKeyStepAction extends StepAction {
31
-
32
32
  setWithValueApi(keys) {
33
33
  const target = this.getTarget();
34
- if (target && target.seleniumElement) {
34
+ if (target?.seleniumElement) {
35
35
  return this.driver.elementIdValue(extractElementId(target.seleniumElement), keys);
36
36
  }
37
- return Promise.reject(new Error("missing selenium element"));
37
+ return Promise.reject(new Error('missing selenium element'));
38
38
  }
39
39
 
40
40
  performAction() {
41
41
  const keys = [];
42
42
  const keyCode = this.step.events[0].eventData.keyCode;
43
-
43
+
44
44
  if (keyCode >= 32 && keyCode <= 127) {
45
45
  keys.push(String.fromCharCode(keyCode));
46
46
  } else {
@@ -48,8 +48,6 @@ class SpecialKeyStepAction extends StepAction {
48
48
  }
49
49
  return this.setWithValueApi(keys);
50
50
  }
51
-
52
51
  }
53
52
 
54
53
  module.exports = SpecialKeyStepAction;
55
-
@@ -45,11 +45,11 @@ class StepAction {
45
45
  /** @type {ClickimStepAction['execute']} */
46
46
  execute(stepActionFactory, step) {
47
47
  return Promise.resolve(this.performAction(stepActionFactory, step))
48
- .then(res => Promise.resolve(Object.assign({}, { success: true }, res)))
48
+ .then(res => Object.assign({ success: true }, res))
49
49
  .catch(err => {
50
- const errorMsg = (err || {}).message || (err && err.seleniumStack && err.seleniumStack.message);
51
- const displayMsg = (err || {}).displayMessage;
52
- return Promise.resolve({
50
+ const errorMsg = err?.message || err?.seleniumStack?.message;
51
+ const displayMsg = err?.displayMessage;
52
+ return {
53
53
  success: false,
54
54
  reason: errorMsg,
55
55
  exception: err,
@@ -60,7 +60,7 @@ class StepAction {
60
60
  // expects resultInfo.error or resultInfo.reason
61
61
  error: displayMsg || errorMsg,
62
62
  },
63
- });
63
+ };
64
64
  });
65
65
  }
66
66
  }
@@ -104,4 +104,3 @@ module.exports = function (driver, stepActionFactory, runMode) {
104
104
  stepActionFactory.registerLocateStepActionUtils(LocateStepAction.getUtils(driver));
105
105
  }
106
106
  };
107
-
@@ -1,9 +1,8 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  const StepAction = require('./stepAction');
4
4
 
5
5
  class SubmitStepAction extends StepAction {
6
-
7
6
  performAction() {
8
7
  return this.driver.submitForm(this.getTarget().seleniumElement)
9
8
  .then(() => {});
@@ -1,18 +1,16 @@
1
1
  'use strict';
2
2
 
3
3
  const StepAction = require('./stepAction');
4
-
5
- const { execute } = require('../../stepPlayers/hybridStepPlayback')
4
+ const { execute } = require('../../stepPlayers/hybridStepPlayback');
6
5
 
7
6
  class TdkHybridStepAction extends StepAction {
8
-
9
7
  async performAction() {
10
- return await execute(
11
- this.step,
12
- this.context,
13
- this.driver,
14
- this.stepActionUtils.testimServicesApi.authenticationManager.getLoggedUserInfo(),
15
- this.frameHandler.frameManager
8
+ return await execute(
9
+ this.step,
10
+ this.context,
11
+ this.driver,
12
+ this.stepActionUtils.testimServicesApi.authenticationManager.getLoggedUserInfo(),
13
+ this.frameHandler.frameManager
16
14
  );
17
15
  }
18
16
  }
@@ -10,6 +10,7 @@ const { extractElementId, delay } = require('../../utils');
10
10
 
11
11
  const constants = sessionPlayer.commonConstants.stepResult;
12
12
  const setTextDraftJs = codeSnippets?.setTextDraftJs;
13
+
13
14
  class TextStepAction extends StepAction {
14
15
  setValueNative() {
15
16
  const context = this.context;
@@ -1,27 +1,24 @@
1
- "use strict";
2
-
1
+ 'use strict';
3
2
 
3
+ const Promise = require('bluebird');
4
4
  const sessionPlayer = require('../../commons/getSessionPlayerRequire');
5
-
6
5
  const StepAction = require('./stepAction');
6
+
7
7
  const constants = sessionPlayer.commonConstants.stepResult;
8
8
  const paramEvaluator = sessionPlayer.stepParamExpressionEvaluator;
9
9
  const utils = sessionPlayer.utils;
10
10
 
11
-
12
- const Promise = require('bluebird');
13
-
14
11
  class TextValidationStepAction extends StepAction {
15
12
  performAction(stepActionFactory) {
16
- var step = this.step;
17
- var context = this.context;
18
- var target = this.getTarget();
19
- var frameHandler = this.frameHandler;
20
-
13
+ const step = this.step;
14
+ const context = this.context;
15
+ const target = this.getTarget();
16
+ const frameHandler = this.frameHandler;
17
+
21
18
 
22
19
  return new Promise(resolve => {
23
- var onFail = resultInfo => {
24
- resolve({ errorType: constants.TEXT_COMPARE_FAILURE, resultInfo: resultInfo, success: false });
20
+ const onFail = resultInfo => {
21
+ resolve({ errorType: constants.TEXT_COMPARE_FAILURE, resultInfo, success: false });
25
22
  };
26
23
  this.stepActionUtils.extractTargetText(target)
27
24
  .then(text => {
@@ -29,13 +26,13 @@ class TextValidationStepAction extends StepAction {
29
26
  const expected = paramEvaluator.computeExpression(step.expression2, context, this.exportsGlobal, this.exportsTest);
30
27
  return {
31
28
  actual: text,
32
- expected: expected.evaluatedText
29
+ expected: expected.evaluatedText,
33
30
  };
34
31
  }
35
32
  return stepActionFactory.executeStep(step.expression2, context, frameHandler, this.exportsGlobal, this.locateElementPlayer, this.exportsTest)
36
33
  .then(res => ({
37
34
  actual: text,
38
- expected: res.evaluatedText
35
+ expected: res.evaluatedText,
39
36
  }));
40
37
  })
41
38
  .then(({ actual, expected }) => {
@@ -43,16 +40,16 @@ class TextValidationStepAction extends StepAction {
43
40
  const compareResult = utils.compareOrMatch(expected, actual);
44
41
  return compareResult ?
45
42
  resolve({ success: true }) :
46
- onFail({ expected: String(expected), actual: actual });
43
+ onFail({ expected: String(expected), actual });
47
44
  } catch (err) {
48
- return onFail({ expected: expected.toString(), actual: actual });
45
+ return onFail({ expected: expected.toString(), actual });
49
46
  }
50
47
  })
51
48
  .catch(err => resolve({
52
49
  success: false,
53
50
  reason: err.message,
54
51
  exception: err,
55
- shouldRetry: true
52
+ shouldRetry: true,
56
53
  }));
57
54
  });
58
55
  }
@@ -1,11 +1,11 @@
1
- "use strict";
1
+ 'use strict';
2
+
2
3
  const Promise = require('bluebird');
3
4
  const StepAction = require('./stepAction');
4
5
  const wheelScript = require('./scripts/wheel');
5
6
  const { codeSnippets } = require('../../commons/getSessionPlayerRequire');
6
7
 
7
8
  class WheelStepAction extends StepAction {
8
-
9
9
  performAction() {
10
10
  const step = this.step;
11
11
  const context = this.context;
@@ -16,12 +16,12 @@ class WheelStepAction extends StepAction {
16
16
  }
17
17
 
18
18
  const eventMessage = {
19
- events: events,
19
+ events,
20
20
  eventData: {
21
21
  modifiers: step.modifiers,
22
- button: step.button
22
+ button: step.button,
23
23
  },
24
- locatedElement: this.getTarget().locatedElement
24
+ locatedElement: this.getTarget().locatedElement,
25
25
  };
26
26
 
27
27
  const timeout = context.data.timeToPlayStep + 3000;
@@ -29,7 +29,7 @@ class WheelStepAction extends StepAction {
29
29
  const wheelCode = `
30
30
  var getLocatedElement = ${codeSnippets.getLocatedElementCode};
31
31
  var wheel = ${wheelScript.toString()};
32
- var eventData = ${this.driver.isEdge() ? `JSON.parse(arguments[0])` : `arguments[0]`};
32
+ var eventData = ${this.driver.isEdge() ? 'JSON.parse(arguments[0])' : 'arguments[0]'};
33
33
  var done = arguments[1];
34
34
  return wheel.call(null, eventData, done);
35
35
  `;
@@ -40,13 +40,12 @@ class WheelStepAction extends StepAction {
40
40
 
41
41
  return this.driver.executeCodeAsync(wheelCode, timeout, eventParam)
42
42
  .then(result => {
43
- if (result.value && result.value.state === "success") {
44
- return Promise.resolve({ success: true });
43
+ if (result.value && result.value.state === 'success') {
44
+ return { success: true };
45
45
  }
46
- return Promise.resolve({ success: false });
46
+ return { success: false };
47
47
  });
48
48
  }
49
-
50
49
  }
51
50
 
52
51
  module.exports = WheelStepAction;
package/runOptions.d.ts CHANGED
@@ -108,6 +108,13 @@ interface RunnerOptions extends Partial<Omit<TunnelOptions, 'tunnelOnlyMode' | '
108
108
  retentionDays?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
109
109
  retries?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20;
110
110
 
111
+ //# region mobile flags
112
+ deviceModel: string;
113
+ deviceUdid: string;
114
+ osVersion: string;
115
+ // #endregion
116
+
117
+
111
118
  // #region Data set based on values from server
112
119
  company: {
113
120
  companyId: string;
package/runOptions.js CHANGED
@@ -210,6 +210,10 @@ program
210
210
  .option('--set-retention [retention-in-days]', 'set the number of days for results retention')
211
211
  .option('--user [user-id]', 'user ID for local Testim-CLI')
212
212
  .option('--pass-zero-tests', 'don\'t fail the run if no tests were found')
213
+ //Mobile options
214
+ .option('--device-model [device-model]', 'The device model to use, iPhone 12, Nexus 5X, SM-G900P etc....')
215
+ .option('--device-udid [device-udid]', 'the device unique id')
216
+ .option('--os-version [os-version]', 'The operating system version number')
213
217
 
214
218
  .option('-str --suppress-tms-reporting [suppress-tms-reporting]', 'disable test management reporting', false)
215
219
  .option('-tsr --tms-suppress-reporting [tms-suppress-reporting]', 'disable test management reporting', false)
@@ -1032,6 +1036,10 @@ module.exports = {
1032
1036
  program.turboMode = true;
1033
1037
  }
1034
1038
 
1039
+ if (program.deviceUdid && (program.deviceModel || program.osVersion)) {
1040
+ throw new ArgError('It is not possible to use --osVersion or --deviceModel with --device-udid. device-udid is unique and cannot be combined with another flag');
1041
+ }
1042
+
1035
1043
  if (program.lightweightMode) {
1036
1044
  try {
1037
1045
  const DEFAULTS = {
@@ -1148,6 +1156,10 @@ module.exports = {
1148
1156
  passZeroTests: Boolean(program.passZeroTests),
1149
1157
  runQuarantinedTests: Boolean(program.runQuarantinedTests),
1150
1158
 
1159
+ deviceModel: program.deviceModel,
1160
+ deviceUdid: program.deviceUdid,
1161
+ osVersion: program.osVersion,
1162
+
1151
1163
  // Extension
1152
1164
  ext: program.ext,
1153
1165
  extensionLocation: [program.extensionPath || extHeadlessUrl].flat(),
@@ -1,20 +1,21 @@
1
1
  // @ts-check
2
2
 
3
- "use strict";
3
+ 'use strict';
4
+
4
5
  const config = require('./commons/config');
5
6
 
6
7
  module.exports = {
7
8
  getExtensionsUrl,
8
9
  getResolvedExtensionUrl,
9
- getPlayerUrl
10
- }
10
+ getPlayerUrl,
11
+ };
11
12
 
12
13
  /**
13
14
  *
14
15
  * @param {Readonly<import("commander").CommanderStatic>} program
15
16
  */
16
17
  function getExtensionsUrl(program, useCanonicalURL) {
17
- const zipFileSuffix = program.canary ? "-master.zip" : ".zip";
18
+ const zipFileSuffix = program.canary ? '-master.zip' : '.zip';
18
19
  let firefox;
19
20
  let chrome;
20
21
  if (!useCanonicalURL) {
@@ -40,11 +41,11 @@ function getResolvedExtensionUrl(program) {
40
41
 
41
42
  if (program.browser === 'firefox') {
42
43
  return firefox;
43
- } else if(program.browser === 'chrome') {
44
- return chrome
45
- } else {
46
- return [chrome, firefox];
47
44
  }
45
+ if (program.browser === 'chrome') {
46
+ return chrome;
47
+ }
48
+ return [chrome, firefox];
48
49
  }
49
50
 
50
51
  /**
@@ -52,8 +53,8 @@ function getResolvedExtensionUrl(program) {
52
53
  * @param {Readonly<import("commander").CommanderStatic>} program
53
54
  */
54
55
  function getPlayerUrl(program) {
55
- let playerUrlPrefix = `${config.BLOB_URL}/extension/sessionPlayer`;
56
- const playerUrl = program.canary ? playerUrlPrefix + "-master" : playerUrlPrefix;
56
+ const playerUrlPrefix = `${config.BLOB_URL}/extension/sessionPlayer`;
57
+ const playerUrl = program.canary ? `${playerUrlPrefix}-master` : playerUrlPrefix;
57
58
 
58
59
  return playerUrl;
59
60
  }
@@ -30,7 +30,7 @@ class WorkerAppium extends BaseWorker {
30
30
  const { driver } = appiumTestPlayer;
31
31
  const nativeApp = testRunHandler.getNativeAppData();
32
32
  const projectType = this.options.projectData.type;
33
- const capabilities = desiredCapabilitiesBuilder.buildAppiumOptions({ projectType, gridInfo, testRunConfig: this.testRunConfig, nativeApp });
33
+ const capabilities = desiredCapabilitiesBuilder.buildAppiumOptions({ projectType, gridInfo, testRunConfig: this.testRunConfig, nativeApp, options: this.options });
34
34
  try {
35
35
  //we assume the application is installed on the device. (all headspin allocated devices)
36
36
  const activeSession = await driver.remote(capabilities);