@testim/testim-cli 3.253.0 → 3.255.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 (103) hide show
  1. package/OverrideTestDataBuilder.js +1 -1
  2. package/agent/routers/cliJsCode/index.js +4 -4
  3. package/agent/routers/cliJsCode/router.js +46 -42
  4. package/agent/routers/cliJsCode/service.js +18 -13
  5. package/agent/routers/codim/router.js +14 -17
  6. package/agent/routers/codim/router.test.js +19 -21
  7. package/agent/routers/codim/service.js +16 -16
  8. package/agent/routers/general/index.js +4 -8
  9. package/agent/routers/hybrid/registerRoutes.js +18 -18
  10. package/agent/routers/index.js +7 -7
  11. package/agent/routers/playground/router.js +11 -10
  12. package/agent/routers/playground/service.js +22 -23
  13. package/agent/routers/standalone-browser/registerRoutes.js +10 -10
  14. package/cdpTestRunner.js +4 -3
  15. package/chromiumInstaller.js +4 -5
  16. package/cli/onExit.js +2 -2
  17. package/cli.js +11 -10
  18. package/cliAgentMode.js +8 -8
  19. package/codim/codim-cli.js +20 -17
  20. package/codim/hybrid-utils.js +1 -1
  21. package/codim/measure-perf.js +9 -6
  22. package/codim/template.js/tests/examples/01-simple-text-validation.test.js +6 -6
  23. package/codim/template.js/tests/examples/02-using-locators.test.js +13 -15
  24. package/codim/template.js/tests/examples/03-using-hooks.test.js +17 -19
  25. package/codim/template.js/tests/examples/04-skip-and-only.test.js +16 -17
  26. package/codim/template.js/tests/examples/05-multiple-windows.test.js +16 -17
  27. package/codim/template.js/webpack.config.js +1 -1
  28. package/codim/template.ts/webpack.config.js +3 -3
  29. package/commons/AbortError.js +4 -4
  30. package/commons/detectDebugger.js +4 -2
  31. package/commons/featureFlags.js +8 -0
  32. package/commons/httpRequest.js +5 -1
  33. package/commons/httpRequestCounters.js +21 -10
  34. package/commons/lazyRequire.js +14 -12
  35. package/commons/logger.js +4 -4
  36. package/commons/performance-logger.js +14 -8
  37. package/commons/preloadTests.js +2 -2
  38. package/commons/prepareRunner.js +4 -2
  39. package/commons/prepareRunnerAndTestimStartUtils.js +40 -42
  40. package/commons/runnerFileCache.js +1 -1
  41. package/commons/socket/baseSocketServiceSocketIO.js +32 -34
  42. package/commons/socket/realDataService.js +6 -5
  43. package/commons/socket/realDataServiceSocketIO.js +4 -4
  44. package/commons/socket/remoteStepService.js +4 -3
  45. package/commons/socket/remoteStepServiceSocketIO.js +11 -12
  46. package/commons/socket/socketService.js +50 -52
  47. package/commons/socket/testResultServiceSocketIO.js +11 -11
  48. package/commons/testimDesiredCapabilitiesBuilder.js +3 -2
  49. package/commons/testimNgrok.js +2 -2
  50. package/commons/testimNgrok.test.js +1 -1
  51. package/commons/testimServicesApi.js +27 -20
  52. package/commons/testimTunnel.test.js +2 -1
  53. package/commons/xhr2.js +97 -100
  54. package/coverage/SummaryToObjectReport.js +0 -1
  55. package/coverage/jsCoverage.js +12 -10
  56. package/errors.js +5 -0
  57. package/fixLocalBuild.js +2 -0
  58. package/inputFileUtils.js +11 -9
  59. package/npm-shrinkwrap.json +2286 -1284
  60. package/package.json +9 -8
  61. package/player/appiumTestPlayer.js +1 -1
  62. package/player/chromeLauncherTestPlayer.js +0 -1
  63. package/player/services/tabService.js +15 -1
  64. package/player/services/tabServiceMock.js +166 -0
  65. package/player/stepActions/locateStepAction.js +2 -0
  66. package/player/stepActions/navigationStepAction.js +11 -10
  67. package/player/stepActions/sleepStepAction.js +4 -5
  68. package/player/stepActions/textStepAction.js +4 -11
  69. package/player/utils/imageCaptureUtils.js +81 -120
  70. package/player/utils/windowUtils.js +4 -3
  71. package/player/webdriver.js +26 -23
  72. package/processHandler.js +3 -3
  73. package/processHandler.test.js +1 -1
  74. package/reports/consoleReporter.js +3 -2
  75. package/reports/junitReporter.js +7 -9
  76. package/reports/reporter.js +34 -39
  77. package/runOptions.d.ts +260 -0
  78. package/runOptions.js +59 -44
  79. package/runner.js +14 -0
  80. package/runners/ParallelWorkerManager.js +9 -10
  81. package/runners/TestPlanRunner.js +142 -78
  82. package/runners/buildCodeTests.js +38 -37
  83. package/runners/runnerUtils.js +3 -3
  84. package/services/gridService.js +36 -40
  85. package/services/lambdatestService.js +3 -5
  86. package/stepPlayers/cliJsStepPlayback.js +22 -17
  87. package/testRunHandler.js +8 -0
  88. package/testRunStatus.js +9 -6
  89. package/utils/argsUtils.js +86 -0
  90. package/utils/argsUtils.test.js +32 -0
  91. package/utils/fsUtils.js +154 -0
  92. package/{utils.js → utils/index.js} +19 -262
  93. package/utils/promiseUtils.js +89 -0
  94. package/utils/stringUtils.js +98 -0
  95. package/utils/stringUtils.test.js +22 -0
  96. package/utils/timeUtils.js +25 -0
  97. package/utils/utils.test.js +27 -0
  98. package/workers/BaseWorker.js +16 -14
  99. package/workers/WorkerAppium.js +1 -1
  100. package/workers/WorkerExtension.js +6 -7
  101. package/workers/WorkerExtensionSingleBrowser.js +4 -4
  102. package/workers/WorkerSelenium.js +5 -2
  103. package/utils.test.js +0 -68
