@testim/testim-cli 3.255.0 → 3.257.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 (35) hide show
  1. package/agent/routers/cliJsCode/service.js +11 -8
  2. package/cli.js +2 -2
  3. package/cliAgentMode.js +7 -7
  4. package/codim/codim-cli.js +4 -1
  5. package/commons/featureFlags.js +21 -7
  6. package/commons/httpRequest.js +1 -1
  7. package/commons/initializeUserWithAuth.js +7 -4
  8. package/commons/preloadTests.js +5 -2
  9. package/commons/prepareRunner.js +5 -5
  10. package/commons/prepareRunnerAndTestimStartUtils.js +11 -4
  11. package/commons/runnerFileCache.js +9 -1
  12. package/commons/testimServicesApi.js +36 -5
  13. package/npm-shrinkwrap.json +59 -60
  14. package/package.json +1 -1
  15. package/player/stepActions/apiStepAction.js +49 -43
  16. package/player/stepActions/baseCliJsStepAction.js +19 -14
  17. package/player/stepActions/baseJsStepAction.js +9 -8
  18. package/player/stepActions/dropFileStepAction.js +1 -3
  19. package/player/stepActions/inputFileStepAction.js +10 -8
  20. package/player/stepActions/mouseStepAction.js +21 -22
  21. package/player/stepActions/nodePackageStepAction.js +34 -35
  22. package/player/stepActions/stepAction.js +1 -0
  23. package/player/utils/imageCaptureUtils.js +63 -63
  24. package/player/utils/screenshotUtils.js +16 -13
  25. package/player/utils/windowUtils.js +20 -8
  26. package/processHandler.js +4 -0
  27. package/runOptions.d.ts +27 -1
  28. package/runOptions.js +7 -7
  29. package/runner.js +62 -23
  30. package/runners/ParallelWorkerManager.js +3 -2
  31. package/runners/TestPlanRunner.js +9 -6
  32. package/runners/buildCodeTests.js +1 -0
  33. package/runners/runnerUtils.js +11 -2
  34. package/services/branchService.js +11 -5
  35. package/services/localRCASaver.js +4 -0
@@ -1,5 +1,4 @@
1
1
  const StepAction = require('./stepAction');
2
- const Promise = require('bluebird');
3
2
  const html5dndAction = require('./scripts/html5dragAction');
4
3
  const html5dndActionV2 = require('./scripts/html5dragActionV2');
5
4
  const doClickScript = require('./scripts/doClick');
