@testim/testim-cli 3.255.0 → 3.256.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 +41 -41
  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
@@ -40,10 +40,6 @@ function runCode(transactionId, incomingParams, context, code, packageLocalLocat
40
40
  return all;
41
41
  }, '');
42
42
 
43
- if (fileDataUrl === 'data:') { // fix chrome/safari bug that creates malformed datauri for empty files
44
- fileDataUrl = 'data:,';
45
- }
46
-
47
43
  const fileDataUrlToFileBuffer = !fileDataUrl ? 'var fileBuffer = null;' :
48
44
  `
49
45
  ${dataUriToBuffer.toString()}
@@ -297,10 +293,6 @@ function runCodeWithWorkerThread(transactionId, incomingParams, context, code, p
297
293
  return all;
298
294
  }, '');
299
295
 
300
- if (fileDataUrl === 'data:') { // fix chrome/safari bug that creates malformed datauri for empty files
301
- fileDataUrl = 'data:,';
302
- }
303
-
304
296
  const fileDataUrlToFileBuffer = !fileDataUrl ? 'var fileBuffer = null;' :
305
297
  `
306
298
  ${dataUriToBuffer.toString()}
@@ -581,6 +573,17 @@ function runCodeWithPackages(code, stepId, incomingParams, context, testResultId
581
573
  }
582
574
  }
583
575
 
576
+ const emptyFileDataUrl = 'data:,';
577
+ if (fileDataUrl === 'data:') { // Fix chrome/safari bug that creates malformed data-uri for empty files
578
+ logger.debug('runCodeWithPackages, fileDataUrl was an empty string ', { fileDataUrl });
579
+ fileDataUrl = emptyFileDataUrl;
580
+ }
581
+
582
+ if (Buffer.isBuffer(fileDataUrl)) { // Fix, S3 is returning a buffer and not a string on empty files
583
+ logger.debug('runCodeWithPackages, fileDataUrl was an empty Buffer ', { fileDataUrl });
584
+ fileDataUrl = emptyFileDataUrl;
585
+ }
586
+
584
587
  if (workerThreads && featureFlags.flags.enableWorkerThreadsCliCodeExecution.isEnabled()) {
585
588
  return runCodeWithWorkerThread(transactionId, incomingParams, context, code, packageLocalLocations, timeout, fileDataUrl);
586
589
  }
package/cli.js CHANGED
@@ -85,9 +85,9 @@ async function main() {
85
85
  }
86
86
  const res = await runnerFileCache.waitForSave();
87
87
  if (res.success) {
88
- console.log(`created prefeched data at ${runnerFileCache.getCacheFileLocation()}`);
88
+ console.log(`created prefetched data at ${runnerFileCache.getCacheFileLocation()}`);
89
89
  } else {
90
- console.error('failed to create prefech data', res.error);
90
+ console.error('failed to create prefetch data', res.error);
91
91
  }
92
92
  return undefined;
93
93
  }
package/cliAgentMode.js CHANGED
@@ -39,10 +39,7 @@ function shouldStartAgentMode(options) {
39
39
  return options.agentMode;
40
40
  }
41
41
 
42
- /**
43
- *
44
- * @param {*} options
45
- */
42
+ /** @param {import('./runOptions').AgentModeOptions} options */
46
43
  async function runAgentMode(options) {
47
44
  let testimStandaloneBrowser;
48
45
 
@@ -169,6 +166,7 @@ async function startFixedVersionChromium(options, extensionBase64, downloadedExt
169
166
  };
170
167
  }
171
168
 
