@testim/testim-cli 3.228.0 → 3.231.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testim/testim-cli",
3
- "version": "3.228.0",
3
+ "version": "3.231.0",
4
4
  "description": "Command line interface for running Testing on your CI",
5
5
  "author": "Oren Rubin",
6
6
  "contributors": [{
@@ -47,8 +47,8 @@
47
47
  "multer": "1.4.4"
48
48
  },
49
49
  "dependencies": {
50
- "@applitools/eyes-sdk-core": "13.0.6",
51
- "@applitools/visual-grid-client": "15.9.0",
50
+ "@applitools/eyes-sdk-core": "13.2.0",
51
+ "@applitools/visual-grid-client": "15.11.0",
52
52
  "@testim/coralogix-logger": "1.1.27-beta.1",
53
53
  "@testim/webdriverio": "0.0.5",
54
54
  "abort-controller": "3.0.0",
@@ -1,7 +1,6 @@
1
1
  'use strict';
2
2
 
3
3
  const StepAction = require('./stepAction');
4
- const Promise = require('bluebird');
5
4
  const _ = require('lodash');
6
5
  const logger = require('../../commons/logger').getLogger('input-file-step-action');
7
6
  const { codeSnippets, utils } = require('../../commons/getSessionPlayerRequire');
@@ -26,53 +25,58 @@ class InputFileStepAction extends StepAction {
26
25
  return this.driver.executeJS(getVisibleElementCode, target.locatedElement);
27
26
  }
28
27
 
29
- safariPreUploadActions(target) {
28
+ async safariPreUploadActions(target) {
30
29
  const options = {
31
30
  width: '150px',
32
31
  height: '150px',
33
32
  left: '10px',
34
33
  top: '10px',
35
34
  };
36
- return this.forceInputToBeVisible(target, options)
37
- .catch(err => {
38
- logger.error('failed to set input file in Safari recovery', { err });
39
- throw err;
40
- });
35
+ try {
36
+ return await this.forceInputToBeVisible(target, options);
37
+ } catch (err) {
38
+ logger.error('failed to set input file in Safari recovery', { err });
39
+ throw err;
40
+ }
41
41
  }
42
42
 
43
- uploadFilesAndForceVisibility(gridLocalFiles, target) {
43
+ async uploadFilesAndForceVisibility(gridLocalFiles, target) {
44
44
  const preUploadStep = this.driver.isSafari() ?
45
- // // in safari we force the visibility ahead of time because making it visible the second time around doesn't work
45
+ // in safari we force the visibility ahead of time because making it visible the second time around doesn't work
46
46
  this.safariPreUploadActions(target) :
47
47
  Promise.resolve();
48
48
 
49
- return preUploadStep.then(() => this.uploadFiles(gridLocalFiles, target))
50
- .catch(err => {
51
- const edgeErrorEditableMessage = 'The element is not editable';
52
- const edgeErrorFocusableMessage = 'The element is not focusable';
53
- const safariErrorVisibleMessege = 'An element command could not be completed because the element is not visible on the page.';
54
- const elementNotInteractable = 'element not interactable';
55
- const elementNotPointerOrKeyboardInteractable = 'element is not pointer- or keyboard interactable';
56
- const invalidStateMsg = 'invalid element state: Element is not currently interactable and may not be manipulated';
57
- const mustBeVisibleMsg = 'Element must not be hidden, disabled or read-only';
58
- const notReachableByKeyboard = 'is not reachable by keyboard';
59
- const errorMsg = err ? err.message : '';
60
- // Workaround move element if element is not visible or disabled
61
- if (_.isEqual(errorMsg, invalidStateMsg) ||
62
- _.startsWith(errorMsg, mustBeVisibleMsg) ||
63
- _.startsWith(errorMsg, edgeErrorEditableMessage) ||
64
- _.startsWith(errorMsg, edgeErrorFocusableMessage) ||
65
- _.startsWith(errorMsg, safariErrorVisibleMessege) ||
66
- _.includes(errorMsg, notReachableByKeyboard) ||
67
- _.includes(errorMsg, elementNotInteractable) ||
68
- _.includes(errorMsg, elementNotPointerOrKeyboardInteractable)
69
- ) {
70
- return this.forceInputToBeVisible(target).then(() => this.uploadFiles(gridLocalFiles, target));
71
- }
49
+ try {
50
+ await preUploadStep;
51
+ await this.uploadFiles(gridLocalFiles, target);
52
+ } catch (err) {
53
+ const edgeErrorEditableMessage = 'The element is not editable';
54
+ const edgeErrorFocusableMessage = 'The element is not focusable';
55
+ const safariErrorVisibleMessege = 'An element command could not be completed because the element is not visible on the page.';
56
+ const elementNotInteractable = 'element not interactable';
57
+ const elementNotPointerOrKeyboardInteractable = 'element is not pointer- or keyboard interactable';
58
+ const invalidStateMsg = 'invalid element state: Element is not currently interactable and may not be manipulated';
59
+ const mustBeVisibleMsg = 'Element must not be hidden, disabled or read-only';
60
+ const notReachableByKeyboard = 'is not reachable by keyboard';
61
+ const errorMsg = err ? err.message : '';
62
+ // Workaround move element if element is not visible or disabled
63
+ if (_.isEqual(errorMsg, invalidStateMsg) ||
64
+ _.startsWith(errorMsg, mustBeVisibleMsg) ||
65
+ _.startsWith(errorMsg, edgeErrorEditableMessage) ||
66
+ _.startsWith(errorMsg, edgeErrorFocusableMessage) ||
67
+ _.startsWith(errorMsg, safariErrorVisibleMessege) ||
68
+ _.includes(errorMsg, notReachableByKeyboard) ||
69
+ _.includes(errorMsg, elementNotInteractable) ||
70
+ _.includes(errorMsg, elementNotPointerOrKeyboardInteractable)
71
+ ) {
72
+ await this.forceInputToBeVisible(target);
73
+ await this.uploadFiles(gridLocalFiles, target);
74
+ return;
75
+ }
72
76
 
73
- logger.error('failed to set input file', { err });
74
- return Promise.reject(err);
75
- });
77
+ logger.error('failed to set input file', { err });
78
+ throw err;
79
+ }
76
80
  }
77
81
 
78
82
  async uploadFiles(gridLocalFiles, target) {
@@ -81,31 +85,22 @@ class InputFileStepAction extends StepAction {
81
85
  }
82
86
  }
83
87
 
84
- performAction() {
88
+ async performAction() {
85
89
  const target = this.context.data[this.step.targetId || 'targetId'];
86
90
  const overrideAzureStorageUrl = featureFlagService.flags.overrideAzureStorageUrl.isEnabled();
87
- //TODO remove if after release session player
88
- return (utils.addTokenToFileUrl ? utils.addTokenToFileUrl(
89
- this.context.project.id,
90
- this.step.fileUrls,
91
- this.stepActionUtils.testimServicesApi,
92
- overrideAzureStorageUrl,
93
- logger,
94
- ) : Promise.resolve(this.step.fileUrls)).then((fileUrls) => {
95
- const useJsInputCodeInSafari = featureFlagService.flags.useJsInputCodeInSafari.isEnabled();
96
- if (this.driver.isSafari() && (useJsInputCodeInSafari || fileUrls.length > 1)) {
97
- return this.driver.executeJSWithArray(`
91
+
92
+ const fileUrls = await utils.addTokenToFileUrl(this.context.project.id, this.step.fileUrls, this.stepActionUtils.testimServicesApi, overrideAzureStorageUrl, logger);
93
+ const useJsInputCodeInSafari = featureFlagService.flags.useJsInputCodeInSafari.isEnabled();
94
+ if (this.driver.isSafari() && (useJsInputCodeInSafari || fileUrls.length > 1)) {
95
+ await this.driver.executeJSWithArray(`
98
96
  const getLocatedElement = ${codeSnippets.getLocatedElementCode};
99
97
  const downloadAndUploadFile = ${downloadAndUpload()};
100
- return downloadAndUploadFile.apply(null, arguments);`,
101
- [target.locatedElement, fileUrls])
102
- .then(() => Promise.resolve());
103
- }
98
+ return downloadAndUploadFile.apply(null, arguments);`, [target.locatedElement, fileUrls]);
99
+ return;
100
+ }
104
101
 
105
- return inputFileUtils.downloadFilesAndUploadToGrid(fileUrls, this.uploadFile.bind(this))
106
- .then(gridLocalFiles => this.uploadFilesAndForceVisibility(gridLocalFiles, target))
107
- .then(() => Promise.resolve());
108
- });
102
+ const gridLocalFiles = await inputFileUtils.downloadFilesAndUploadToGrid(fileUrls, this.uploadFile.bind(this));
103
+ await this.uploadFilesAndForceVisibility(gridLocalFiles, target);
109
104
  }
110
105
  }
111
106
 
@@ -138,8 +133,35 @@ function downloadAndUpload() {
138
133
  throw new Error('element not found');
139
134
  }
140
135
 
136
+ function getFileBlob(url) {
137
+ return new Promise((resolve, reject) => {
138
+ var xhr = new XMLHttpRequest();
139
+ xhr.open('GET', url, true);
140
+ xhr.responseType = 'blob';
141
+
142
+ xhr.onload = function() {
143
+ if (this.status === 200) {
144
+ resolve(this.response);
145
+ } else {
146
+ reject(new Error('Could not load file, failure status:' + this.status));
147
+ }
148
+ }
149
+ xhr.onerror = function(e) {
150
+ reject(new Error("Error " + e.target.status + " occurred while loading the file."));
151
+ };
152
+ xhr.send();
153
+ });
154
+
155
+ }
156
+
141
157
  const fileList = await Promise.all(fileUrls.map(async ({ url, name }) => {
142
- const blob = await fetch(url).then(r => r.blob());
158
+ let blob;
159
+ try {
160
+ const res = await fetch(url)
161
+ blob = await res.blob();
162
+ } catch (err) {
163
+ blob = await getFileBlob(url); // Sometimes the fetch fails, try using XHR as fallback
164
+ }
143
165
  return new File([blob], name, { type: blob.type });
144
166
  }));
145
167
 
@@ -9,6 +9,24 @@ const { makeSDK } = require('@applitools/eyes-sdk-core');
9
9
  const { W3C_ELEMENT_ID } = require('../constants');
10
10
  const _ = require('lodash');
11
11
 
12
+ let packageJson;
13
+ // There is a difference in the folder structure in prod vs. dev
14
+ try {
15
+ // PRODUCTION
16
+ // eslint-disable-next-line import/no-unresolved
17
+ packageJson = require('../../package.json');
18
+ } catch (e) {
19
+ //pass
20
+ }
21
+ if (!packageJson) {
22
+ try {
23
+ // in dev, they are one level up
24
+ packageJson = require('../../../package.json');
25
+ } catch (e) {
26
+ //pass
27
+ }
28
+ }
29
+
12
30
  const LEGACY_ELEMENT_ID = 'ELEMENT';
13
31
 
14
32
  function extractElementId(element) {
@@ -217,10 +235,12 @@ class EyesSpec {
217
235
 
218
236
  class EyeSdkService {
219
237
  constructor() {
238
+ const sdkVersion = packageJson ? packageJson.dependencies['@applitools/eyes-sdk-core'] : 'N/A';
239
+
220
240
  /** @type {Core} */
221
241
  this.sdk = makeSDK({
222
242
  name: 'Testim.io',
223
- version: '4.0.0',
243
+ version: `4.0.0/eyes-sdk-core/${sdkVersion}`,
224
244
  spec: new EyesSpec(),
225
245
  VisualGridClient: require('@applitools/visual-grid-client'),
226
246
  });