@@ -30,7 +29,7 @@ class MouseStepAction extends StepAction {
30
29
  const timeout = context.data.timeToPlayStep + 3000;
31
30
  const events = step.events;
32
31
 
33
- if (!events || !events.length) {
32
+ if (!events?.length) {
34
33
  return Promise.resolve();
35
34
  }
36
35
 
@@ -58,12 +57,12 @@ class MouseStepAction extends StepAction {
58
57
 
59
58
  return this.driver.executeCodeAsync(doClickCode, timeout, eventParam)
60
59
  .then(result => {
61
- if (result.value && result.value.success) {
62
- return Promise.resolve({ success: true });
60
+ if (result.value?.success) {
61
+ return { success: true };
63
62
  }
64
- return Promise.resolve({ success: false });
63
+ return { success: false };
65
64
  })
66
- .catch(err => Promise.resolve({
65
+ .catch(err => ({
67
66
  success: false,
68
67
  reason: err.message,
69
68
  exception: err,
@@ -75,7 +74,7 @@ class MouseStepAction extends StepAction {
75
74
  }
76
75
 
77
76
  getEventSequenceOffset() {
78
- const initialPosition = (this.step.events[0] || {}).pointerPosition;
77
+ const initialPosition = this.step.events[0]?.pointerPosition;
79
78
  if (!initialPosition) {
80
79
  return { xOffset: 0, yOffset: 0 };
81
80
  }
@@ -91,7 +90,7 @@ class MouseStepAction extends StepAction {
91
90
 
92
91
  addOffsetToEvents(offsetFromElement) {
93
92
  this.step.events.forEach(event => {
94
- if (event && event.pointerPosition) {
93
+ if (event?.pointerPosition) {
95
94
  event.pointerPosition.originX += offsetFromElement.xOffset;
96
95
  event.pointerPosition.originY += offsetFromElement.yOffset;
97
96
  }
@@ -113,7 +112,9 @@ class MouseStepAction extends StepAction {
113
112
 
114
113
  const { recordPointerMoveEvents = false } = this.context.project.defaults || {};
115
114
  const mouseUpEvent = this.step.events.find(event => event.event === 'mouseup') || (recordPointerMoveEvents && this.step.events.find(event => event.event === 'pointerup'));
116
- const lastMouseMoveEventIndex = _.findLastIndex(this.step.events, event => event.event === 'mousemove') || (recordPointerMoveEvents && _.findLastIndex(this.step.events, event => event.event === 'pointermove'));
115
+ const lastMouseMoveEventIndex =
116
+ _.findLastIndex(this.step.events, event => event.event === 'mousemove') ||
117
+ (recordPointerMoveEvents && _.findLastIndex(this.step.events, event => event.event === 'pointermove'));
117
118
  if (mouseUpEvent && lastMouseMoveEventIndex > 0 && !this.step.allEventsOnSameElement) {
118
119
  this.step.events.splice(lastMouseMoveEventIndex + 1, 0, this.generateEventOfType(mouseUpEvent, 'mouseover'));
119
120
  }
@@ -159,12 +160,12 @@ class MouseStepAction extends StepAction {
159
160
 
160
161
  return this.driver.executeCodeAsync(doDragPathCode, timeout, eventMessage)
161
162
  .then(result => {
162
- if (result.value && result.value.success) {
163
- return Promise.resolve({ success: true });
163
+ if (result.value?.success) {
164
+ return { success: true };
164
165
  }
165
- return Promise.resolve({ success: false });
166
+ return { success: false };
166
167
  })
167
- .catch(err => Promise.resolve({
168
+ .catch(err => ({
168
169
  success: false,
169
170
  reason: err.message,
170
171
  exception: err,
@@ -173,9 +174,7 @@ class MouseStepAction extends StepAction {
173
174
 
174
175
  chooseAndRunAction() {
175
176
  const target = this.getTarget();
176
- const {
177
- locatedElement, seleniumElement, rectWithoutFrameOffset, rect,
178
- } = target;
177
+ const { locatedElement, seleniumElement, rectWithoutFrameOffset, rect } = target;
179
178
  const { xOffset, yOffset } = this.stepActionUtils.getClickOffset(this.step.element.clickOffset, rectWithoutFrameOffset);
180
179
 
181
180
  // used for fallback native click
@@ -220,7 +219,7 @@ class MouseStepAction extends StepAction {
220
219
  if (!isIE && featureFlagService.flags.usePortedHtml5DragDrop.isEnabled()) {
221
220
  const events = this.generateHTML5DragEventSequence();
222
221
  const timeout = this.context.data.timeToPlayStep + 3000;
223
- const target = this.context.data[this.step.targetId || 'targetId'];
222
+ const contextTarget = this.context.data[this.step.targetId || 'targetId'];
224
223
  const eventMessage = {
225
224
  transactionId: `${this.context.testResultId}:${this.step.id}`,
226
225
  id: this.step.id,
@@ -235,10 +234,10 @@ class MouseStepAction extends StepAction {
235
234
  isDrag: this.step.isDrag,
236
235
  useRecordedMousedown: this.step.useRecordedMousedown,
237
236
  allEventsOnSameElement: this.step.allEventsOnSameElement,
238
- elementToFocusLocatedElement: target.elementToFocusLocatedElement,
237
+ elementToFocusLocatedElement: contextTarget.elementToFocusLocatedElement,
239
238
  trackActiveElement: this.step.trackActiveElement,
240
- locatedElement: target.locatedElement,
241
- isRoot: target.isRoot,
239
+ locatedElement: contextTarget.locatedElement,
240
+ isRoot: contextTarget.isRoot,
242
241
  };
243
242
  // hack for Edge (17/18) which does not accept properties with negative (throws Unknown Error)
244
243
  // values between 0 and -1 -_-.
@@ -311,7 +310,7 @@ class MouseStepAction extends StepAction {
311
310
  }
312
311
 
313
312
  addDragendIfNeeded(events) {
314
- if (events.find(event => event.event === 'dragend')) {
313
+ if (events.some(event => event.event === 'dragend')) {
315
314
  return events;
316
315
  }
317
316
  const dragendDefaultEvent = {
@@ -325,7 +324,7 @@ class MouseStepAction extends StepAction {
325
324
  }
326
325
 
327
326
  getToElementPosition() {
328
- if (!(this.context.data && this.context.data.toElement && this.context.data.toElement.rect)) {
327
+ if (!(this.context.data?.toElement?.rect)) {
329
328
  return undefined;
330
329
  }
331
330
  const { rect } = this.context.data.toElement;
@@ -1,47 +1,46 @@
1
- "use strict";
1
+ 'use strict';
2
2
 
3
3
  const StepAction = require('./stepAction');
4
- const Promise = require('bluebird');
5
- const {NpmPackageError} = require('../../errors');
4
+ const Bluebird = require('bluebird');
5
+ const { NpmPackageError } = require('../../errors');
6
6
 
7
7
  const service = require('../../agent/routers/cliJsCode/service');
8
8
 
9
9
  class NodePackageStepAction extends StepAction {
10
+ async performAction() {
11
+ const { context } = this;
12
+ const { stepId, packageData, resultId, retryIndex, stepResultId, timeToPlayBeforeExec } = context;
10
13
 
11
- performAction() {
12
- const {context} = this;
13
- const {
14
- stepId,
15
- packageData,
16
- resultId,
17
- retryIndex,
18
- stepResultId,
19
- timeToPlayBeforeExec
20
- } = context;
21
-
22
- return service.installPackage(stepId, resultId, retryIndex, packageData, stepResultId, timeToPlayBeforeExec)
23
- .then(data => ({data, success: true}))
24
- .catch(NpmPackageError, err => {
25
- return Promise.resolve({
26
- success: false,
27
- code: "invalid-node-package",
28
- message: err.message
29
- })
30
- })
31
- .catch(Promise.TimeoutError, () => {
32
- return Promise.resolve({
14
+ try {
15
+ const data = await service.installPackage(
16
+ stepId,
17
+ resultId,
18
+ retryIndex,
19
+ packageData,
20
+ stepResultId,
21
+ timeToPlayBeforeExec,
22
+ );
23
+ return ({ data, success: true });
24
+ } catch (err) {
25
+ if (err instanceof NpmPackageError) {
26
+ return {
33
27
  success: false,
34
- code: "timeout"
35
- });
36
- })
37
- .catch(err =>
38
- Promise.resolve({
28
+ code: 'invalid-node-package',
29
+ message: err.message,
30
+ };
31
+ }
32
+ if (err instanceof Bluebird.TimeoutError) {
33
+ return {
39
34
  success: false,
40
- reason: err.message,
41
- exception: err
42
- })
43
- );
44
-
35
+ code: 'timeout',
36
+ };
37
+ }
38
+ return {
39
+ success: false,
40
+ reason: err.message,
41
+ exception: err,
42
+ };
43
+ }
45
44
  }
46
45
  }
47
46
 
@@ -22,6 +22,7 @@ class StepAction {
22
22
  this.context = context;
23
23
  this.frameHandler = frameHandler;
24
24
  this.frameId = 0;
25
+ /** @type {import('../utils/stepActionUtils'))} */
25
26
  this.stepActionUtils = stepActionUtils;
26
27
  this.locateElementPlayer = locateElementPlayer;
27
28
  this.exportsGlobal = exportsGlobal;
@@ -16,16 +16,6 @@ class RectIsOutsideOfImageError extends Error {
16
16
  }
17
17
  }
18
18
 
19
- /**
20
- * @param {never} tabId
21
- * @param {import('./windowUtils')} windowUtils
22
- * @param {import('./screenshotUtils')} screenshotUtils
23
- * */
24
- const ImageCaptureUtils = function (tabId, windowUtils, screenshotUtils) {
25
- this.windowUtils = windowUtils;
26
- this.screenshotUtils = screenshotUtils;
27
- };
28
-
29
19
  async function cropImageFromImageData(imageData, imageInfo) {
30
20
  const _image = imageInfo.image || imageInfo;
31
21
  const pixelRatio = imageInfo.devicePixelRatio;
@@ -114,6 +104,7 @@ function stitchImage(fullSize, parts) {
114
104
  return chromeStitchImage(fullSize, parts);
115
105
  }
116
106
 
107
+ // ???????????
117
108
  function uploadDataUrl() {
118
109
  return Promise.resolve();
119
110
  }
@@ -148,74 +139,80 @@ function getElementAbsoluteRectangle(elementRect, pixelRatio) {
148
139
  };
149
140
  }
150
141
 
151
- ImageCaptureUtils.prototype = {
152
- takeViewPortImage() {
153
- return this.screenshotUtils.takeScreenshot()
154
- .then((imageInfo) => ((typeof imageInfo === 'string') ? imageInfo : imageInfo.image));
155
- },
142
+ class ImageCaptureUtils {
143
+ /**
144
+ * @param {unknown} _unusedId
145
+ * @param {import('./windowUtils')} windowUtils
146
+ * @param {import('./screenshotUtils')} screenshotUtils
147
+ * */
148
+ constructor(_unusedId, windowUtils, screenshotUtils) {
149
+ this.windowUtils = windowUtils;
150
+ this.screenshotUtils = screenshotUtils;
151
+ }
152
+
153
+ async takeViewPortImage() {
154
+ const imageInfo = await this.screenshotUtils.takeScreenshot();
155
+ return ((typeof imageInfo === 'string') ? imageInfo : imageInfo.image);
156
+ }
156
157
 
157
158
  takeImageForComparison() {
158
159
  return this.takeViewPortImage();
159
- },
160
+ }
160
161
 
161
- takeAreaDataUrl(areas, format) {
162
+ async takeAreaDataUrl(areas, format) {
162
163
  // Future changes in clickim will pass parameters to this function as a single object
163
164
  if (areas.areas) {
164
165
  areas = areas.areas;
165
166
  }
166
167
 
167
- return this.screenshotUtils.takeScreenshot(format)
168
- .then((imageInfo) => cropImageFromImageData(areas, imageInfo).then((result) => {
169
- result.screenImage = imageInfo.image;
170
- result.absoluteScreenHighlight = getElementAbsoluteRectangle(areas.elementRect, imageInfo.devicePixelRatio);
171
- return result;
172
- }));
173
- },
168
+ const imageInfo = await this.screenshotUtils.takeScreenshot(format);
169
+ const result = await cropImageFromImageData(areas, imageInfo);
170
+ result.screenImage = imageInfo.image;
171
+ result.absoluteScreenHighlight = getElementAbsoluteRectangle(areas.elementRect, imageInfo.devicePixelRatio);
172
+ return result;
173
+ }
174
174
 
175
- takeArea(areas) {
175
+ async takeArea(areas) {
176
176
  // Future changes in clickim will pass parameters to this function as a single object
177
177
  if (areas.areas) {
178
178
  areas = areas.areas;
179
179
  }
180
180
 
181
- return this.screenshotUtils.takeScreenshot()
182
- .then((imageInfo) => {
183
- const result = {};
184
- result.screenImage = imageInfo.image;
185
- result.absoluteScreenHighlight = getElementAbsoluteRectangle(areas.elementRect, imageInfo.devicePixelRatio);
186
- return result;
187
- }).then(uploadAllDataUrls);
188
- },
181
+ const imageInfo = await this.screenshotUtils.takeScreenshot();
182
+ return uploadAllDataUrls({
183
+ screenImage: imageInfo.image,
184
+ absoluteScreenHighlight: getElementAbsoluteRectangle(areas.elementRect, imageInfo.devicePixelRatio),
185
+ });
186
+ }
189
187
 
190
188
  forcePixelRatio(forceRatio) {
191
189
  return this.screenshotUtils.forcePixelRatio(forceRatio);
192
- },
190
+ }
193
191
 
194
192
  getCurrentDevicePixelRatio() {
195
193
  return this.screenshotUtils.getCurrentDevicePixelRatio();
196
- },
194
+ }
197
195
 
198
196
  async takeStitchedDataUrl(useImprovedScreenshotStitching) {
199
- const windowUtil = this.windowUtils;
200
- const getCurrentScrollPosition = windowUtil.getCurrentScrollPosition.bind(windowUtil);
197
+ const { windowUtils, screenshotUtils } = this;
201
198
 
202
- const that = this;
203
199
  const stabilize = () => utils.delay(250);
204
200
  const usingImprovedStitching = Boolean(useImprovedScreenshotStitching);
205
- const scroll = usingImprovedStitching ?
206
- (pos) => windowUtil.scrollToPositionWithoutAnimation.bind(windowUtil)(pos) :
207
- (pos) => windowUtil.scrollToPosition.bind(windowUtil)(pos);
208
-
209
- function createPart(position, crop) {
210
- return scroll(position)
211
- .then(stabilize)
212
- .then(() => that.screenshotUtils.takeScreenshot())
213
- .then(imageInfo => cropImageFromImageData({ elementRect: crop }, imageInfo))
214
- .then(cropResult => ({
215
- position: { left: position.x + crop.left, top: position.y + crop.top },
216
- size: { width: crop.width, height: crop.height },
217
- image: cropResult.elementImage,
218
- }));
201
+
202
+ async function createPart(position, crop) {
203
+ if (usingImprovedStitching) {
204
+ await windowUtils.scrollToPositionWithoutAnimation(position);
205
+ } else {
206
+ await windowUtils.scrollToPosition(position);
207
+ }
208
+ await stabilize();
209
+ const imageInfo = await screenshotUtils.takeScreenshot();
210
+ const cropResult = await cropImageFromImageData({ elementRect: crop }, imageInfo);
211
+ return ({
212
+ position: { left: position.x + crop.left, top: position.y + crop.top },
213
+ size: { width: crop.width, height: crop.height },
214
+ image: cropResult.elementImage,
215
+ });
219
216
  }
220
217
 
221
218
  async function takeAllParts(positionsData) {
@@ -232,36 +229,39 @@ ImageCaptureUtils.prototype = {
232
229
  const VPW = viewPortSize.width;
233
230
  const FPH = Math.max(fullPageSize.height, viewPortSize.height);
234
231
  const VPH = viewPortSize.height;
235
- const Ws = (Array.apply(null, new Array(Math.ceil(FPW / VPW)))).map((_, i) => ({
232
+ const Ws = Array.from({ length: Math.ceil(FPW / VPW) }, (__, i) => ({
236
233
  scrollX: Math.min(i * VPW, FPW - VPW),
237
234
  cropX: i * VPW - Math.min(i * VPW, FPW - VPW),
238
235
  cropW: VPW - (i * VPW - Math.min(i * VPW, FPW - VPW)),
239
236
  }));
240
- const Hs = (Array.apply(null, new Array(Math.ceil(FPH / VPH)))).map((_, i) => ({
237
+ const Hs = Array.from({ length: Math.ceil(FPH / VPH) }, (__, i) => ({
241
238
  scrollY: Math.min(i * VPH, FPH - VPH),
242
239
  cropY: i * VPH - Math.min(i * VPH, FPH - VPH),
243
240
  cropH: VPH - (i * VPH - Math.min(i * VPH, FPH - VPH)),
244
241
  }));
245
- const positions = Ws.reduce((posList, w) => posList.concat(Hs.map((h) => ({
242
+ return Ws.flatMap(w => Hs.map(h => ({
246
243
  scrollPos: { x: w.scrollX, y: h.scrollY },
247
244
  cropData: {
248
- top: h.cropY, left: w.cropX, width: w.cropW, height: h.cropH,
245
+ top: h.cropY,
246
+ left: w.cropX,
247
+ width: w.cropW,
248
+ height: h.cropH,
249
249
  },
250
- }))), []);
251
- return positions;
250
+ }))
251
+ );
252
252
  }
253
253
 
254
254
  async function createStitchImage(fullPageSize, viewPortSize) {
255
- const originalPosition = await getCurrentScrollPosition();
255
+ const originalPosition = await windowUtils.getCurrentScrollPosition();
256
256
  const positions = getPartsPositions(fullPageSize, viewPortSize);
257
257
  const parts = await takeAllParts(positions);
258
- await windowUtil.scrollToPosition(originalPosition);
258
+ await windowUtils.scrollToPosition(originalPosition);
259
259
  return stitchImage(fullPageSize, parts);
260
260
  }
261
261
 
262
- const [fullPageSize, viewPortSize] = await Promise.all([windowUtil.getFullPageSize(), windowUtil.getViewportSize()]);
262
+ const [fullPageSize, viewPortSize] = await Promise.all([windowUtils.getFullPageSize(), windowUtils.getViewportSize()]);
263
263
  return await createStitchImage(fullPageSize, viewPortSize);
264
- },
265
- };
264
+ }
265
+ }
266
266
 
267
267
  module.exports = ImageCaptureUtils;
@@ -1,9 +1,15 @@
1
+ // @ts-check
2
+
1
3
  'use strict';
2
4
 
3
5
  const Promise = require('bluebird');
4
6
  const pRetry = require('p-retry');
5
7
 
6
8
  class ScreenshotUtils {
9
+ /**
10
+ * @param {any} tabId
11
+ * @param {import('../webdriver')} driver
12
+ */
7
13
  constructor(tabId, driver, options = { takeScreenshots: true }) {
8
14
  this.tabId = tabId;
9
15
  this.driver = driver;
@@ -21,23 +27,21 @@ class ScreenshotUtils {
21
27
  return this.options.takeScreenshots;
22
28
  }
23
29
 
24
- takeScreenshot() {
30
+ async takeScreenshot() {
25
31
  if (!this.shouldTakeScreenshots()) {
26
- return Promise.resolve({ devicePixelRatio: 1, image: '' });
32
+ return { devicePixelRatio: 1, image: '' };
27
33
  }
28
34
  const MAX_RETRY_COUNT = 3;
29
35
  const SCREENSHOT_RETRY_DELAY = 2000;
30
36
  const devicePixelRatioPromise = this.currentDevicePixelRatio ? Promise.resolve(this.currentDevicePixelRatio) : this.getDevicePixelRatio();
31
37
  const getScreenshot = () => Promise.all([devicePixelRatioPromise, this.driver.takeScreenshot()]);
32
- return pRetry(getScreenshot, { retries: MAX_RETRY_COUNT, minTimeout: SCREENSHOT_RETRY_DELAY })
33
- .then(([devicePixelRatio, image]) => {
34
- const base64 = image ? image.value : '';
35
- const dataUrl = `data:image/png;base64,${this.base64AddPadding(base64.replace(/[\r\n]/g, ''))}`;
36
- return {
37
- image: dataUrl,
38
- devicePixelRatio,
39
- };
40
- });
38
+ const [devicePixelRatio, image] = await pRetry(getScreenshot, { retries: MAX_RETRY_COUNT, minTimeout: SCREENSHOT_RETRY_DELAY });
39
+ const base64 = image ? image.value : '';
40
+ const dataUrl = `data:image/png;base64,${this.base64AddPadding(base64.replace(/[\r\n]/g, ''))}`;
41
+ return {
42
+ image: dataUrl,
43
+ devicePixelRatio,
44
+ };
41
45
  }
42
46
 
43
47
  getDevicePixelRatio() {
@@ -49,7 +53,7 @@ class ScreenshotUtils {
49
53
  }
50
54
  }
51
55
 
52
- return this.driver.executeJS(devicePixelRatioJS).then(result => Promise.resolve(result.value));
56
+ return this.driver.executeJS(devicePixelRatioJS).then(result => result.value);
53
57
  }
54
58
 
55
59
  forcePixelRatio(forceRatio = 1) {
@@ -63,4 +67,3 @@ class ScreenshotUtils {
63
67
  }
64
68
 
65
69
  module.exports = ScreenshotUtils;
66
-
@@ -1,3 +1,5 @@
1
+ // @ts-check
2
+
1
3
  'use strict';
2
4
 
3
5
  const Promise = require('bluebird');
@@ -7,6 +9,10 @@ const { PageNotAvailableError } = require('../../errors');
7
9
  const logger = require('../../commons/logger').getLogger('window-utils');
8
10
 
9
11
  class WindowUtils {
12
+ /**
13
+ * @param {number} id tab or worker id
14
+ * @param {import('../webdriver')} driver
15
+ * */
10
16
  constructor(id, driver) {
11
17
  this.id = id;
12
18
  this.driver = driver;
@@ -131,12 +137,12 @@ class WindowUtils {
131
137
  });
132
138
  }
133
139
 
134
- setViewportSize(size) {
135
- return this.driver.setViewportSize(size.width, size.height)
136
- .then(() => this.checkSize(size));
140
+ async setViewportSize(size) {
141
+ await this.driver.setViewportSize(size.width, size.height);
142
+ return await this.checkSize(size);
137
143
  }
138
144
 
139
- validatePageIsAvailable() {
145
+ async validatePageIsAvailable() {
140
146
  /* eslint-disable */
141
147
  function pageIsAvailable() {
142
148
  var locationObj;
@@ -153,7 +159,8 @@ class WindowUtils {
153
159
  }
154
160
  /* eslint-enable */
155
161
 
156
- return this.driver.executeJS(pageIsAvailable).then(result => (result.value ? Promise.resolve() : Promise.reject(new PageNotAvailableError())));
162
+ const result = await this.driver.executeJS(pageIsAvailable);
163
+ return await (result.value ? Promise.resolve() : Promise.reject(new PageNotAvailableError()));
157
164
  }
158
165
 
159
166
  focusTab() {
@@ -164,9 +171,14 @@ class WindowUtils {
164
171
  return undefined;
165
172
  }
166
173
 
167
- getOsAndBrowser() {
168
- return pRetry(() => this.driver.getBrowserAndOS(), { retries: 3 })
169
- .then(osAndBrowser => ({ uaBrowserName: osAndBrowser.browser, uaOs: osAndBrowser.os, userAgent: osAndBrowser.userAgent, browserVersion: osAndBrowser.browserVersion }));
174
+ async getOsAndBrowser() {
175
+ const osAndBrowser = await pRetry(() => this.driver.getBrowserAndOS(), { retries: 3 });
176
+ return {
177
+ uaBrowserName: osAndBrowser.browser,
178
+ uaOs: osAndBrowser.os,
179
+ userAgent: osAndBrowser.userAgent,
180
+ browserVersion: osAndBrowser.browserVersion,
181
+ };
170
182
  }
171
183
 
172
184
  getUserAgentInfo() {
package/processHandler.js CHANGED
@@ -7,6 +7,10 @@ const logger = require('./commons/logger').getLogger('process-handler');
7
7
 
8
8
  const exitHooks = [];
9
9
 
10
+ /**
11
+ * @param {(e: any) => void} onExit
12
+ * @param {NodeJS.Process=} _process
13
+ */
10
14
  module.exports = function (onExit, _process = process) {
11
15
  async function cleanup(err) {
12
16
  // give cleanup and socket reports a chance to run
package/runOptions.d.ts CHANGED
@@ -70,6 +70,11 @@ interface LightweightSettings {
70
70
  disableProjectDefaults: boolean;
71
71
  }
72
72
 
73
+ type InitUserWithAuth = Awaited<ReturnType<typeof import('./commons/testimServicesApi')['initializeUserWithAuth']>>;
74
+ interface ProjectData extends Pick<InitUserWithAuth['projectById'], 'type' | 'name' | 'defaults'> {
75
+ projectId: string;
76
+ }
77
+
73
78
  // TODO: consider typing better, based on the validations we do (example: must have one of grid/grid-id/host&port/test plan)
74
79
  interface RunnerOptions extends Partial<Omit<TunnelOptions, 'tunnelOnlyMode' | 'tunnel'>> {
75
80
  token: string;
@@ -103,6 +108,26 @@ interface RunnerOptions extends Partial<Omit<TunnelOptions, 'tunnelOnlyMode' | '
103
108
  retentionDays?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
104
109
  retries?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20;
105
110
 
111
+ // #region Data set based on values from server
112
+ company: {
113
+ companyId: string;
114
+ onprem: boolean;
115
+ storageBaseUrl: string;
116
+ storageType: string;
117
+ name: string;
118
+ planType: 'pro' | 'free' | 'trial';
119
+ isPOC: boolean;
120
+ isStartUp: boolean;
121
+ activePlan: import('services/src/commons/mongo/db-dto-definitions/DbCompanyProjects').Plan;
122
+ };
123
+ gridData?: Awaited<ReturnType<typeof import('./services/gridService')['getGridData']>>;
124
+ sfdcCredential?: string;
125
+ editorUrl?: string;
126
+ allGrids?: InitUserWithAuth['allGrids'];
127
+ authData?: InitUserWithAuth['authData'];
128
+ projectData?: ProjectData;
129
+ // #endregion
130
+
106
131
  // #region What to execute
107
132
  testId: string[];
108
133
  name: string[];
@@ -161,7 +186,7 @@ interface RunnerOptions extends Partial<Omit<TunnelOptions, 'tunnelOnlyMode' | '
161
186
 
162
187
  // #region Extension debugging
163
188
  ext?: string;
164
- extensionLocation?: string[];
189
+ extensionLocation: string[];
165
190
  extensionPath?: string;
166
191
  // #endregion
167
192
 
@@ -243,6 +268,7 @@ interface RunnerOptions extends Partial<Omit<TunnelOptions, 'tunnelOnlyMode' | '
243
268
  lightweightMode?: LightweightSettings;
244
269
  createPrefechedData?: boolean;
245
270
  saveRCALocally?: boolean | string;
271
+ localRCASaver?: string;
246
272
  // #endregion
247
273
 
248
274
  // #region intersections
package/runOptions.js CHANGED
@@ -804,7 +804,7 @@ module.exports = {
804
804
 
805
805
  program.port = program.port && Number(program.port);
806
806
 
807
- if (program.retries <= 0 || _.isNaN(program.retries)) {
807
+ if (program.retries <= 0 || Number.isNaN(program.retries)) {
808
808
  throw new ArgError('test failure retry count could not be a negative number or string, --retries <max_num_of_retries>');
809
809
  }
810
810
 
@@ -823,27 +823,27 @@ module.exports = {
823
823
  }
824
824
  }
825
825
 
826
- if (program.browserTimeout <= 0 || _.isNaN(program.browserTimeout)) {
826
+ if (program.browserTimeout <= 0 || Number.isNaN(program.browserTimeout)) {
827
827
  throw new ArgError('get browser timeout could not be a negative number, --browser-timeout <get-browser-timeout>');
828
828
  }
829
829
 
830
- if (program.newBrowserWaitTimeout <= 0 || _.isNaN(program.newBrowserWaitTimeout)) {
830
+ if (program.newBrowserWaitTimeout <= 0 || Number.isNaN(program.newBrowserWaitTimeout)) {
831
831
  throw new ArgError('max new browser wait timeout could not be a negative number, --new-browser-wait-timeout <max-wait-to-browser>');
832
832
  }
833
833
 
834
- if (program.timeout <= 0 || _.isNaN(program.timeout)) {
834
+ if (program.timeout <= 0 || Number.isNaN(program.timeout)) {
835
835
  throw new ArgError('test run timeout could not be a negative number, --timeout <run-timeout>');
836
836
  }
837
837
 
838
- if (program.beforeParallel <= 0 || _.isNaN(program.beforeParallel)) {
838
+ if (program.beforeParallel <= 0 || Number.isNaN(program.beforeParallel)) {
839
839
  throw new ArgError('before-parallel could not be a negative number or not number, --before-parallel <number-of-tests>');
840
840
  }
841
841
 
842
- if (program.parallel <= 0 || _.isNaN(program.parallel)) {
842
+ if (program.parallel <= 0 || Number.isNaN(program.parallel)) {
843
843
  throw new ArgError('parallel could not be a negative number or not number, --parallel <number-of-tests>');
844
844
  }
845
845
 
846
- if (program.afterParallel <= 0 || _.isNaN(program.afterParallel)) {
846
+ if (program.afterParallel <= 0 || Number.isNaN(program.afterParallel)) {
847
847
  throw new ArgError('after-parallel could not be a negative number or not number, --after-parallel <number-of-tests>');
848
848
  }
849
849