@@ -1,7 +1,10 @@
1
+ // @ts-check
2
+
1
3
  'use strict';
2
4
 
3
- const Promise = require('bluebird');
5
+ const _ = require('lodash');
4
6
  const Jimp = require('jimp');
7
+ const utils = require('../../utils');
5
8
 
6
9
  const logger = require('../../commons/logger').getLogger('image-capture-utils');
7
10
 
@@ -13,22 +16,27 @@ class RectIsOutsideOfImageError extends Error {
13
16
  }
14
17
  }
15
18
 
19
+ /**
20
+ * @param {never} tabId
21
+ * @param {import('./windowUtils')} windowUtils
22
+ * @param {import('./screenshotUtils')} screenshotUtils
23
+ * */
16
24
  const ImageCaptureUtils = function (tabId, windowUtils, screenshotUtils) {
17
25
  this.windowUtils = windowUtils;
18
26
  this.screenshotUtils = screenshotUtils;
19
27
  };
20
28
 
21
- function cropImageFromImageData(imageData, imageInfo) {
22
- const image = imageInfo.image || imageInfo;
29
+ async function cropImageFromImageData(imageData, imageInfo) {
30
+ const _image = imageInfo.image || imageInfo;
23
31
  const pixelRatio = imageInfo.devicePixelRatio;
24
32
 
25
- if (!image) {
26
- return Promise.reject(new Error('Failed to get image'));
33
+ if (!_image) {
34
+ throw new Error('Failed to get image');
27
35
  }
28
36
 
29
- const imageRegExMatch = image.match(/^data\:[^;]*\;base64,(.*)$/);
37
+ const imageRegExMatch = _image.match(/^data\:[^;]*\;base64,(.*)$/);
30
38
  if (!imageRegExMatch) {
31
- return Promise.reject(new Error('Image is not in base64 format'));
39
+ throw new Error('Image is not in base64 format');
32
40
  }
33
41
 
34
42
  // chromeCropImage2
@@ -39,102 +47,67 @@ function cropImageFromImageData(imageData, imageInfo) {
39
47
 
40
48
  // elementImage
41
49
  if (!imageData.elementRect) {
42
- const { image, ...rest } = imageData;
43
- logger.warn('missing elementRect', { ...rest });
44
- return Promise.resolve({});
50
+ logger.warn('missing elementRect', _.omit(imageData, 'image'));
51
+ return {};
45
52
  }
46
53
 
47
54
  const { elementRect } = imageData;
48
- return new Promise((resolve, reject) => {
49
- Jimp.read(Buffer.from(imageRegExMatch[1], 'base64'), (err, image) => {
50
- if (err) {
51
- return reject(err);
52
- }
53
- try {
54
- let x = elementRect.left * pixelRatio + offset.left * pixelRatio;
55
- let y = elementRect.top * pixelRatio + offset.top * pixelRatio;
56
- let width = elementRect.width * pixelRatio;
57
- let height = elementRect.height * pixelRatio;
58
-
59
- if (x < 0) {
60
- width += x;
61
- width = width < 0 ? 0 : width;
62
- x = 0;
63
- }
55
+ const image = await Jimp.read(Buffer.from(imageRegExMatch[1], 'base64'));
56
+ let x = elementRect.left * pixelRatio + offset.left * pixelRatio;
57
+ let y = elementRect.top * pixelRatio + offset.top * pixelRatio;
58
+ let width = elementRect.width * pixelRatio;
59
+ let height = elementRect.height * pixelRatio;
60
+
61
+ if (x < 0) {
62
+ width += x;
63
+ width = width < 0 ? 0 : width;
64
+ x = 0;
65
+ }
64
66
 
65
- if (y < 0) {
66
- height += y;
67
- height = height < 0 ? 0 : height;
68
- y = 0;
69
- }
67
+ if (y < 0) {
68
+ height += y;
69
+ height = height < 0 ? 0 : height;
70
+ y = 0;
71
+ }
70
72
 
71
- const imageWidth = image.bitmap.width;
72
- const imageHeight = image.bitmap.height;
73
- if ((x + width) > imageWidth) {
74
- width = imageWidth - x;
75
- }
73
+ const imageWidth = image.bitmap.width;
74
+ const imageHeight = image.bitmap.height;
75
+ if ((x + width) > imageWidth) {
76
+ width = imageWidth - x;
77
+ }
76
78
 
77
- if ((y + height) > imageHeight) {
78
- height = imageHeight - y;
79
- }
79
+ if ((y + height) > imageHeight) {
80
+ height = imageHeight - y;
81
+ }
80
82
 
81
- if (height <= 0 || width <= 0) {
82
- reject(new RectIsOutsideOfImageError('height or width is equal or lower than zero'));
83
- return undefined;
84
- }
83
+ if (height <= 0 || width <= 0) {
84
+ throw new RectIsOutsideOfImageError('height or width is equal or lower than zero');
85
+ }
85
86
 
86
- const cImage = image.crop(x, y, width, height);
87
- cImage.getBase64(Jimp.MIME_PNG, (err, base64) => {
88
- if (err) {
89
- return reject(err);
90
- }
91
- resolve({
92
- elementImage: base64,
93
- });
94
- return undefined;
95
- });
96
- return undefined;
97
- } catch (err) {
98
- return reject(err);
99
- }
100
- });
101
- });
87
+ const cImage = image.crop(x, y, width, height);
88
+ const base64 = await cImage.getBase64Async(Jimp.MIME_PNG);
89
+ return { elementImage: base64 };
102
90
  }
103
91
 
104
-
105
- function chromeStitchImage(fullSize, parts) {
106
- return new Promise((resolve, reject) => {
107
- new Jimp(fullSize.width, fullSize.height, ((err, fullImage) => {
108
- if (err) {
109
- reject(err);
110
- return undefined;
111
- }
112
- return Promise.each(parts, part => new Promise((resolve, reject) => {
113
- const imageRegExMatch = part.image.match(/^data\:[^;]*\;base64,(.*)$/);
114
- Jimp.read(Buffer.from(imageRegExMatch[1], 'base64'), (err, partImage) => {
115
- if (err) {
116
- return reject(err);
117
- }
118
- fullImage.composite(partImage, part.position.left, part.position.top, (err, image) => {
119
- if (err) {
120
- return reject(err);
121
- }
122
- resolve(image);
123
- return undefined;
124
- });
125
- return undefined;
126
- });
127
- })).then(() => {
128
- fullImage.getBase64(Jimp.MIME_PNG, (err, base64) => {
129
- if (err) {
130
- return reject(err);
131
- }
132
- resolve(base64);
133
- return undefined;
134
- });
92
+ async function chromeStitchImage(fullSize, parts) {
93
+ const fullImage = await Jimp.read(fullSize.width, fullSize.height);
94
+
95
+ for (const part of parts) {
96
+ const imageRegExMatch = part.image.match(/^data\:[^;]*\;base64,(.*)$/);
97
+ const partImage = await Jimp.read(Buffer.from(imageRegExMatch[1], 'base64'));
98
+ // From the code or types doesn't seem like `fullImage.composite` has an async Promise API
99
+ await new Promise((resolve, reject) => {
100
+ fullImage.composite(partImage, part.position.left, part.position.top, (err) => {
101
+ if (err) {
102
+ reject(err);
103
+ return;
104
+ }
105
+ resolve();
135
106
  });
136
- }));
137
- });
107
+ });
108
+ }
109
+ const base64 = await fullImage.getBase64Async(Jimp.MIME_PNG);
110
+ return base64;
138
111
  }
139
112
 
140
113
  function stitchImage(fullSize, parts) {
@@ -194,10 +167,8 @@ ImageCaptureUtils.prototype = {
194
167
  return this.screenshotUtils.takeScreenshot(format)
195
168
  .then((imageInfo) => cropImageFromImageData(areas, imageInfo).then((result) => {
196
169
  result.screenImage = imageInfo.image;
197
- result.absoluteScreenHighlight = getElementAbsoluteRectangle(
198
- areas.elementRect,
199
- imageInfo.devicePixelRatio);
200
- return Promise.resolve(result);
170
+ result.absoluteScreenHighlight = getElementAbsoluteRectangle(areas.elementRect, imageInfo.devicePixelRatio);
171
+ return result;
201
172
  }));
202
173
  },
203
174
 
@@ -211,10 +182,8 @@ ImageCaptureUtils.prototype = {
211
182
  .then((imageInfo) => {
212
183
  const result = {};
213
184
  result.screenImage = imageInfo.image;
214
- result.absoluteScreenHighlight = getElementAbsoluteRectangle(
215
- areas.elementRect,
216
- imageInfo.devicePixelRatio);
217
- return Promise.resolve(result);
185
+ result.absoluteScreenHighlight = getElementAbsoluteRectangle(areas.elementRect, imageInfo.devicePixelRatio);
186
+ return result;
218
187
  }).then(uploadAllDataUrls);
219
188
  },
220
189
 
@@ -226,14 +195,12 @@ ImageCaptureUtils.prototype = {
226
195
  return this.screenshotUtils.getCurrentDevicePixelRatio();
227
196
  },
228
197
 
229
- takeStitchedDataUrl(useImprovedScreenshotStitching) {
198
+ async takeStitchedDataUrl(useImprovedScreenshotStitching) {
230
199
  const windowUtil = this.windowUtils;
231
200
  const getCurrentScrollPosition = windowUtil.getCurrentScrollPosition.bind(windowUtil);
232
201
 
233
202
  const that = this;
234
- const stabilize = () => new Promise(resolve => {
235
- setTimeout(resolve, 250);
236
- });
203
+ const stabilize = () => utils.delay(250);
237
204
  const usingImprovedStitching = Boolean(useImprovedScreenshotStitching);
238
205
  const scroll = usingImprovedStitching ?
239
206
  (pos) => windowUtil.scrollToPositionWithoutAnimation.bind(windowUtil)(pos) :
@@ -243,12 +210,7 @@ ImageCaptureUtils.prototype = {
243
210
  return scroll(position)
244
211
  .then(stabilize)
245
212
  .then(() => that.screenshotUtils.takeScreenshot())
246
- .then(imageInfo => {
247
- const imageData = {
248
- elementRect: crop,
249
- };
250
- return cropImageFromImageData(imageData, imageInfo);
251
- })
213
+ .then(imageInfo => cropImageFromImageData({ elementRect: crop }, imageInfo))
252
214
  .then(cropResult => ({
253
215
  position: { left: position.x + crop.left, top: position.y + crop.top },
254
216
  size: { width: crop.width, height: crop.height },
@@ -256,13 +218,13 @@ ImageCaptureUtils.prototype = {
256
218
  }));
257
219
  }
258
220
 
259
- function takeAllParts(positionsData) {
260
- const takeAllPartsPromises = positionsData.reduce(function (allParts, nextPos) {
261
- const lastPart = allParts[allParts.length - 1];
262
- allParts.push(lastPart.then(createPart.bind(this, nextPos.scrollPos, nextPos.cropData)));
263
- return allParts;
264
- }, [Promise.resolve()]);
265
- return Promise.all(takeAllPartsPromises);
221
+ async function takeAllParts(positionsData) {
222
+ const allParts = [];
223
+ for (const nextPos of positionsData) {
224
+ const part = await createPart(nextPos.scrollPos, nextPos.cropData);
225
+ allParts.push(part);
226
+ }
227
+ return allParts;
266
228
  }
267
229
 
268
230
  function getPartsPositions(fullPageSize, viewPortSize) {
@@ -294,12 +256,11 @@ ImageCaptureUtils.prototype = {
294
256
  const positions = getPartsPositions(fullPageSize, viewPortSize);
295
257
  const parts = await takeAllParts(positions);
296
258
  await windowUtil.scrollToPosition(originalPosition);
297
- parts.shift();
298
259
  return stitchImage(fullPageSize, parts);
299
260
  }
300
261
 
301
- return Promise.all([windowUtil.getFullPageSize(), windowUtil.getViewportSize()])
302
- .then(([fullPageSize, viewPortSize]) => createStitchImage(fullPageSize, viewPortSize));
262
+ const [fullPageSize, viewPortSize] = await Promise.all([windowUtil.getFullPageSize(), windowUtil.getViewportSize()]);
263
+ return await createStitchImage(fullPageSize, viewPortSize);
303
264
  },
304
265
  };
305
266
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  const Promise = require('bluebird');
4
4
  const pRetry = require('p-retry');
5
+ const { delay } = require('../../utils');
5
6
  const { PageNotAvailableError } = require('../../errors');
6
7
  const logger = require('../../commons/logger').getLogger('window-utils');
7
8
 
@@ -72,7 +73,7 @@ class WindowUtils {
72
73
  const shouldRetryNavigation = err.seleniumStack && err.message.includes('method IWebBrowser2::Navigate2() failed');
73
74
  if (shouldRetryNavigation && retries > 0) {
74
75
  logger.warn('selenium navigation failed. retrying to navigate', { err });
75
- await Promise.delay(1500);
76
+ await delay(1500);
76
77
  return navigate(retries - 1);
77
78
  }
78
79
  throw err;
@@ -80,13 +81,13 @@ class WindowUtils {
80
81
  return undefined;
81
82
  }
82
83
 
83
- return Promise.race([navigate(), Promise.delay(NAVIGATION_MAX_TIME)]);
84
+ return Promise.race([navigate(), delay(NAVIGATION_MAX_TIME)]);
84
85
  }
85
86
 
86
87
  reloadTab(timeoutMSec = 15000) {
87
88
  return Promise.race([
88
89
  this.driver.reloadTab(),
89
- Promise.delay(timeoutMSec),
90
+ delay(timeoutMSec),
90
91
  ]);
91
92
  }
92
93
 
@@ -1,9 +1,9 @@
1
- /* eslint-disable no-var */
1
+ /* eslint-disable arrow-body-style, no-shadow, @typescript-eslint/prefer-optional-chain, comma-spacing, no-empty, padded-blocks, semi, indent, unicorn/no-useless-promise-resolve-reject, default-param-last, comma-dangle, semi-style, consistent-return, radix, prefer-template, prefer-const, object-shorthand, no-trailing-spaces, operator-linebreak, no-else-return, unicorn/prefer-includes, prefer-arrow-callback, max-len, no-var */
2
2
 
3
3
  'use strict';
4
4
 
5
+ const _ = require('lodash');
5
6
  const logger = require('../commons/logger').getLogger('webdriver');
6
- const Promise = require('bluebird');
7
7
  const parser = require('ua-parser-js');
8
8
  const desiredCapabilitiesBuilder = require('../commons/testimDesiredCapabilitiesBuilder');
9
9
  const { SeleniumError, SeleniumCrashError, IeError } = require('../errors');
@@ -13,7 +13,7 @@ const doubleClick = require('./stepActions/scripts/doubleClick');
13
13
  const dispatchFocus = require('./stepActions/scripts/focusElement');
14
14
  const { isOldProtocol } = require('./webDriverUtils');
15
15
  const featureFlags = require('../commons/featureFlags');
16
- const _ = require('lodash');
16
+ const { W3C_ELEMENT_ID } = require('./constants');
17
17
 
18
18
  const [LEFT, RIGHT] = [0, 2];
19
19
  const { extractElementId, getCdpAddressForHost } = utils;
@@ -93,7 +93,7 @@ class WebDriver extends WebDriverApi {
93
93
  this.cdpUrl = await getCdpAddress(initResult);
94
94
  perf.log('after getCdpAddress in webdriver.js init');
95
95
  logger.info(`init new session testName: ${testName}`, { sessionId: this.getSessionId(), testResultId });
96
- await Promise.delay(driverDelay);
96
+ await utils.delay(driverDelay);
97
97
  await focus();
98
98
  perf.log('after focus and delay in webdriver.js init');
99
99
  } catch (err) {
@@ -202,7 +202,8 @@ class WebDriver extends WebDriverApi {
202
202
  switchToLocatedFrame(locatedElement) {
203
203
  return this.getElement(locatedElement)
204
204
  .then(async el => {
205
- await this.switchToFrame(el.value);
205
+ const elementId = extractElementId(el.value);
206
+ await this.switchToFrame({ ELEMENT: elementId, [W3C_ELEMENT_ID]: elementId });
206
207
  return el;
207
208
  });
208
209
  }
@@ -213,7 +214,7 @@ class WebDriver extends WebDriverApi {
213
214
 
214
215
  switchToTopFrame() {
215
216
  return this.frame().catch(err => {
216
- if (err.message && err.message.includes('ECONNREFUSED')) {
217
+ if (err.message?.includes('ECONNREFUSED')) {
217
218
  throw new SeleniumCrashError();
218
219
  }
219
220
  throw err;
@@ -221,11 +222,11 @@ class WebDriver extends WebDriverApi {
221
222
  }
222
223
 
223
224
  /**
224
- * @returns {Promise<{ value: HTMLElement }>}
225
+ * @returns {Promise<{ value: HTMLElement | { [W3C_ELEMENT_ID]: string } | { ELEMENT: string } }>}
225
226
  */
226
227
  getElement(locatedElement) {
227
228
  const perfId = this.seleniumPerfStats.markStart(SELENIUM_PERF_MARKS.GET_ELEMENT);
228
- if (typeof locatedElement === 'string' || typeof locatedElement === 'number') { // support testimId in the meanwhile for backwards compatability
229
+ if (typeof locatedElement === 'string' || typeof locatedElement === 'number') { // support testimId in the meanwhile for backwards compatibility
229
230
  return this.getElementBySelector(`[testim_dom_element_id='${locatedElement}']`)
230
231
  .finally(() => this.seleniumPerfStats.markEnd(perfId, SELENIUM_PERF_MARKS.GET_ELEMENT));
231
232
  }
@@ -452,10 +453,10 @@ class WebDriver extends WebDriverApi {
452
453
  throw testimInternalError;
453
454
  }
454
455
  return this.executeJS('return navigator.userAgent;')
455
- .catch(() => Promise.reject(testimInternalError))
456
+ .catch(() => { throw testimInternalError; })
456
457
  .then(ua => {
457
458
  const error = this.isUsingUnsupportedCompabilityMode(ua.value) ? this.getIeError('Can’t run test in IE compatibility mode') : testimInternalError;
458
- return Promise.reject(error);
459
+ throw error;
459
460
  });
460
461
  });
461
462
  }
@@ -586,7 +587,7 @@ class WebDriver extends WebDriverApi {
586
587
  userAgent: rawUserAgent,
587
588
  browserVersion: parse.browser.version
588
589
  };
589
- return Promise.resolve(this.browserAndOS);
590
+ return this.browserAndOS;
590
591
  });
591
592
  }
592
593
 
@@ -690,7 +691,7 @@ class WebDriver extends WebDriverApi {
690
691
  this.unsupportedActions.move = true;
691
692
  return this.rightClickWithActionsAPI(element, offsets);
692
693
  }
693
- return Promise.reject(err);
694
+ throw err;
694
695
  });
695
696
  }
696
697
 
@@ -704,7 +705,7 @@ class WebDriver extends WebDriverApi {
704
705
  this.unsupportedActions.move = true;
705
706
  return this.leftClickWithActionsAPI(element, offsets);
706
707
  }
707
- return Promise.reject(err);
708
+ throw err;
708
709
  });
709
710
  }
710
711
 
@@ -826,7 +827,7 @@ class WebDriver extends WebDriverApi {
826
827
  this.unsupportedActions.move = true;
827
828
  return this.dragWithActionsAPI(seleniumElement, xDiff, yDiff, midXRelative, midYRelative);
828
829
  }
829
- return Promise.reject(err);
830
+ throw err;
830
831
  });
831
832
  });
832
833
  }
@@ -857,15 +858,17 @@ class WebDriver extends WebDriverApi {
857
858
  }, [{ x: Math.round(startLeft), y: Math.round(startTop) }]);
858
859
  }
