@testim/testim-cli 3.242.0 → 3.245.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.242.0",
3
+ "version": "3.245.0",
4
4
  "description": "Command line interface for running Testing on your CI",
5
5
  "author": "Oren Rubin",
6
6
  "contributors": [{
@@ -57,7 +57,6 @@
57
57
  "appium-dom-utils": "1.0.6",
58
58
  "archiver": "5.3.0",
59
59
  "bluebird": "3.7.2",
60
- "bluebird-retry": "0.11.0",
61
60
  "body-parser": "1.19.1",
62
61
  "chalk": "4.1.2",
63
62
  "chrome-launcher": "0.15.0",
@@ -87,6 +86,7 @@
87
86
  "npm": "8.3.0",
88
87
  "object-hash": "3.0.0",
89
88
  "ora": "5.4.1",
89
+ "p-retry": "4.6.2",
90
90
  "pako": "1.0.11",
91
91
  "portfinder": "1.0.28",
92
92
  "promise-queue": "2.2.5",
@@ -116,7 +116,7 @@
116
116
  "test": "IS_UNIT_TEST=1 ../../node_modules/mocha/bin/_mocha --timeout 2000 --reporter spec --exit --recursive \"./src/**/*.test.js\" --exclude ./src/codim/template.js/tests/examples/**/*.test.js",
117
117
  "test:watch": "IS_UNIT_TEST=1 ../../node_modules/mocha/bin/_mocha --timeout 2000 --exit --recursive \"./src/**/*.test.js\" --exclude ./src/codim/template.js/tests/examples/**/*.test.js --watch",
118
118
  "test:cov": "nyc --reporter=lcov --reporter=text yarn test",
119
- "upload-bundle-s3": "scripts/upload.js",
119
+ "upload-bundle-s3": "ts-node-transpile-only scripts/upload.js",
120
120
  "prepare-version": "rm -rf ./deploy && mkdir -p deploy && gulp prepare-version-on-prem",
121
121
  "make-onprem-deps": "cp ../../yarn.lock deploy && cd deploy && yarn install --production && bundle-deps",
122
122
  "pack-onprem": "yarn prepare-version && yarn make-onprem-deps && cd deploy && npm pack && zip -r testim-cli.zip testim-cli-*.tgz",
@@ -6,10 +6,8 @@ require('bluebird');
6
6
  class RefreshStepAction extends StepAction {
7
7
  execute() {
8
8
  return this.driver.reloadTab()
9
- .return({ success: true })
10
- .catch(error => {
11
- return { success: false, reason: error.message };
12
- });
9
+ .then(() => ({ success: true }))
10
+ .catch(error => ({ success: false, reason: error.message }));
13
11
  }
14
12
  }
15
13
 
@@ -1,14 +1,15 @@
1
- "use strict";
1
+ 'use strict';
2
+
2
3
  const Promise = require('bluebird');
3
4
  const sessionPlayer = require('../../commons/getSessionPlayerRequire');
4
5
  const StepAction = require('./stepAction');
6
+
5
7
  const constants = sessionPlayer.commonConstants.stepResult;
6
8
  const { stepParamBuilder } = sessionPlayer;
7
9
  const logger = require('../../commons/logger').getLogger('evaluate-expression-step-action');
8
10
  const _ = require('lodash');
9
11
 
10
12
  class EvaluateExpressionStepAction extends StepAction {
11
-
12
13
  execute() {
13
14
  const step = this.step;
14
15
  const context = this.context;
@@ -25,8 +26,8 @@ class EvaluateExpressionStepAction extends StepAction {
25
26
 
26
27
  const params = ['context', ...incomingParams.as.functionParameters];
27
28
  const args = [context, ...incomingParams.as.functionArguments];
28
- const expressionToEvaluate = step.subType === "text" ? "'" + step.expression.replace(/'/g, "\\\'") + "'" : step.expression;
29
- const code = ("return " + expressionToEvaluate).replace(/\n/g, "\\n");
29
+ const expressionToEvaluate = step.subType === 'text' ? `'${step.expression.replace(/'/g, "\\\'")}'` : step.expression;
30
+ const code = (`return ${expressionToEvaluate}`).replace(/\n/g, '\\n');
30
31
  const textEvaluateFunction = Function.apply(Function, params.concat([code]));
31
32
  const evaluatedText = textEvaluateFunction.apply(null, args);
32
33
 
@@ -38,8 +39,8 @@ class EvaluateExpressionStepAction extends StepAction {
38
39
 
39
40
  const result = {
40
41
  success: true,
41
- evaluatedText: evaluatedText,
42
- data: context.data
42
+ evaluatedText,
43
+ data: context.data,
43
44
  };
44
45
 
45
46
  resolve(result);
@@ -48,7 +49,6 @@ class EvaluateExpressionStepAction extends StepAction {
48
49
  }
49
50
  });
50
51
  }
51
-
52
52
  }
53
53
 
54
54
  module.exports = EvaluateExpressionStepAction;
@@ -86,18 +86,22 @@ class InputFileStepAction extends StepAction {
86
86
  const target = this.context.data[this.step.targetId || 'targetId'];
87
87
  const overrideAzureStorageUrl = featureFlagService.flags.overrideAzureStorageUrl.isEnabled();
88
88
  const useJsInputCodeInSafari = featureFlagService.flags.useJsInputCodeInSafari.isEnabled();
89
+ const useJsInputCodeInFirefox = featureFlagService.flags.useJsInputCodeInFirefox.isEnabled();
89
90
  const downloadToBase64 = featureFlagService.flags.downloadToBase64.isEnabled();
90
91
 
91
92
  let fileUrls = await utils.addTokenToFileUrl(this.context.project.id, this.step.fileUrls, this.stepActionUtils.testimServicesApi, overrideAzureStorageUrl, logger);
92
93
 
94
+
95
+ const isSafariJsInputCode = this.driver.isSafari() && (useJsInputCodeInSafari || fileUrls.length > 1);
96
+ const isFirefoxJsInputCode = this.driver.isFirefox() && (useJsInputCodeInFirefox || fileUrls.length > 1);
97
+
93
98
  if (downloadToBase64) {
94
99
  fileUrls = await Promise.all(fileUrls.map(async ({ name, url }) => {
95
100
  const res = await download(url);
96
101
  return { name, url: `data:${res.type};base64,${Buffer.from(res.body).toString('base64')}` };
97
102
  }));
98
103
  }
99
-
100
- if (this.driver.isSafari() && (useJsInputCodeInSafari || fileUrls.length > 1)) {
104
+ if (isSafariJsInputCode || isFirefoxJsInputCode) {
101
105
  await this.driver.executeJSWithArray(`
102
106
  const getLocatedElement = ${codeSnippets.getLocatedElementCode};
103
107
  const downloadAndUploadFile = ${downloadAndUpload()};
@@ -1,4 +1,6 @@
1
- "use strict";
1
+ /* globals getLocatedElement, dispatchFocus */
2
+
3
+ 'use strict';
2
4
 
3
5
  var doClick = function (eventData, done) {
4
6
  var eventConstructorSupported = typeof Event === 'function';
@@ -1,4 +1,6 @@
1
- "use strict";
1
+ /* global getLocatedElement */
2
+
3
+ 'use strict';
2
4
 
3
5
  var html5dndAction = function(eventData) {
4
6
  var data = {};
@@ -1,4 +1,6 @@
1
- "use strict";
1
+ /* global getLocatedElement */
2
+
3
+ 'use strict';
2
4
 
3
5
  var html5dndAction = function (eventData, done) {
4
6
  var mouseEventConstructorSupported = typeof MouseEvent === 'function';
@@ -3,23 +3,40 @@
3
3
  'use strict';
4
4
 
5
5
  const runCode = function (eventData, preCompiledCode) {
6
+ typeof Object.tstassign !== 'function' && (Object.tstassign = function (n, t) {
7
+ 'use strict';
6
8
 
7
- "function"!=typeof Object.tstassign&&(Object.tstassign=function(n,t){"use strict";if(null==n)throw new TypeError("Cannot convert undefined or null to object");for(var r=Object(n),e=1;e<arguments.length;e++){var o=arguments[e];if(null!=o)for(var a in o)Object.prototype.hasOwnProperty.call(o,a)&&(r[a]=o[a])}return r});
8
- Object.assign = typeof Object.assign !== "function" ? Object.tstassign : Object.assign;
9
+ if (n == null) throw new TypeError('Cannot convert undefined or null to object'); for (var r = Object(n), e = 1; e < arguments.length; e++) { var o = arguments[e]; if (o != null) for (var a in o)Object.prototype.hasOwnProperty.call(o, a) && (r[a] = o[a]); } return r;
10
+ });
11
+ Object.assign = typeof Object.assign !== 'function' ? Object.tstassign : Object.assign;
9
12
 
10
13
  function appendToStorage(name, data) {
11
14
  const sessionItem = 'data-testim-' + name;
15
+
16
+ const nativeFuncErrMsg = 'Native sessionStorage is not available';
17
+ function isNativeFunction(fn) {
18
+ if (!fn || !fn.toString) {
19
+ return false;
20
+ }
21
+ return fn.toString().indexOf('[native code]') > -1;
22
+ }
12
23
  try {
24
+ if (![window.sessionStorage.setItem, window.sessionStorage.getItem].every(isNativeFunction)) {
25
+ throw new Error(nativeFuncErrMsg);
26
+ }
13
27
  const oldData = JSON.parse(window.sessionStorage.getItem(sessionItem) || '{}');
14
28
  const newData = Object.tstassign({}, oldData, data);
15
29
  window.sessionStorage.setItem(sessionItem, JSON.stringify(newData));
16
30
  } catch (err) {
17
- // any vernation QuotaExceededError from browsers
31
+ // any variation QuotaExceededError from browsers
18
32
  const isQuotaExceededError = err.message.toLowerCase().indexOf('quota') > -1;
33
+ const isNativeFunctionError = err.message === nativeFuncErrMsg;
34
+
19
35
  if (err.message.indexOf('sessionStorage') > -1 || // Chrome + Firefox
20
36
  err.message.indexOf('The operation is insecure') > -1 || // Safari
21
37
  err.message.indexOf('SecurityError') > -1 || // Edge
22
- isQuotaExceededError
38
+ isQuotaExceededError ||
39
+ isNativeFunctionError
23
40
  ) {
24
41
  var storage = document.head.querySelector('#testim-storage-backup');
25
42
  if (!storage) {
@@ -30,13 +47,13 @@ const runCode = function (eventData, preCompiledCode) {
30
47
  const oldData = JSON.parse(storage.getAttribute(sessionItem) || '{}');
31
48
  const newData = Object.tstassign({}, oldData, data);
32
49
  storage.setAttribute(sessionItem, JSON.stringify(newData));
33
- if (isQuotaExceededError) {
50
+ if (isQuotaExceededError || isNativeFunctionError) {
34
51
  try {
35
52
  window.sessionStorage.removeItem(sessionItem);
36
53
  } catch (e) {
37
54
  // Prevents future retries from looking in sessionStorage with old data
38
55
  }
39
- window.TSTA.useFallbackStorage = true;
56
+ (window.TSTA = window.TSTA || {}).useFallbackStorage = true;
40
57
  }
41
58
  return;
42
59
  }
@@ -1,9 +1,4 @@
1
- // Disabling the eslint to keep this in a format which works on IE 11.
2
- /* eslint-disable no-var */
3
- /* eslint-disable no-redeclare */
4
- /* eslint-disable object-shorthand */
5
- /* eslint-disable one-var */
6
- /* eslint-disable operator-linebreak */
1
+ /* globals getLocatedElement, elementScrollTo */
7
2
 
8
3
  'use strict';
9
4
 
@@ -1,4 +1,7 @@
1
- "use strict";
1
+ /* globals getLocatedElement, dispatchFocus */
2
+
3
+ 'use strict';
4
+
2
5
  /*global KeyboardEvent */
3
6
  var setText = function (eventData, done) {
4
7
  var eventConstructorSupported = typeof Event === 'function';
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const Promise = require('bluebird');
4
- const utils = require('../../utils');
4
+ const pRetry = require('p-retry');
5
5
 
6
6
  class ScreenshotUtils {
7
7
  constructor(tabId, driver, options = { takeScreenshots: true }) {
@@ -29,7 +29,7 @@ class ScreenshotUtils {
29
29
  const SCREENSHOT_RETRY_DELAY = 2000;
30
30
  const devicePixelRatioPromise = this.currentDevicePixelRatio ? Promise.resolve(this.currentDevicePixelRatio) : this.getDevicePixelRatio();
31
31
  const getScreenshot = () => Promise.all([devicePixelRatioPromise, this.driver.takeScreenshot()]);
32
- return utils.runWithRetries(getScreenshot, MAX_RETRY_COUNT, SCREENSHOT_RETRY_DELAY)
32
+ return pRetry(getScreenshot, { retries: MAX_RETRY_COUNT, minTimeout: SCREENSHOT_RETRY_DELAY })
33
33
  .then(([devicePixelRatio, image]) => {
34
34
  const base64 = image ? image.value : '';
35
35
  const dataUrl = `data:image/png;base64,${this.base64AddPadding(base64.replace(/[\r\n]/g, ''))}`;
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const Promise = require('bluebird');
4
- const utils = require('../../utils');
4
+ const pRetry = require('p-retry');
5
5
  const { PageNotAvailableError } = require('../../errors');
6
6
  const logger = require('../../commons/logger').getLogger('window-utils');
7
7
 
@@ -152,12 +152,12 @@ WindowUtils.prototype.quit = function () {
152
152
  };
153
153
 
154
154
  WindowUtils.prototype.getOsAndBrowser = function () {
155
- return utils.runWithRetries(() => this.driver.getBrowserAndOS())
155
+ return pRetry(() => this.driver.getBrowserAndOS(), { retries: 3 })
156
156
  .then(osAndBrowser => ({ uaBrowserName: osAndBrowser.browser, uaOs: osAndBrowser.os, userAgent: osAndBrowser.userAgent, browserVersion: osAndBrowser.browserVersion }));
157
157
  };
158
158
 
159
159
  WindowUtils.prototype.getUserAgentInfo = function () {
160
- return utils.runWithRetries(() => this.driver.getUserAgentInfo());
160
+ return pRetry(() => this.driver.getUserAgentInfo(), { retries: 3 });
161
161
  };
162
162
 
163
163
  module.exports = WindowUtils;
@@ -1,6 +1,6 @@
1
1
  const os = require('os');
2
2
  const childProcess = require('child_process');
3
- const Promise = require('bluebird');
3
+ const pRetry = require('p-retry');
4
4
  const fse = require('fs-extra');
5
5
  const portfinder = require('portfinder');
6
6
  const ms = require('ms');
@@ -154,7 +154,7 @@ class LambdatestService {
154
154
 
155
155
  // verify that LT tunnel strated successfully
156
156
  try {
157
- const ltInfo = await utils.runWithRetries(() => httpRequest.get(`http://127.0.0.1:${infoAPIPort}/api/v1.0/info`, {}, {}, undefined, { skipProxy: true }), 30, 2000);
157
+ const ltInfo = await pRetry(() => httpRequest.get(`http://127.0.0.1:${infoAPIPort}/api/v1.0/info`, {}, {}, undefined, { skipProxy: true }), { retries: 30, minTimeout: 2000 });
158
158
  logger.info('LT tunnel info', ltInfo);
159
159
  } catch (err) {
160
160
  logger.error('Failed to start LT tunnel', { err, stdoutResult, stderrResult });
@@ -4,6 +4,7 @@ const httpRequest = require('../commons/httpRequest');
4
4
  const LambdatestService = require('./lambdatestService');
5
5
  const utils = require('../utils');
6
6
  const fse = require('fs-extra');
7
+ const { AbortError } = require('p-retry');
7
8
  const os = require('os');
8
9
  const childProcess = require('child_process');
9
10
  const EventEmitter = require('events');
@@ -312,7 +313,7 @@ describe('LambdatestService', () => {
312
313
  sinon.assert.calledOnce(httpGetStub);
313
314
  });
314
315
  it('should throw when tunnel did not start', async () => {
315
- sandbox.stub(utils, 'runWithRetries').rejects(new Error('tunnel did not start'));
316
+ httpGetStub.rejects(new AbortError('tunnel did not start'));
316
317
  await expect(LambdatestService.connectTunnel({ ...credentials })).to.be.rejectedWith(Error, 'tunnel did not start');
317
318
  processMock.stdout.emit('data', '');
318
319
  processMock.stderr.emit('data', '');
package/testRunHandler.js CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const pRetry = require('p-retry');
3
4
  const _ = require('lodash');
4
5
  const testimCustomToken = require('./commons/testimCustomToken');
5
6
  const remoteStepService = require('./commons/socket/remoteStepService');
@@ -312,12 +313,12 @@ class TestRun {
312
313
  const { sessionId: extensionSessionId } = extensionSession || {};
313
314
  perf.log('before Runtime.evaluate');
314
315
 
315
- await utils.runWithRetries(async () => {
316
+ await pRetry(async () => {
316
317
  const { result } = await cdpTestRunner.cdpCommand('Runtime.evaluate', { expression: 'typeof runTestimTest !== \'undefined\'', returnByValue: true }, extensionSessionId);
317
318
  if (!result.value) {
318
319
  throw new Error('runTestimTest not available on global scope');
319
320
  }
320
- }, 100, 30);
321
+ }, { retries: 100, minTimeout: 30 });
321
322
 
322
323
  perf.log('after wait for runTestimTest function');
323
324
  const { result } = await cdpTestRunner.cdpCommand(
package/testRunStatus.js CHANGED
@@ -17,7 +17,6 @@ const { calculateCoverage } = require('./coverage/jsCoverage');
17
17
  const featureAvailabilityService = require('./commons/featureAvailabilityService');
18
18
  const featureFlags = require('./commons/featureFlags');
19
19
  const { mapFilesToLocalDrive } = require('./services/localRCASaver');
20
- const { removeHiddenParamsInTestData } = require('./commons/testimServicesApi');
21
20
 
22
21
  const gitBranch = utils.getEnvironmentGitBranch();
23
22
  const gitCommit = process.env.GIT_COMMIT || process.env.CIRCLE_SHA1 || process.env.TRAVIS_COMMIT;
@@ -125,13 +124,6 @@ RunStatus.prototype.addRetryTestResult = async function ({
125
124
 
126
125
  this.testRunStatus[newResultId] = newTestResult;
127
126
 
128
- const { projectData } = this.options;
129
-
130
-
131
- if (newTestResult.config.testData) {
132
- newTestResult.config.testData = removeHiddenParamsInTestData(newTestResult.config.testData, projectData.defaults);
133
- }
134
-
135
127
  return servicesApi.addTestRetry({
136
128
  projectId,
137
129
  runId: executionId,
@@ -450,7 +442,8 @@ RunStatus.prototype.executionStart = function (executionId, projectId, startTime
450
442
  logger.error('Failed to start suite', { err });
451
443
  // eslint-disable-next-line no-console
452
444
  console.error('Failed to start test run. Please contact support@testim.io');
453
- }).return({ beforeTests, tests, afterTests });
445
+ })
446
+ .then(() => ({ beforeTests, tests, afterTests }));
454
447
  });
455
448
  };
456
449
 
package/utils.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const moment = require('moment');
4
- const retry = require('bluebird-retry');
4
+ const pRetry = require('p-retry');
5
5
  const _ = require('lodash');
6
6
  const Promise = require('bluebird');
7
7
  const fs = Promise.promisifyAll(require('fs'));
@@ -71,20 +71,16 @@ function getRunConfigByBrowserName(browser, saucelabs, browserstack) {
71
71
  return _.merge(selectedBrowser, selectedOS);
72
72
  }
73
73
 
74
- function handleAngularURIComponent(part) {
75
- return part.replace(/(~|\/)/g, m => ({ '~': '~~', '/': '~2F' }[m]));
76
- }
77
-
78
74
  function getTestUrl(editorUrl, projectId, testId, resultId, branch) {
79
75
  let testUrl = '';
80
- branch = branch ? handleAngularURIComponent(branch) : 'master';
76
+ branch = branch ? encodeURIComponent(branch) : 'master';
81
77
  if (projectId && testId) {
82
78
  testUrl = `${editorUrl}/#/project/${projectId}/branch/${branch}/test/${testId}`;
83
79
  if (resultId) {
84
80
  testUrl += `?result-id=${resultId}`;
85
81
  }
86
82
  }
87
- return encodeURI(testUrl);
83
+ return testUrl;
88
84
  }
89
85
 
90
86
  function isPromise(obj) {
@@ -100,17 +96,6 @@ function getDurationSec(ms) {
100
96
  return moment.duration(ms).asSeconds();
101
97
  }
102
98
 
103
- function runWithRetries(task, times, interval, predicate) {
104
- times = times || 3;
105
- interval = interval || 3000;
106
-
107
- const opt = { max_tries: times, interval, throw_original: true };
108
- if (predicate) {
109
- opt.predicate = predicate;
110
- }
111
- return retry(task, opt);
112
- }
113
-
114
99
  function getRunnerVersion() {
115
100
  try {
116
101
  const pack = require(`${__dirname}/package.json`);
@@ -247,7 +232,7 @@ function isURL(path) {
247
232
  }
248
233
 
249
234
  const DOWNLOAD_RETRY = 3;
250
- const download = async (url) => runWithRetries(() => httpRequest.download(url), DOWNLOAD_RETRY);
235
+ const download = async (url) => pRetry(() => httpRequest.download(url), { retries: DOWNLOAD_RETRY });
251
236
 
252
237
  const downloadAndSave = async (url, saveToLocation) => {
253
238
  const res = await download(url);
@@ -315,6 +300,16 @@ function getPlanType(plan) {
315
300
  return 'free';
316
301
  }
317
302
 
303
+ /**
304
+ * @param time {number} in ms
305
+ * @returns {Promise}
306
+ */
307
+ function delay(time) {
308
+ return new Promise(((resolve) => {
309
+ setTimeout(resolve, time);
310
+ }));
311
+ }
312
+
318
313
  const calcPercentile = (arr, percentile) => {
319
314
  if (arr.length === 0) return 0;
320
315
  if (typeof percentile !== 'number') throw new TypeError('p must be a number');
@@ -366,7 +361,6 @@ module.exports = {
366
361
  getTestUrl,
367
362
  getDuration,
368
363
  getDurationSec,
369
- runWithRetries,
370
364
  getRunnerVersion,
371
365
  getEnginesVersion,
372
366
  getEnginesVersionAsync,
@@ -395,4 +389,5 @@ module.exports = {
395
389
  isQuarantineAndNotRemoteRun,
396
390
  groupTestsByRetries,
397
391
  getPlanType,
392
+ delay,
398
393
  };
package/utils.test.js CHANGED
@@ -32,7 +32,7 @@ describe('utils', () => {
32
32
  expect(utils.getTestUrl('http://localhost:8080', 'project', 'test', 'result', 'normal-branch-name'))
33
33
  .to.equal('http://localhost:8080/#/project/project/branch/normal-branch-name/test/test?result-id=result');
34
34
  expect(utils.getTestUrl('http://localhost:8080', 'project', 'test', 'result', 'branch/with/slashes'))
35
- .to.equal('http://localhost:8080/#/project/project/branch/branch~2Fwith~2Fslashes/test/test?result-id=result');
35
+ .to.equal('http://localhost:8080/#/project/project/branch/branch%2Fwith%2Fslashes/test/test?result-id=result');
36
36
  expect(utils.getTestUrl('http://localhost:8080', 'project', 'test', 'result', 'branch with spaces'))
37
37
  .to.equal('http://localhost:8080/#/project/project/branch/branch%20with%20spaces/test/test?result-id=result');
38
38
  expect(utils.getTestUrl('http://localhost:8080', 'project', 'test', 'result', 'encoded%20branch'))
@@ -2,6 +2,7 @@
2
2
 
3
3
  const Bluebird = require('bluebird');
4
4
  const moment = require('moment');
5
+ const pRetry = require('p-retry');
5
6
  const ms = require('ms');
6
7
 
7
8
  const { timeoutMessages, testRunStatus, stepResult, runnerTestStatus } = require('../commons/constants');
@@ -116,7 +117,8 @@ class BaseWorker {
116
117
  try {
117
118
  perf.log('before getSlotOnce retries');
118
119
  let failedGetSlotAttempts = 0;
119
- let gridInfo = await utils.runWithRetries(async () => {
120
+
121
+ let gridInfo = await pRetry(async () => {
120
122
  const startTime = Date.now();
121
123
  try {
122
124
  return await Bluebird.resolve(this.getSlotOnce(testRunHandler))
@@ -124,10 +126,10 @@ class BaseWorker {
124
126
  } catch (error) {
125
127
  logger.error('error getting grid slot', { error, testId: this.testId, testResultId: this.testResultId, executionId: this.executionId });
126
128
  failedGetSlotAttempts++;
127
- await Bluebird.delay(this.options.getBrowserTimeout - (Date.now() - startTime));
129
+ await utils.delay(this.options.getBrowserTimeout - (Date.now() - startTime));
128
130
  throw error;
129
131
  }
130
- }, this.options.getBrowserRetries);
132
+ }, { retries: this.options.getBrowserRetries - 1, minTimeout: 0 });
131
133
  perf.log('after getSlotOnce retries');
132
134
 
133
135
  perf.log('before getBrowserOnce retries');
@@ -136,7 +138,7 @@ class BaseWorker {
136
138
  throw new Error('No free browser slots in desired grid');
137
139
  }
138
140
  let failedGetBrowserAttempts = 0;
139
- testPlayer = await utils.runWithRetries(async () => {
141
+ testPlayer = await pRetry(async () => {
140
142
  const startTime = Date.now();
141
143
  const player = this.initPlayer(testRunHandler);
142
144
  try {
@@ -162,11 +164,11 @@ class BaseWorker {
162
164
  player.onDone();
163
165
 
164
166
  if (!(error instanceof PageNotAvailableError)) {
165
- await Bluebird.delay(this.options.getBrowserTimeout - (Date.now() - startTime));
167
+ await utils.delay(this.options.getBrowserTimeout - (Date.now() - startTime));
166
168
  }
167
169
  throw error;
168
170
  }
169
- }, getBrowserRetriesNumber, undefined, (err) => !(err instanceof PageNotAvailableError));
171
+ }, { retries: getBrowserRetriesNumber - 1, minTimeout: 0 });
170
172
  perf.log('after getBrowserOnce retries');
171
173
  } catch (err) {
172
174
  await releasePlayer(this.id, this.releaseSlotOnTestFinished, projectId, testPlayer);
@@ -235,7 +237,7 @@ class BaseWorker {
235
237
  testResult.testRetryKey = testRetryKey;
236
238
  await this.onTestCompleted(this.id, this.testId, testResult, sessionId, shouldRerun);
237
239
  if (this.executionQueue.hasMoreTests() && !(this.options.lightweightMode && this.options.lightweightMode.general)) {
238
- await Bluebird.delay(DELAY_BETWEEN_TESTS);
240
+ await utils.delay(DELAY_BETWEEN_TESTS);
239
241
  }
240
242
  await this.runTestCleanup();
241
243
  if (shouldRerun) {
@@ -3,10 +3,9 @@ const proxyquire = require('proxyquire');
3
3
  const { expect, sinon } = require('../../test/utils/testUtils');
4
4
  const gridService = require('../services/gridService');
5
5
  const reporter = require('../reports/reporter');
6
- const Bluebird = require('bluebird');
7
6
  const { PageNotAvailableError, GridError, GetBrowserError } = require('../errors');
8
7
  const servicesApi = require('../commons/testimServicesApi');
9
- const { releasePlayer } = require('./workerUtils');
8
+ const utils = require('../utils');
10
9
 
11
10
 
12
11
  describe('BaseWorker', () => {
@@ -41,7 +40,7 @@ describe('BaseWorker', () => {
41
40
  getGridSlotStub = sinon.stub(gridService, 'getGridSlot').resolves({});
42
41
 
43
42
 
44
- sandbox.stub(Bluebird, 'delay').returns(Promise.resolve());
43
+ sandbox.stub(utils, 'delay').returns(Promise.resolve());
45
44
  sandbox.stub(reporter);
46
45
  });
47
46
 
@@ -57,7 +56,7 @@ describe('BaseWorker', () => {
57
56
  it('should get grid slot from server', async () => {
58
57
  await worker.getTestPlayer(testRunHandlerMock);
59
58
  sinon.assert.calledOnce(getGridSlotStub);
60
- sinon.assert.notCalled(Bluebird.delay);
59
+ sinon.assert.notCalled(utils.delay);
61
60
  });
62
61
  it('should retry getting slot until it succeeds', async () => {
63
62
  getGridSlotStub.onFirstCall().rejects();
@@ -65,7 +64,7 @@ describe('BaseWorker', () => {
65
64
 
66
65
  await worker.getTestPlayer(testRunHandlerMock);
67
66
  sinon.assert.calledTwice(getGridSlotStub);
68
- sinon.assert.calledTwice(Bluebird.delay);
67
+ sinon.assert.calledOnce(utils.delay);
69
68
  });
70
69
  it('should not proceed to getting browser if all retries used for getting a slot', async () => {
71
70
  getGridSlotStub.resolves({});
@@ -74,7 +73,7 @@ describe('BaseWorker', () => {
74
73
  sinon.assert.calledOnce(getGridSlotStub);
75
74
  sinon.assert.notCalled(worker.getBrowserOnce);
76
75
  sinon.assert.notCalled(worker.initPlayer);
77
- sinon.assert.notCalled(Bluebird.delay);
76
+ sinon.assert.notCalled(utils.delay);
78
77
  });
79
78
  });
80
79
 
@@ -84,7 +83,7 @@ describe('BaseWorker', () => {
84
83
  sinon.assert.calledOnce(getGridSlotStub);
85
84
  sinon.assert.calledOnce(worker.getBrowserOnce);
86
85
  sinon.assert.calledOnce(worker.initPlayer);
87
- sinon.assert.notCalled(Bluebird.delay);
86
+ sinon.assert.notCalled(utils.delay);
88
87
  });
89
88
  it('should retry getting browser until it succeeds', async () => {
90
89
  worker.getBrowserOnce.onFirstCall().rejects();
@@ -95,16 +94,16 @@ describe('BaseWorker', () => {
95
94
  sinon.assert.calledTwice(worker.getBrowserOnce);
96
95
  sinon.assert.calledTwice(worker.initPlayer);
97
96
  sinon.assert.calledOnce(testPlayerMock.onDone);
98
- sinon.assert.calledTwice(Bluebird.delay);
97
+ sinon.assert.calledOnce(utils.delay);
99
98
  });
100
99
  it('should not retry if page is not available', async () => {
101
100
  worker.getBrowserOnce.throws(() => new PageNotAvailableError());
102
101
 
103
- await expect(worker.getTestPlayer(testRunHandlerMock)).to.eventually.be.rejectedWith(PageNotAvailableError);
102
+ await expect(worker.getTestPlayer(testRunHandlerMock)).to.eventually.be.rejectedWith(Error);
104
103
  sinon.assert.calledOnce(getGridSlotStub);
105
104
  sinon.assert.calledOnce(worker.getBrowserOnce);
106
105
  sinon.assert.calledOnce(testPlayerMock.onDone);
107
- sinon.assert.notCalled(Bluebird.delay);
106
+ sinon.assert.notCalled(utils.delay);
108
107
  });
109
108
  it('should handle get grid error', async () => {
110
109
  worker.getBrowserOnce.throws(() => new GridError());
@@ -153,8 +152,8 @@ describe('BaseWorker', () => {
153
152
  getHybridGridProviderStub.onFirstCall().resolves({ provider: 'loacker', connectionDetails: { host: 'localhost', external: { user: 'user', key: 'password' } } });
154
153
  getHybridGridProviderStub.onSecondCall().resolves({ provider: 'nitzan', connectionDetails: { host: 'google.com', port: 443 } });
155
154
  getHybridGridProviderStub.onThirdCall().resolves({ provider: 'a', connectionDetails: { host: 'google.com', port: 4444 } });
156
- worker.getBrowserOnce.onFirstCall().rejects();
157
- worker.getBrowserOnce.onSecondCall().rejects();
155
+ worker.getBrowserOnce.onFirstCall().rejects(new Error());
156
+ worker.getBrowserOnce.onSecondCall().rejects(new Error());
158
157
  worker.getBrowserOnce.onThirdCall().resolves({});
159
158
 
160
159
  await worker.getTestPlayer(testRunHandlerMock);