169
+ /** @param {import('./runOptions').AgentModeOptions} options */
172
170
  async function startTestimStandaloneBrowser(options) {
173
171
  // After next clickim release we will have also testim-full.zip
174
172
  // const fullExtensionUrl = "https://testimstatic.blob.core.windows.net/extension/testim-full-master.zip";
@@ -222,9 +220,11 @@ async function startTestimStandaloneBrowser(options) {
222
220
  }
223
221
  await prepareUtils.prepareChromeDriver(
224
222
  { projectId: options.project },
223
+ // @ts-expect-error not clear where chromeBinaryLocations comes from
225
224
  { chromeBinaryLocation: options.chromeBinaryLocations },
226
225
  );
227
226
 
227
+ // @ts-expect-error not clear where chromeBinaryLocations comes from
228
228
  const seleniumOptions = buildSeleniumOptions(USER_DATA_DIR, extensionBase64, options.extensionPath, options.chromeBinaryLocations);
229
229
 
230
230
  const WebDriver = require('./player/webdriver');
@@ -264,7 +264,7 @@ async function startTestimStandaloneBrowser(options) {
264
264
 
265
265
  /**
266
266
  * @param {string} userDataDir
267
- * @param {string} fullExtensionPath
267
+ * @param {string | null} fullExtensionPath
268
268
  */
269
269
  function buildSeleniumOptions(userDataDir, fullExtensionPath, unpackedExtensionPath, chromeBinaryPath) {
270
270
  const extensions = fullExtensionPath ? [fullExtensionPath] : [];
@@ -356,7 +356,7 @@ async function readAndValidateChromedriverDevToolsActivePortFile() {
356
356
 
357
357
  /**
358
358
  * @param {string | import("url").URL} webSocketDebuggerUrl
359
- * @param {number?} timeout
359
+ * @param {number=} timeout
360
360
  */
361
361
  async function tryToCloseBrowserWithCDPUrl(webSocketDebuggerUrl, timeout = 100) {
362
362
  const websocketConnection = await wsConnectAndOpen(webSocketDebuggerUrl, timeout);
@@ -371,7 +371,7 @@ async function tryToCloseBrowserWithCDPUrl(webSocketDebuggerUrl, timeout = 100)
371
371
 
372
372
  /**
373
373
  * @param {string | import("url").URL} webSocketDebuggerUrl
374
- * @param {number?} timeout
374
+ * @param {number=} timeout
375
375
  */
376
376
  async function wsConnectAndOpen(webSocketDebuggerUrl, timeout = 100) {
377
377
  const websocket = new WebSocket(webSocketDebuggerUrl, { timeout });
@@ -1,3 +1,5 @@
1
+ // @ts-check
2
+
1
3
  /* eslint-disable no-console */
2
4
 
3
5
  'use strict';
@@ -6,11 +8,12 @@ const fs = require('fs');
6
8
  const childProcess = require('child_process');
7
9
  const path = require('path');
8
10
  const validateNpmPackageName = require('validate-npm-package-name');
9
- const ArgError = require('../errors.js').ArgError;
10
11
  const { promisify } = require('util');
12
+ const { ArgError } = require('../errors.js');
11
13
 
12
14
  const exec = promisify(childProcess.exec);
13
15
 
16
+ /** @param {string} name */
14
17
  module.exports.init = async function init(name) {
15
18
  const ora = require('ora');
16
19
  const prompts = require('prompts');
@@ -1,9 +1,11 @@
1
1
  'use strict';
2
2
 
3
- const { ROLLOUT_KEY, IS_ON_PREM, GATEWAY_URL } = require('./config');
4
- const logger = require('./logger').getLogger('FeatureFlagsService');
5
- const Promise = require('bluebird');
6
3
  const Rox = require('rox-node');
4
+ const { getLogger } = require('./logger');
5
+ const { promiseTimeout } = require('../utils');
6
+ const { ROLLOUT_KEY, IS_ON_PREM, GATEWAY_URL } = require('./config');
7
+
8
+ const logger = getLogger('FeatureFlagsService');
7
9
 
8
10
  // IS_UNIT_TEST = disable rollout if code run in unit test mode to ignore mocha process stuck on running
9
11
  const USE_FEATURE_FLAGS = !IS_ON_PREM && !process.env.IS_UNIT_TEST && !GATEWAY_URL;
@@ -11,6 +13,7 @@ const USE_FEATURE_FLAGS = !IS_ON_PREM && !process.env.IS_UNIT_TEST && !GATEWAY_U
11
13
  const FORCE_FETCH_TIMEOUT_MS = 20000; // rollout sometimes takes up to 15 seconds to load
12
14
  const SEC_IN_DAY = 60 * 60 * 24;
13
15
 
16
+ /** @type {['labs', 'disabled', 'enabled'] as const} */
14
17
  const LAB_FEATURE_FLAG_VALUES = ['labs', 'disabled', 'enabled'];
15
18
 
16
19
  class LabFeatureFlag extends Rox.Variant {
@@ -18,6 +21,7 @@ class LabFeatureFlag extends Rox.Variant {
18
21
  super(initialValue, LAB_FEATURE_FLAG_VALUES);
19
22
  }
20
23
 
24
+ /** @returns {(typeof LAB_FEATURE_FLAG_VALUES)[number]} */
21
25
  getValue() {
22
26
  const value = super.getValue();
23
27
  if (!LAB_FEATURE_FLAG_VALUES.includes(value)) {
@@ -63,41 +67,51 @@ class FeatureFlagsService {
63
67
  Rox.register('default', this.flags);
64
68
  }
65
69
 
70
+ /** @param {string} projectId */
66
71
  setProjectId(projectId) {
67
72
  Rox.setCustomStringProperty('projectId', projectId);
68
73
  }
69
74
 
75
+ /** @param {string} projectType */
70
76
  setProjectType(projectType) {
71
77
  Rox.setCustomStringProperty('projectType', projectType);
72
78
  }
73
79
 
80
+ /** @param {string} productType */
74
81
  setCompanyProductType(productType) {
75
82
  Rox.setCustomStringProperty('productType', productType);
76
83
  }
77
84
 
85
+ /** @param {string} companyId */
78
86
  setCompanyId(companyId) {
79
87
  Rox.setCustomStringProperty('companyId', companyId);
80
88
  }
81
89
 
90
+ /** @param {string} planType */
82
91
  setPlanType(planType) {
83
92
  Rox.setCustomStringProperty('planType', planType);
84
93
  }
85
94
 
95
+ /** @param {boolean} isPOC */
86
96
  setIsPOC(isPOC) {
87
97
  Rox.setCustomBooleanProperty('isPOC', isPOC);
88
98
  }
99
+
100
+ /** @param {boolean} isStartUp */
89
101
  setIsStartUp(isStartUp) {
90
102
  Rox.setCustomBooleanProperty('isStartUp', isStartUp);
91
103
  }
92
104
 
105
+ /** @param {string} mode */
93
106
  setRunnerMode(mode) {
94
107
  Rox.setCustomStringProperty('runnerMode', mode);
95
108
  }
96
109
 
97
- fetch() {
110
+ async fetch() {
98
111
  if (!USE_FEATURE_FLAGS) {
99
- return Promise.resolve();
112
+ return undefined;
100
113
  }
114
+ /** @type {Rox.RoxSetupOptions} */
101
115
  const opts = {
102
116
  fetchIntervalInSec: SEC_IN_DAY, // we don't actually want to refresh feature flags in the CLI,
103
117
  disableNetworkFetch: false,
@@ -110,8 +124,8 @@ class FeatureFlagsService {
110
124
  opts.httpAgent = agent;
111
125
  }
112
126
 
113
- return Promise.resolve(Rox.setup(ROLLOUT_KEY, opts))
114
- .timeout(FORCE_FETCH_TIMEOUT_MS).catch(err => logger.error('failed to get feature flag status', err));
127
+ return promiseTimeout(Rox.setup(ROLLOUT_KEY, opts), FORCE_FETCH_TIMEOUT_MS)
128
+ .catch(err => logger.error('failed to get feature flag status', err));
115
129
  }
116
130
  }
117
131
 
@@ -217,7 +217,7 @@ function put(url, body, headers = {}, timeout = DEFAULT_REQUEST_TIMEOUT) {
217
217
 
218
218
  /**
219
219
  * @param {string} url
220
- * @returns {Promise<superagent.Response>}
220
+ * @returns {Promise<Omit<superagent.Response, 'body'> & { body: Buffer }>}
221
221
  */
222
222
  function download(url) {
223
223
  logger.info('start to download', { url });
@@ -1,7 +1,7 @@
1
1
 
2
2
  const perf = require('./performance-logger');
3
3
  const localRunnerCache = require('./runnerFileCache');
4
- const servicesApi = require('./testimServicesApi.js');
4
+ const servicesApi = require('./testimServicesApi');
5
5
  const testimCustomToken = require('./testimCustomToken');
6
6
  const { CLI_MODE } = require('./constants');
7
7
 
@@ -24,12 +24,15 @@ function preloadSlowRequires(mode) {
24
24
  });
25
25
  }
26
26
 
27
+ /**
28
+ * @param {import('../runOptions').RunnerOptions} options
29
+ */
27
30
  async function initializeUserWithAuth(options) {
28
31
  const { project, token, lightweightMode, useLocalChromeDriver, useChromeLauncher, mode } = options;
29
32
 
30
- const lightweightModeGenral = Boolean(lightweightMode && lightweightMode.general);
33
+ const lightweightModeGeneral = Boolean(lightweightMode?.general);
31
34
  const localGrid = Boolean(useLocalChromeDriver || useChromeLauncher);
32
- const memoizationTTL = lightweightModeGenral ? TEN_HOURS_MS : FIVE_MINUTES_MS;
35
+ const memoizationTTL = lightweightModeGeneral ? TEN_HOURS_MS : FIVE_MINUTES_MS;
33
36
 
34
37
  perf.log('before initializeUserWithAuth');
35
38
  const result = await localRunnerCache.memoize(async () => {
@@ -41,7 +44,7 @@ async function initializeUserWithAuth(options) {
41
44
  lightweightMode,
42
45
  localGrid,
43
46
  });
44
- }, 'initializeUserWithAuth', memoizationTTL, { project, token, branchName: options.branch, lightweightModeGenral, localGrid })();
47
+ }, 'initializeUserWithAuth', memoizationTTL, { project, token, branchName: options.branch, lightweightModeGeneral, localGrid })();
45
48
  perf.log('after initializeUserWithAuth');
46
49
 
47
50
  testimCustomToken.initFromData(result.authData, options.project, options.token);
@@ -1,11 +1,14 @@
1
1
  const _ = require('lodash');
2
- const { promiseMap } = require('../utils');
3
2
  const localRunnerCache = require('./runnerFileCache');
4
- const servicesApi = require('./testimServicesApi.js');
3
+ const servicesApi = require('./testimServicesApi');
4
+ const { promiseMap } = require('../utils');
5
5
 
6
6
 
7
7
  const TEN_HOURS = 1000 * 60 * 60 * 10;
8
8
 
9
+ /**
10
+ * @param {import('../runOptions').RunnerOptions} options
11
+ */
9
12
  async function preloadTests(options) {
10
13
  if (!Array.isArray(options.testId) || !options.testId.length) {
11
14
  return {};
@@ -22,6 +22,7 @@ Promise.resolve().then(() => {
22
22
  global.xhr2 = require('./xhr2'); // this is inside a `then` to not block and let network requests start
23
23
  });
24
24
 
25
+ /** @param {import('../runOptions').RunnerOptions} options */
25
26
  async function prepare(options) {
26
27
  /**
27
28
  * @type {globalThis.Promise<void>}
@@ -61,16 +62,15 @@ async function prepare(options) {
61
62
 
62
63
  async function prepareMockNetwork(location) {
63
64
  logger.info('prepare MockNetwork', { location });
64
- /** @type {Buffer} */
65
- // @ts-expect-error There seems to be an actual bug in case the location is a URL.
66
- const rulesJsonBuf = await utils.getSourceAsBuffer(location);
65
+ const _rulesJson = await utils.getSourceAsBuffer(location);
66
+ const rulesJsonBuf = Buffer.isBuffer(_rulesJson) ? _rulesJson : _rulesJson.body;
67
67
  if (rulesJsonBuf.byteLength > MAX_RULE_FILE_SIZE_IN_MB * 1000000) {
68
68
  throw new Error(`${PREPARE_MOCK_NETWORK_ERROR_PREFIX} exceeded ${MAX_RULE_FILE_SIZE_IN_MB}MB`);
69
69
  }
70
70
 
71
71
  let rulesJson;
72
72
  try {
73
- rulesJson = JSON.parse(rulesJsonBuf);
73
+ rulesJson = JSON.parse(rulesJsonBuf.toString('utf-8'));
74
74
  } catch (error) {
75
75
  throw new Error(`${PREPARE_MOCK_NETWORK_ERROR_PREFIX} cannot be parsed.${os.EOL}${error}`);
76
76
  }
@@ -78,7 +78,7 @@ async function prepareMockNetwork(location) {
78
78
  const ajv = new Ajv();
79
79
  const valid = ajv.validate(mockNetworkRuleFileSchema, rulesJson);
80
80
  if (!valid) {
81
- const errors = ajv.errors.map((e, i) => `${++i}) ${e.dataPath} ${e.message}`).join(os.EOL);
81
+ const errors = ajv.errors?.map((e, i) => `${++i}) ${e.dataPath} ${e.message}`).join(os.EOL);
82
82
  throw new Error(`${PREPARE_MOCK_NETWORK_ERROR_PREFIX} is malformed.${os.EOL}${errors}`);
83
83
  }
84
84
 
@@ -140,7 +140,7 @@ async function getPlayerVersion() {
140
140
 
141
141
  /**
142
142
  * @param {string} location
143
- * @param {string | undefined} canary
143
+ * @param {boolean=} canary
144
144
  */
145
145
  async function getPlayerLocation(location, canary) {
146
146
  if (!isURL(location) || (isURL(location) && canary) || config.IS_ON_PREM) {
@@ -177,13 +177,20 @@ async function downloadAndUnzip(loc, playerFileName, isRetry = false) {
177
177
  }
178
178
  }
179
179
 
180
+ /**
181
+ * @param {string} location
182
+ * @param {boolean=} canary
183
+ */
180
184
  async function preparePlayer(location, canary) {
181
185
  logger.info('prepare player', { location, canary });
182
186
  const playerFileName = getPlayerDestination();
183
187
  return localRunnerCache.memoize(
184
- () => getPlayerLocation(location, canary)
185
- .then(loc => downloadAndUnzip(loc, playerFileName))
186
- .then(() => ({})),
188
+ async () => {
189
+ const loc = await getPlayerLocation(location, canary);
190
+ await downloadAndUnzip(loc, playerFileName);
191
+ // return a truthy value, so the caching has a value, and doesn't ignore
192
+ return {};
193
+ },
187
194
  'preparePlayer',
188
195
  MSEC_IN_HALF_DAY,
189
196
  [location, canary, playerFileName]
@@ -79,7 +79,15 @@ function decrypt(key, buffer) {
79
79
  const decrypted = decipher.update(encryptedText);
80
80
  return JSON.parse(Buffer.concat([decrypted, decipher.final()]));
81
81
  }
82
- // argument less memoize for functions with a global cache name
82
+ /**
83
+ * argument-less memoize for functions with a global cache name
84
+ * @template T
85
+ * @param {() => PromiseLike<T>} fn
86
+ * @param {string} fnName
87
+ * @param {number=} duration
88
+ * @param {*} parameters
89
+ * @returns {() => Promise<Awaited<T>>}
90
+ */
83
91
  function memoize(fn, fnName, duration = THREE_HOURS, parameters = undefined) {
84
92
  return Promise.method(async () => {
85
93
  if (!cacheEnabled) {
@@ -192,6 +192,27 @@ async function getTestPlanTestList(projectId, names, planIds, branch, intersecti
192
192
  }), { retries: DEFAULT_REQUEST_RETRY });
193
193
  }
194
194
 
195
+ /**
196
+ * @param {{
197
+ * projectId: string;
198
+ * labels: string[];
199
+ * testIds: string[];
200
+ * testNames: string[];
201
+ * testConfigNames?: string[];
202
+ * suiteNames: string[];
203
+ * suiteIds: string[];
204
+ * branch: string;
205
+ * rerunFailedByRunId?: string;
206
+ * testConfigIds?: string[];
207
+ * intersections: import('../runOptions').RunnerOptions['intersections'];
208
+ * }} param0
209
+ * @returns {globalThis.Promise<{
210
+ * tests: any[][];
211
+ * branch?: string;
212
+ * runName?: string;
213
+ * runExists?: boolean;
214
+ * }>}
215
+ */
195
216
  function getSuiteTestList({
196
217
  projectId, labels, testIds, testNames, testConfigNames, suiteNames, suiteIds, branch, rerunFailedByRunId, testConfigIds, intersections,
197
218
  }) {
@@ -263,7 +284,17 @@ function getGridById(companyId, projectId, gridId, browser, executionId) {
263
284
  return pRetry(() => getWithAuth(`/grid/${gridId}`, { companyId, projectId, browser, executionId, reqId: utils.guid() }), { retries: DEFAULT_REQUEST_RETRY });
264
285
  }
265
286
 
266
-
287
+ /**
288
+ * @param {{ projectId: string; token: string; branchName: string; lightweightMode?: import('../runOptions').LightweightSettings; localGrid: boolean; }} param0
289
+ * @returns {globalThis.Promise<{
290
+ * authData: { token: string; refreshToken: string; uid: string; ngrokToken?: string; isNgrokWhitelisted?: boolean; };
291
+ * editorConfig: { editorUrl: string };
292
+ * companyByProjectId: Awaited<ReturnType<import('services/src/company/companyService')['getCompanyByProjectIdUsingCache']>>;
293
+ * projectById: NonNullable<Awaited<ReturnType<import('services/src/commons/testimCache')['project']['getById']>>>;
294
+ * allGrids: import('services/src/commons/mongo/models/grid').RawGrid[];
295
+ * branchName: string | import('services/src/commons/mongo/models/branchesData').RawBranchesData | null;
296
+ * }>}
297
+ */
267
298
  async function initializeUserWithAuth({ projectId, token, branchName, lightweightMode, localGrid }) {
268
299
  try {
269
300
  return await pRetry(() => httpRequest.post({
@@ -278,14 +309,14 @@ async function initializeUserWithAuth({ projectId, token, branchName, lightweigh
278
309
  }), { retries: DEFAULT_REQUEST_RETRY });
279
310
  } catch (e) {
280
311
  logger.error('error initializing info from server', e);
281
- if (e && e.message && e.message.includes('Bad Request')) {
312
+ if (e?.message?.includes('Bad Request')) {
282
313
  throw new ArgError(
283
314
  'Error trying to retrieve CLI token. ' +
284
315
  'Your CLI token and project might not match. ' +
285
316
  'Please make sure to pass `--project` and `--token` that' +
286
317
  ' match to each other or make sure they match in your ~/.testim file.');
287
318
  }
288
- if (e && e.code && e.code.includes('ENOTFOUND')) {
319
+ if (e?.code?.includes('ENOTFOUND')) {
289
320
  throw new ArgError('Due to network connectivity issues, Testim CLI has been unable to connect to the Testim backend.');
290
321
  }
291
322
  throw e;
@@ -415,7 +446,7 @@ const updateTestDataArtifact = _.memoize(async (projectId, testId, testResultId,
415
446
  }
416
447
  const removeHiddenParamsInTestData = () => {
417
448
  const testDataValueClone = _.clone(testData);
418
- if (projectDefaults && projectDefaults.hiddenParams) {
449
+ if (projectDefaults?.hiddenParams) {
419
450
  const { hiddenParams } = projectDefaults;
420
451
  (hiddenParams || []).forEach((param) => {
421
452
  if (testDataValueClone[param]) {
@@ -521,7 +552,7 @@ module.exports = {
521
552
  getLabFeaturesByProjectId,
522
553
  uploadRunDataArtifact: Promise.method(uploadRunDataArtifact),
523
554
  updateTestDataArtifact: Promise.method(updateTestDataArtifact),
524
- initializeUserWithAuth: Promise.method(initializeUserWithAuth),
555
+ initializeUserWithAuth,
525
556
  addTestRetry,
526
557
  getHybridGridProvider,
527
558
  loadSfdcCredential,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@testim/testim-cli",
3
- "version": "3.255.0",
3
+ "version": "3.256.0",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@testim/testim-cli",
9
- "version": "3.255.0",
9
+ "version": "3.256.0",
10
10
  "license": "Proprietary",
11
11
  "dependencies": {
12
12
  "@applitools/eyes-sdk-core": "13.6.23",
@@ -1064,9 +1064,9 @@
1064
1064
  }
1065
1065
  },
1066
1066
  "node_modules/@sinonjs/commons": {
1067
- "version": "1.8.4",
1068
- "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.4.tgz",
1069
- "integrity": "sha512-RpmQdHVo8hCEHDVpO39zToS9jOhR6nw+/lQAzRNq9ErrGV9IeHM71XCn68svVl/euFeVW6BWX4p35gkhbOcSIQ==",
1067
+ "version": "1.8.5",
1068
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.5.tgz",
1069
+ "integrity": "sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA==",
1070
1070
  "dev": true,
1071
1071
  "dependencies": {
1072
1072
  "type-detect": "4.0.8"
@@ -2929,15 +2929,15 @@
2929
2929
  "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
2930
2930
  },
2931
2931
  "node_modules/chai": {
2932
- "version": "4.3.6",
2933
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
2934
- "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
2932
+ "version": "4.3.7",
2933
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz",
2934
+ "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==",
2935
2935
  "dev": true,
2936
2936
  "peer": true,
2937
2937
  "dependencies": {
2938
2938
  "assertion-error": "^1.1.0",
2939
2939
  "check-error": "^1.0.2",
2940
- "deep-eql": "^3.0.1",
2940
+ "deep-eql": "^4.1.2",
2941
2941
  "get-func-name": "^2.0.0",
2942
2942
  "loupe": "^2.3.1",
2943
2943
  "pathval": "^1.1.1",
@@ -4365,16 +4365,16 @@
4365
4365
  }
4366
4366
  },
4367
4367
  "node_modules/deep-eql": {
4368
- "version": "3.0.1",
4369
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
4370
- "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
4368
+ "version": "4.1.2",
4369
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.2.tgz",
4370
+ "integrity": "sha512-gT18+YW4CcW/DBNTwAmqTtkJh7f9qqScu2qFVlx7kCoeY9tlBu9cUcr7+I+Z/noG8INehS3xQgLpTtd/QUTn4w==",
4371
4371
  "dev": true,
4372
4372
  "peer": true,
4373
4373
  "dependencies": {
4374
4374
  "type-detect": "^4.0.0"
4375
4375
  },
4376
4376
  "engines": {
4377
- "node": ">=0.12"
4377
+ "node": ">=6"
4378
4378
  }
4379
4379
  },
4380
4380
  "node_modules/deep-equal": {
@@ -8015,9 +8015,9 @@
8015
8015
  }
8016
8016
  },
8017
8017
  "node_modules/keyv": {
8018
- "version": "4.5.0",
8019
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.0.tgz",
8020
- "integrity": "sha512-2YvuMsA+jnFGtBareKqgANOEKe1mk3HKiXu2fRmAfyxG0MJAywNhi5ttWA3PMjl4NmpyjZNbFifR2vNjW1znfA==",
8018
+ "version": "4.5.2",
8019
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
8020
+ "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==",
8021
8021
  "dependencies": {
8022
8022
  "json-buffer": "3.0.1"
8023
8023
  }
@@ -8390,9 +8390,9 @@
8390
8390
  }
8391
8391
  },
8392
8392
  "node_modules/loglevel": {
8393
- "version": "1.8.0",
8394
- "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz",
8395
- "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==",
8393
+ "version": "1.8.1",
8394
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz",
8395
+ "integrity": "sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==",
8396
8396
  "engines": {
8397
8397
  "node": ">= 0.6.0"
8398
8398
  },
@@ -8407,9 +8407,9 @@
8407
8407
  "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g=="
8408
8408
  },
8409
8409
  "node_modules/loupe": {
8410
- "version": "2.3.5",
8411
- "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.5.tgz",
8412
- "integrity": "sha512-KNGVjhsXDxvY/cYE8GNi7SBaJSfJIT+/+/8GlprqBXpoU6cSR7/RT7OBJOsoYtyxq0L3q6oIcO8tX7dbEEXr3A==",
8410
+ "version": "2.3.6",
8411
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz",
8412
+ "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==",
8413
8413
  "dev": true,
8414
8414
  "peer": true,
8415
8415
  "dependencies": {
@@ -16966,9 +16966,9 @@
16966
16966
  "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="
16967
16967
  },
16968
16968
  "@sinonjs/commons": {
16969
- "version": "1.8.4",
16970
- "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.4.tgz",
16971
- "integrity": "sha512-RpmQdHVo8hCEHDVpO39zToS9jOhR6nw+/lQAzRNq9ErrGV9IeHM71XCn68svVl/euFeVW6BWX4p35gkhbOcSIQ==",
16969
+ "version": "1.8.5",
16970
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.5.tgz",
16971
+ "integrity": "sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA==",
16972
16972
  "dev": true,
16973
16973
  "requires": {
16974
16974
  "type-detect": "4.0.8"
@@ -18483,15 +18483,15 @@
18483
18483
  "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
18484
18484
  },
18485
18485
  "chai": {
18486
- "version": "4.3.6",
18487
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
18488
- "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
18486
+ "version": "4.3.7",
18487
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz",
18488
+ "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==",
18489
18489
  "dev": true,
18490
18490
  "peer": true,
18491
18491
  "requires": {
18492
18492
  "assertion-error": "^1.1.0",
18493
18493
  "check-error": "^1.0.2",
18494
- "deep-eql": "^3.0.1",
18494
+ "deep-eql": "^4.1.2",
18495
18495
  "get-func-name": "^2.0.0",
18496
18496
  "loupe": "^2.3.1",
18497
18497
  "pathval": "^1.1.1",
@@ -19655,9 +19655,9 @@
19655
19655
  }
19656
19656
  },
19657
19657
  "deep-eql": {
19658
- "version": "3.0.1",
19659
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
19660
- "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
19658
+ "version": "4.1.2",
19659
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.2.tgz",
19660
+ "integrity": "sha512-gT18+YW4CcW/DBNTwAmqTtkJh7f9qqScu2qFVlx7kCoeY9tlBu9cUcr7+I+Z/noG8INehS3xQgLpTtd/QUTn4w==",
19661
19661
  "dev": true,
19662
19662
  "peer": true,
19663
19663
  "requires": {
@@ -22525,9 +22525,9 @@
22525
22525
  }
22526
22526
  },
22527
22527
  "keyv": {
22528
- "version": "4.5.0",
22529
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.0.tgz",
22530
- "integrity": "sha512-2YvuMsA+jnFGtBareKqgANOEKe1mk3HKiXu2fRmAfyxG0MJAywNhi5ttWA3PMjl4NmpyjZNbFifR2vNjW1znfA==",
22528
+ "version": "4.5.2",
22529
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
22530
+ "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==",
22531
22531
  "requires": {
22532
22532
  "json-buffer": "3.0.1"
22533
22533
  }
@@ -22857,9 +22857,9 @@
22857
22857
  }
22858
22858
  },
22859
22859
  "loglevel": {
22860
- "version": "1.8.0",
22861
- "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz",
22862
- "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA=="
22860
+ "version": "1.8.1",
22861
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz",
22862
+ "integrity": "sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg=="
22863
22863
  },
22864
22864
  "loglevel-plugin-prefix": {
22865
22865
  "version": "0.8.4",
@@ -22867,9 +22867,9 @@
22867
22867
  "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g=="
22868
22868
  },
22869
22869
  "loupe": {
22870
- "version": "2.3.5",
22871
- "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.5.tgz",
22872
- "integrity": "sha512-KNGVjhsXDxvY/cYE8GNi7SBaJSfJIT+/+/8GlprqBXpoU6cSR7/RT7OBJOsoYtyxq0L3q6oIcO8tX7dbEEXr3A==",
22870
+ "version": "2.3.6",
22871
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz",
22872
+ "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==",
22873
22873
  "dev": true,
22874
22874
  "peer": true,
22875
22875
  "requires": {