859
860
 
860
- dragAndDropWithGeneratedMoves(sourceSeleniumElement, destinationSeleniumElement, rectsAndOffsets) {
861
+ async dragAndDropWithGeneratedMoves(sourceSeleniumElement, destinationSeleniumElement, rectsAndOffsets) {
861
862
  const { fromRect, fromX, fromY, toRect, toX, toY } = rectsAndOffsets;
862
863
  const moveSequence = this.getMoveRelativeSequence(fromRect.left + fromX, fromRect.top + fromY, toRect.left + toX, toRect.top + toY);
863
864
 
864
- return this.moveTo(extractElementId(sourceSeleniumElement), Math.round(fromX), Math.round(fromY))
865
- .then(() => this.buttonDown())
866
- .then(() => Promise.each(moveSequence, movePosition => this.moveTo(null, movePosition.x, movePosition.y)))
867
- .then(() => this.moveTo(extractElementId(destinationSeleniumElement), Math.round(toX), Math.round(toY)))
868
- .then(() => this.buttonUp());
865
+ await this.moveTo(extractElementId(sourceSeleniumElement), Math.round(fromX), Math.round(fromY));
866
+ await this.buttonDown();
867
+ for (const movePosition of moveSequence) {
868
+ await this.moveTo(null, movePosition.x, movePosition.y);
869
+ }
870
+ await this.moveTo(extractElementId(destinationSeleniumElement), Math.round(toX), Math.round(toY));
871
+ return await this.buttonUp();
869
872
  }
870
873
 
871
874
  dragAndDropWithActionsAPIWithGeneratedMoves(rectsAndOffsets) {
@@ -900,7 +903,7 @@ class WebDriver extends WebDriverApi {
900
903
  this.unsupportedActions.move = true;
901
904
  return this.dragAndDropWithActionsAPIWithGeneratedMoves(rectsAndOffsets);
902
905
  }
903
- return Promise.reject(err);
906
+ throw err;
904
907
  });
905
908
  }
906
909
  if (this.unsupportedActions.move) {
@@ -912,7 +915,7 @@ class WebDriver extends WebDriverApi {
912
915
  this.unsupportedActions.move = true;
913
916
  return this.dragAndDropWithActionsAPI(rectsAndOffsets);
914
917
  }
915
- return Promise.reject(err);
918
+ throw err;
916
919
  });
917
920
  }
918
921
 
@@ -934,7 +937,7 @@ class WebDriver extends WebDriverApi {
934
937
  this.unsupportedActions.move = true;
935
938
  return this.doubleClickFallback(element, eventData, offsets);
936
939
  }
937
- return Promise.reject(err);
940
+ throw err;
938
941
  });
939
942
  }
940
943
 
package/processHandler.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  'use strict';
4
4
 
5
- const Promise = require('bluebird');
5
+ const { promiseTimeout, promiseMap } = require('./utils');
6
6
  const logger = require('./commons/logger').getLogger('process-handler');
7
7
 
8
8
  const exitHooks = [];
@@ -10,7 +10,7 @@ const exitHooks = [];
10
10
  module.exports = function (onExit, _process = process) {
11
11
  async function cleanup(err) {
12
12
  // give cleanup and socket reports a chance to run
13
- await Promise.all(exitHooks.map(x => x())).timeout(10000).catch(() => {});
13
+ await promiseTimeout(promiseMap(exitHooks, hook => hook()), 10000).catch(() => null);
14
14
  onExit(err);
15
15
  }
16
16
  _process.on('uncaughtException', async (err) => {
@@ -29,7 +29,7 @@ module.exports = function (onExit, _process = process) {
29
29
  // rollout manages promises incorrectly and generates unhandled rejections from within their code
30
30
  logger.fatal('Caught unhandled promise rejection', reason);
31
31
  //TODO(benji) - this is a pretty shitty way to detect this error since rollout can change their API endpoint
32
- if (reason && reason.message && reason.message.includes('ENOTFOUND x-api.rollout.io')) {
32
+ if (reason?.message?.includes('ENOTFOUND x-api.rollout.io')) {
33
33
  // this is not a fatal error - we recover from this in feature-flags service
34
34
  return;
35
35
  }
@@ -1,5 +1,5 @@
1
1
 
2
- const { delay } = require('bluebird');
2
+ const { delay } = require('./utils');
3
3
  const EventEmitter = require('events');
4
4
  const { expect, sinon } = require('../test/utils/testUtils');
5
5
  const processHandler = require('./processHandler');
@@ -2,7 +2,7 @@
2
2
  const chalk = require('chalk');
3
3
  const _ = require('lodash');
4
4
 
5
- const utils = require('../utils.js');
5
+ const utils = require('../utils');
6
6
  const constants = require('../commons/constants');
7
7
  const featureAvailabilityService = require('../commons/featureAvailabilityService');
8
8
  const { getAbortedTests, getFailedTests, getPassedTests, getFailureEvaluatingCount, getSkippedCount } = require('./reporterUtils');
@@ -120,7 +120,8 @@ class ConsoleReporter {
120
120
  if (isCodeMode) {
121
121
  console.log(`Run test plan, Project: ${this.options.project} (Execution ID: ${executionId}):`);
122
122
  } else {
123
- console.log(`Run${this.buildTestPlanName(isAnonymous, testPlanName)} test plan with ${configString}, Project: ${this.options.project}, Branch: ${this.branchToUse} (${executionId})`);
123
+ const sfdcCredentialLog = this.options.sfdcCredential ? ` SfdcCredential: ${this.options.sfdcCredential}` : '';
124
+ console.log(`Run${this.buildTestPlanName(isAnonymous, testPlanName)} test plan with ${configString}, Project: ${this.options.project}, Branch: ${this.branchToUse}${sfdcCredentialLog} (${executionId})`);
124
125
  }
125
126
  this.printWorkerDivider();
126
127
 
@@ -3,13 +3,11 @@
3
3
  'use strict';
4
4
 
5
5
  const xml2js = require('xml2js');
6
- const Promise = require('bluebird');
7
- const fs = Promise.promisifyAll(require('fs'));
8
- const utils = require('../utils.js');
6
+ const fsPromises = require('fs/promises');
7
+ const utils = require('../utils');
9
8
  const {
10
9
  isAbortedTest, isSkippedTest, getFailedTests, isFailedTest, getFailureEvaluatingCount, getSkippedCount, getAbortedTests,
11
10
  } = require('./reporterUtils');
12
- const featureFlags = require('../commons/featureFlags.js');
13
11
  const featureAvailabilityService = require('../commons/featureAvailabilityService');
14
12
 
15
13
  class JunitReporter {
@@ -35,7 +33,7 @@ class JunitReporter {
35
33
  return undefined;
36
34
  }
37
35
  try {
38
- await fs.writeFileAsync(reportFile, reportText);
36
+ await fsPromises.writeFile(reportFile, reportText);
39
37
  console.log('JUnit XML file saved to', reportFile);
40
38
  return testResults;
41
39
  } catch (err) {
@@ -56,7 +54,7 @@ function getPrintName(testResult) {
56
54
  }
57
55
 
58
56
  async function report(editorUrl, testPlanResults, projectId, branch, classname, options) {
59
- function createTestCaseObject(testResult, projectId) {
57
+ function createTestCaseObject(testResult) {
60
58
  const testResultUrl = utils.getTestUrl(editorUrl, projectId, testResult.testId, testResult.resultId, branch);
61
59
  const testResultObject = {
62
60
  $: {
@@ -103,7 +101,7 @@ async function report(editorUrl, testPlanResults, projectId, branch, classname,
103
101
  }
104
102
  return {
105
103
  $: testSuiteAttributes,
106
- testcase: Object.keys(testResults).map(resultId => createTestCaseObject(testResults[resultId], projectId)),
104
+ testcase: Object.keys(testResults).map(resultId => createTestCaseObject(testResults[resultId])),
107
105
  };
108
106
  }
109
107
 
@@ -131,9 +129,9 @@ async function report(editorUrl, testPlanResults, projectId, branch, classname,
131
129
  try {
132
130
  const builder = new xml2js.Builder();
133
131
  const jUnitXmlReporter = builder.buildObject(testResultObject);
134
- return Promise.resolve(jUnitXmlReporter);
132
+ return jUnitXmlReporter;
135
133
  } catch (err) {
136
- return Promise.resolve(createErrorjUnitReporter(err));
134
+ return createErrorjUnitReporter(err);
137
135
  }
138
136
  }
139
137