@testim/testim-cli 3.261.0 → 3.263.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 (39) hide show
  1. package/cli.js +11 -5
  2. package/commons/featureFlags.js +1 -0
  3. package/commons/testimServicesApi.js +10 -7
  4. package/executionQueue.js +9 -1
  5. package/npm-shrinkwrap.json +52 -52
  6. package/package.json +1 -1
  7. package/player/stepActions/RefreshStepAction.js +7 -4
  8. package/player/stepActions/baseJsStepAction.js +45 -46
  9. package/player/stepActions/dropFileStepAction.js +11 -12
  10. package/player/stepActions/evaluateExpressionStepAction.js +32 -33
  11. package/player/stepActions/extensionOnlyStepAction.js +3 -4
  12. package/player/stepActions/extractTextStepAction.js +8 -10
  13. package/player/stepActions/hoverStepAction.js +3 -3
  14. package/player/stepActions/locateStepAction.js +39 -34
  15. package/player/stepActions/mouseStepAction.js +36 -34
  16. package/player/stepActions/navigationStepAction.js +7 -8
  17. package/player/stepActions/scrollStepAction.js +22 -22
  18. package/player/stepActions/stepAction.js +21 -21
  19. package/player/stepActions/stepActionRegistrar.js +63 -58
  20. package/player/stepActions/submitStepAction.js +2 -3
  21. package/player/stepActions/textStepAction.js +14 -14
  22. package/player/stepActions/textValidationStepAction.js +50 -38
  23. package/player/stepActions/wheelStepAction.js +5 -11
  24. package/polyfills/Array.prototype.at.js +13 -0
  25. package/polyfills/index.js +1 -0
  26. package/processHandler.js +2 -0
  27. package/reports/junitReporter.js +18 -1
  28. package/runOptions.d.ts +4 -0
  29. package/runOptions.js +8 -1
  30. package/runner.js +7 -0
  31. package/runners/TestPlanRunner.js +20 -19
  32. package/runners/runnerUtils.js +1 -2
  33. package/testRunHandler.js +18 -9
  34. package/testRunStatus.js +209 -157
  35. package/utils/index.js +9 -2
  36. package/workers/BaseWorker.js +11 -0
  37. package/workers/WorkerExtension.js +117 -91
  38. package/workers/WorkerSelenium.js +8 -3
  39. package/player/stepActions/scripts/polyfills.js +0 -393
@@ -2,7 +2,6 @@
2
2
 
3
3
  const StepAction = require('./stepAction');
4
4
  const setTextScript = require('./scripts/setText');
5
- const Promise = require('bluebird');
6
5
  const { codeSnippets } = require('../../commons/getSessionPlayerRequire');
7
6
  const dispatchFocus = require('./scripts/focusElement');
8
7
  const sessionPlayer = require('../../commons/getSessionPlayerRequire');
@@ -12,17 +11,18 @@ const constants = sessionPlayer.commonConstants.stepResult;
12
11
  const setTextDraftJs = codeSnippets?.setTextDraftJs;
13
12
 
14
13
  class TextStepAction extends StepAction {
15
- setValueNative() {
14
+ async setValueNative() {
16
15
  const context = this.context;
17
16
  const target = this.getTarget();
18
17
  if (!this.step.delayBetweenChars) {
19
18
  return this.driver.setValue(target.seleniumElement, context.stepText);
20
19
  }
21
20
 
22
- return this.driver.elementIdClear(extractElementId(target.seleniumElement)).then(async () => await this.setTextDelayed());
21
+ await this.driver.elementIdClear(extractElementId(target.seleniumElement));
22
+ return await this.setTextDelayed();
23
23
  }
24
24
 
25
- setValueJS() {
25
+ async setValueJS() {
26
26
  const step = this.step;
27
27
  const context = this.context;
28
28
  const target = context.data[step.targetId || 'targetId'];
@@ -33,8 +33,8 @@ class TextStepAction extends StepAction {
33
33
  return this.driver.executeJS(setTextDraftJs(target.locatedElement, context.stepText));
34
34
  }
35
35
 
36
- if (!events || !events.length) {
37
- return Promise.resolve();
36
+ if (!events?.length) {
37
+ return undefined;
38
38
  }
39
39
 
40
40
  const eventMessage = {
@@ -59,8 +59,8 @@ class TextStepAction extends StepAction {
59
59
  // values between 0 and -1 -_-.
60
60
  const eventParam = this.driver.isEdge() ? JSON.stringify(eventMessage) : eventMessage;
61
61
 
62
- return this.driver.executeCodeAsync(setTextCode, timeout, eventParam)
63
- .then(result => ({ success: Boolean(result.value?.success) }));
62
+ const result = await this.driver.executeCodeAsync(setTextCode, timeout, eventParam);
63
+ return { success: Boolean(result.value?.success) };
64
64
  }
65
65
 
66
66
  async setTextDelayed() {
@@ -75,7 +75,7 @@ class TextStepAction extends StepAction {
75
75
  }
76
76
  }
77
77
 
78
- setValueAppendNative() {
78
+ async setValueAppendNative() {
79
79
  const keys = [];
80
80
  const context = this.context;
81
81
  const target = this.getTarget();
@@ -86,12 +86,12 @@ class TextStepAction extends StepAction {
86
86
  return this.driver.elementIdValue(extractElementId(target.seleniumElement), keys);
87
87
  }
88
88
 
89
- return Promise.resolve(this.setTextDelayed());
89
+ return this.setTextDelayed();
90
90
  }
91
- return Promise.reject(new Error('missing selenium element'));
91
+ throw new Error('missing selenium element');
92
92
  }
93
93
 
94
- performAction() {
94
+ async performAction() {
95
95
  const target = this.getTarget();
96
96
  const forceJsEvent = this.driver.isSafari() &&
97
97
  target.locatedElement && target.locatedElement.shadowPath &&
@@ -101,11 +101,11 @@ class TextStepAction extends StepAction {
101
101
  if (this.step.nativeEvents) {
102
102
  return this.setValueAppendNative();
103
103
  }
104
- return Promise.resolve({
104
+ return {
105
105
  success: false,
106
106
  errorType: constants.TEXT_ACTION_FAILURE,
107
107
  resultInfo: { error: "'Append Text' is only supported in Native Mode" },
108
- });
108
+ };
109
109
  }
110
110
  if (this.step.nativeEvents && !forceJsEvent) {
111
111
  return this.setValueNative();
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
 
3
- const Promise = require('bluebird');
4
3
  const sessionPlayer = require('../../commons/getSessionPlayerRequire');
5
4
  const StepAction = require('./stepAction');
6
5
 
@@ -9,49 +8,62 @@ const paramEvaluator = sessionPlayer.stepParamExpressionEvaluator;
9
8
  const utils = sessionPlayer.utils;
10
9
 
11
10
  class TextValidationStepAction extends StepAction {
12
- performAction(stepActionFactory) {
11
+ async performAction(stepActionFactory) {
13
12
  const step = this.step;
14
13
  const context = this.context;
15
14
  const target = this.getTarget();
16
15
  const frameHandler = this.frameHandler;
17
16
 
18
-
19
- return new Promise(resolve => {
20
- const onFail = resultInfo => {
21
- resolve({ errorType: constants.TEXT_COMPARE_FAILURE, resultInfo, success: false });
22
- };
23
- this.stepActionUtils.extractTargetText(target)
24
- .then(text => {
25
- if (paramEvaluator) {
26
- const expected = paramEvaluator.computeExpression(step.expression2, context, this.exportsGlobal, this.exportsTest);
27
- return {
28
- actual: text,
29
- expected: expected.evaluatedText,
30
- };
31
- }
32
- return stepActionFactory.executeStep(step.expression2, context, frameHandler, this.exportsGlobal, this.locateElementPlayer, this.exportsTest)
33
- .then(res => ({
34
- actual: text,
35
- expected: res.evaluatedText,
36
- }));
37
- })
38
- .then(({ actual, expected }) => {
39
- try {
40
- const compareResult = utils.compareOrMatch(expected, actual);
41
- return compareResult ?
42
- resolve({ success: true }) :
43
- onFail({ expected: String(expected), actual });
44
- } catch (err) {
45
- return onFail({ expected: expected.toString(), actual });
46
- }
47
- })
48
- .catch(err => resolve({
17
+ try {
18
+ const text = await this.stepActionUtils.extractTargetText(target);
19
+ let actual;
20
+ let expected;
21
+ if (paramEvaluator) {
22
+ const evaluation = paramEvaluator.computeExpression(
23
+ step.expression2,
24
+ context,
25
+ this.exportsGlobal,
26
+ this.exportsTest,
27
+ );
28
+ actual = text;
29
+ expected = evaluation.evaluatedText;
30
+ } else {
31
+ const res = await stepActionFactory.executeStep(
32
+ step.expression2,
33
+ context,
34
+ frameHandler,
35
+ this.exportsGlobal,
36
+ this.locateElementPlayer,
37
+ this.exportsTest,
38
+ );
39
+ actual = text;
40
+ expected = res.evaluatedText;
41
+ }
42
+ try {
43
+ const compareResult = utils.compareOrMatch(expected, actual);
44
+ if (compareResult) {
45
+ return { success: true };
46
+ }
47
+ return {
49
48
  success: false,
50
- reason: err.message,
51
- exception: err,
52
- shouldRetry: true,
53
- }));
54
- });
49
+ errorType: constants.TEXT_COMPARE_FAILURE,
50
+ resultInfo: { expected: String(expected), actual },
51
+ };
52
+ } catch (err) {
53
+ return {
54
+ success: false,
55
+ errorType: constants.TEXT_COMPARE_FAILURE,
56
+ resultInfo: { expected: expected.toString(), actual },
57
+ };
58
+ }
59
+ } catch (err) {
60
+ return {
61
+ success: false,
62
+ reason: err.message,
63
+ exception: err,
64
+ shouldRetry: true,
65
+ };
66
+ }
55
67
  }
56
68
  }
57
69
 
@@ -1,18 +1,17 @@
1
1
  'use strict';
2
2
 
3
- const Promise = require('bluebird');
4
3
  const StepAction = require('./stepAction');
5
4
  const wheelScript = require('./scripts/wheel');
6
5
  const { codeSnippets } = require('../../commons/getSessionPlayerRequire');
7
6
 
8
7
  class WheelStepAction extends StepAction {
9
- performAction() {
8
+ async performAction() {
10
9
  const step = this.step;
11
10
  const context = this.context;
12
11
  const events = step.events;
13
12
 
14
- if (!events || !events.length) {
15
- return Promise.resolve();
13
+ if (!events?.length) {
14
+ return undefined;
16
15
  }
17
16
 
18
17
  const eventMessage = {
@@ -38,13 +37,8 @@ class WheelStepAction extends StepAction {
38
37
  // values between 0 and -1 -_-.
39
38
  const eventParam = this.driver.isEdge() ? JSON.stringify(eventMessage) : eventMessage;
40
39
 
41
- return this.driver.executeCodeAsync(wheelCode, timeout, eventParam)
42
- .then(result => {
43
- if (result.value && result.value.state === 'success') {
44
- return { success: true };
45
- }
46
- return { success: false };
47
- });
40
+ const result = await this.driver.executeCodeAsync(wheelCode, timeout, eventParam);
41
+ return { success: result.value?.state === 'success' };
48
42
  }
49
43
  }
50
44
 
@@ -0,0 +1,13 @@
1
+ /* eslint-disable no-extend-native */
2
+
3
+ Array.prototype.at = Array.prototype.at || function (index) {
4
+ const relativeIndex = Number.isInteger(index) ? index : 0;
5
+
6
+ const indexToRead = relativeIndex >= 0 ? relativeIndex : this.length + relativeIndex;
7
+
8
+ if (indexToRead < 0 || indexToRead >= this.length) {
9
+ return undefined;
10
+ }
11
+
12
+ return this[indexToRead];
13
+ };
@@ -0,0 +1 @@
1
+ require('./Array.prototype.at');
package/processHandler.js CHANGED
@@ -5,6 +5,7 @@
5
5
  const { promiseTimeout, promiseMap } = require('./utils');
6
6
  const logger = require('./commons/logger').getLogger('process-handler');
7
7
 
8
+ /** @type {Array<() => PromiseLike<void>>} */
8
9
  const exitHooks = [];
9
10
 
10
11
  /**
@@ -67,6 +68,7 @@ module.exports = function (onExit, _process = process) {
67
68
  });
68
69
  };
69
70
 
71
+ /** @param {() => PromiseLike<void>} hook */
70
72
  module.exports.registerExitHook = function (hook) {
71
73
  exitHooks.push(hook);
72
74
  };
@@ -52,7 +52,17 @@ function getPrintName(testResult) {
52
52
  const testDataNumber = typeof testData.total === 'number' ? ` - ${testData.index} / ${testData.total} Data set` : '';
53
53
  return `${testResult.name}${testDataNumber}`;
54
54
  }
55
-
55
+ function getVisitedUrlsList(testResult) {
56
+ if (!testResult.visitedUrlsList) {
57
+ console.log('No URLs found:', 'Please contact our support team or remove the --urls flag from the CLI command');
58
+ }
59
+ const visitedUrls = testResult.visitedUrlsList || '';
60
+ return `${visitedUrls}`;
61
+ }
62
+ function getVisitedUrlsJson(testResult) {
63
+ const visitedUrls = testResult.visitedUrlsJson || '';
64
+ return `${visitedUrls}`;
65
+ }
56
66
  async function report(editorUrl, testPlanResults, projectId, branch, classname, options) {
57
67
  function createTestCaseObject(testResult) {
58
68
  const testResultUrl = utils.getTestUrl(editorUrl, projectId, testResult.testId, testResult.resultId, branch);
@@ -79,7 +89,14 @@ async function report(editorUrl, testPlanResults, projectId, branch, classname,
79
89
  if (isSkippedTest(testResult) && utils.isQuarantineAndNotRemoteRun(testResult, options) && featureAvailabilityService.isTestStatusEnabled) {
80
90
  testResultObject.skipped = {};
81
91
  }
92
+
82
93
  testResultObject['system-out'] = testResultUrl;
94
+
95
+ if (options.urls) {
96
+ testResultObject['visited-urls-list'] = getVisitedUrlsList(testResult);
97
+ testResultObject['visited-urls-json'] = getVisitedUrlsJson(testResult);
98
+ }
99
+
83
100
  return testResultObject;
84
101
  }
85
102
 
package/runOptions.d.ts CHANGED
@@ -281,6 +281,10 @@ interface RunnerOptions extends Partial<Omit<TunnelOptions, 'tunnelOnlyMode' | '
281
281
  // #region intersections
282
282
  intersections: { labels?: string[]; suiteNames?: string[]; suiteIds?: string[] };
283
283
  // #endregion
284
+
285
+ // #region visited URLs
286
+ urls?: string;
287
+ // #endregion
284
288
  }
285
289
 
286
290
  type Options = |
package/runOptions.js CHANGED
@@ -112,6 +112,10 @@ const printUsage = () => {
112
112
  return line.includes('--high-speed'); // high speed mode was renamed to turbo mode
113
113
  }
114
114
 
115
+ function isUrls(line) {
116
+ return line.includes('--urls');
117
+ }
118
+
115
119
  function isTestStartTimeout(line) {
116
120
  return line.includes('--test-start-timeout');
117
121
  }
@@ -119,7 +123,7 @@ const printUsage = () => {
119
123
  program.help((txt) => {
120
124
  const lines = txt.split('\n');
121
125
  return lines
122
- .filter(
126
+ .filter( // hide CLI options
123
127
  (ln) =>
124
128
  !isExtOnlyOption(ln) &&
125
129
  !isParamsJsonOption(ln) &&
@@ -132,6 +136,7 @@ const printUsage = () => {
132
136
  !isSaveRCALocally(ln) &&
133
137
  !isExitCodeIgnoreFailingTests(ln) &&
134
138
  !isDeprecatedHighSpeed(ln) &&
139
+ !isUrls(ln) &&
135
140
  !isTestStartTimeout(ln)
136
141
  )
137
142
  .join('\n');
@@ -172,6 +177,7 @@ program
172
177
  .option('-n, --name [test-name]', 'test name to run', collect, [])
173
178
  .option('--project [project-id]', 'project ID')
174
179
  .option('-r, --report-file [report junit xml path]', 'where to save junit xml results file')
180
+ .option('--urls', 'add step urls to the junit report')
175
181
  .option('--override-report-file-classname [override-report-file-classname]', 'custom junit class name for the junit reporter')
176
182
  .option('--reporters [names]', 'report types', list)
177
183
  .option('-h, --host [host-name]', 'host name or ip containing the selenium grid')
@@ -1108,6 +1114,7 @@ module.exports = {
1108
1114
  files: [program.files].flat(),
1109
1115
  webpackConfig: program.webpackConfig,
1110
1116
  reportFile: program.reportFile,
1117
+ urls: program.urls,
1111
1118
  reportFileClassname: program.overrideReportFileClassname,
1112
1119
  reporters: program.reporters,
1113
1120
  project: program.project,
package/runner.js CHANGED
@@ -310,6 +310,13 @@ async function init(options) {
310
310
  validateOptionsForCompany(options, companyByProjectId);
311
311
  await Promise.all([featureFlagsReady, socketConnected]);
312
312
 
313
+ if (options.browser && featureFlags.flags.dec2022eolBrowsers.isEnabled()) {
314
+ const browser = utils.getBrowserInfo(options.browser);
315
+ if (browser.eol) {
316
+ throw new ArgError(`Unsupported browser: ${browser.browserName}`);
317
+ }
318
+ }
319
+
313
320
  perf.log('after featureFlagsReady and socketConnected');
314
321
  setSystemInfo(options, editorConfig);
315
322
  setCompany(options, companyByProjectId);
@@ -1,29 +1,30 @@
1
1
  'use strict';
2
2
 
3
3
  const _ = require('lodash');
4
- const constants = require('../commons/constants');
5
-
6
- const TESTIM_RUN_STATUS = constants.testRunStatus;
4
+ const utils = require('../utils');
5
+ const Logger = require('../commons/logger');
6
+ const config = require('../commons/config');
7
7
  const reporter = require('../reports/reporter');
8
- const RealDataService = require('../commons/socket/realDataService');
9
- const testimServicesApi = require('../commons/testimServicesApi');
10
- const testimCustomToken = require('../commons/testimCustomToken');
8
+ const constants = require('../commons/constants');
11
9
  const TestRunStatus = require('../testRunStatus');
12
- const analyticsService = require('../services/analyticsService');
10
+ const perf = require('../commons/performance-logger');
13
11
  const gridService = require('../services/gridService');
14
12
  const branchService = require('../services/branchService');
15
- const config = require('../commons/config');
16
13
  const ParallelWorkerManager = require('./ParallelWorkerManager');
17
- const utils = require('../utils');
18
- const { getSuite, calcTestResultStatus, validateConfig } = require('./runnerUtils');
14
+ const analyticsService = require('../services/analyticsService');
15
+ const testimServicesApi = require('../commons/testimServicesApi');
16
+ const testimCustomToken = require('../commons/testimCustomToken');
17
+ const RealDataService = require('../commons/socket/realDataService');
19
18
  const { StopRunOnError, ArgError } = require('../errors');
20
- const Logger = require('../commons/logger');
21
- const perf = require('../commons/performance-logger');
19
+ const { getSuite, calcTestResultStatus, validateConfig } = require('./runnerUtils');
22
20
 
23
21
  const guid = utils.guid;
22
+ const TESTIM_RUN_STATUS = constants.testRunStatus;
24
23
  const logger = Logger.getLogger('test-plan-runner');
25
24
  const TDK_CHILD_RESULTS_TIMEOUT = 1000 * 60 * 5;
26
25
 
26
+ /** @typedef {Awaited<ReturnType<typeof getSuite>>['tests'][number]} ExecutionList */
27
+
27
28
  class TestPlanRunner {
28
29
  /**
29
30
  * @param {string=} customExtensionLocalLocation
@@ -35,9 +36,9 @@ class TestPlanRunner {
35
36
 
36
37
  /**
37
38
  * @private
38
- * @param {any[]} beforeTests
39
- * @param {any[]} tests
40
- * @param {any[]} afterTests
39
+ * @param {ExecutionList} beforeTests
40
+ * @param {ExecutionList} tests
41
+ * @param {ExecutionList} afterTests
41
42
  * @param {string} branchToUse
42
43
  * @param {import('../runOptions').RunnerOptions} tpOptions
43
44
  * @param {string} executionId
@@ -213,9 +214,9 @@ class TestPlanRunner {
213
214
 
214
215
  /**
215
216
  * @private
216
- * @param {any[]} beforeTests
217
- * @param {any[]} tests
218
- * @param {any[]} afterTests
217
+ * @param {ExecutionList} beforeTests
218
+ * @param {ExecutionList} tests
219
+ * @param {ExecutionList} afterTests
219
220
  * @param {import('../runOptions').RunnerOptions} tpOptions
220
221
  * @param {string} testPlanName
221
222
  * @param {string | null} testPlanId
@@ -285,7 +286,7 @@ class TestPlanRunner {
285
286
  });
286
287
 
287
288
  function flattenTestListData(testPlansData) {
288
- return _.flattenDeep(Object.keys(testPlansData).map(tpId => testPlansData[tpId])).reduce((all, testRun) => _.concat(all, testRun.beforeTests, testRun.tests, testRun.afterTests), []);
289
+ return _.flattenDeep(Object.values(testPlansData)).reduce((all, testRun) => all.concat(testRun.beforeTests, testRun.tests, testRun.afterTests), []);
289
290
  }
290
291
 
291
292
  const testPlansResults = {};
@@ -53,9 +53,8 @@ function calcTestResultStatus(tests) {
53
53
 
54
54
 
55
55
  /**
56
- * @template T
57
56
  * @param {import('../runOptions').RunnerOptions} options
58
- * @param {T[]} testList
57
+ * @param {import('./TestPlanRunner').ExecutionList} testList
59
58
  */
60
59
  async function validateConfig(options, testList) {
61
60
  const supportedBrowsers = options.mode === 'extension' ? [
package/testRunHandler.js CHANGED
@@ -23,6 +23,14 @@ const MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE = 20 * 1000; // max size, in characters
23
23
  const canSendRunDataOverUrl = (runData) => JSON.stringify(runData).length < MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE;
24
24
 
25
25
  class TestRun {
26
+ /**
27
+ * @param {string} executionId
28
+ * @param {string} executionName
29
+ * @param {*} test
30
+ * @param {import('./runOptions').RunnerOptions} options
31
+ * @param {string} branchToUse
32
+ * @param {import('./testRunStatus')} testRunStatus
33
+ */
26
34
  constructor(executionId, executionName, test, options, branchToUse, testRunStatus) {
27
35
  this._executionId = executionId;
28
36
  this._executionName = executionName;
@@ -33,7 +41,7 @@ class TestRun {
33
41
  this._code = test.code;
34
42
  this._baseUrl = options.baseUrl || test.baseUrl || test.testConfig.baseUrl;
35
43
  this._nativeApp = test.nativeApp;
36
- this._overrideTestConfigId = test.overrideTestConfig && test.overrideTestConfig.id;
44
+ this._overrideTestConfigId = test.overrideTestConfig?.id;
37
45
  this._options = options;
38
46
  this._branch = branchToUse;
39
47
  this._maxRetryCount = options.retries;
@@ -43,7 +51,7 @@ class TestRun {
43
51
  this._totalRetryCount = 1;
44
52
 
45
53
  this._testRunStatus = testRunStatus;
46
- const shouldUpdateConfig = !(test.runConfig && test.runConfig.isMobileWeb) && options.browser;
54
+ const shouldUpdateConfig = !test.runConfig?.isMobileWeb && options.browser;
47
55
  this._runConfig = shouldUpdateConfig ? utils.getRunConfigByBrowserName(options.browser, options.saucelabs, options.browserstack) : test.runConfig;
48
56
  this.clearTestResultFinished = Promise.resolve();
49
57
 
@@ -181,20 +189,22 @@ class TestRun {
181
189
  runRequestParams.lightweightMode = this._options.lightweightMode;
182
190
  }
183
191
 
184
- if (this._options.lightweightMode && this._options.lightweightMode.general) {
192
+ if (this._options.lightweightMode?.general) {
185
193
  runRequestParams.company = this._options.company;
186
194
  const runData = this.getRunData();
187
195
  runRequestParams.lightweightMode.isRunDataSentInUrl = canSendRunDataOverUrl(runData);
196
+ const stringifiedLength = JSON.stringify(runData).length;
197
+ const testId = this.getTestId();
188
198
  if (runRequestParams.lightweightMode.isRunDataSentInUrl) {
189
199
  runRequestParams.runData = runData;
190
- logger.info(`Run data sent as URL param, test id: ${this.getTestId()} run data length: ${JSON.stringify(runData).length}`);
200
+ logger.info(`Run data sent as URL param, test id: ${testId} run data length: ${stringifiedLength}`);
191
201
  } else {
192
- logger.warn(`Run data is too big to be sent as a URL param. Test id: ${this.getTestId()}, run data size: ${JSON.stringify(runData).length} (limit: ${MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE} characters)`);
202
+ logger.warn(`Run data is too big to be sent as a URL param. Test id: ${testId}, run data size: ${stringifiedLength} (limit: ${MAX_LIGHTWEIGHT_MODE_RUN_DATA_SIZE} characters)`);
193
203
  }
194
204
  runRequestParams.isLocalRun = Boolean(this._options.useLocalChromeDriver || this._options.useChromeLauncher);
195
205
  }
196
206
 
197
- if (this._options.lightweightMode && this._options.lightweightMode.preloadTests && this._options.useChromeLauncher) {
207
+ if (this._options.lightweightMode?.preloadTests && this._options.useChromeLauncher) {
198
208
  const preloadedTests = await preloadTests(this._options);
199
209
  runRequestParams.preloadedTest = preloadedTests[runRequestParams.testId];
200
210
  }
@@ -259,8 +269,7 @@ class TestRun {
259
269
  }
260
270
  const mustClearPreviousStepResults = (this._timeoutRetryCount > 1 || this._retryCount > 1);
261
271
 
262
- if (this._options.lightweightMode && this._options.lightweightMode.disableResults &&
263
- !mustClearPreviousStepResults && canSendRunDataOverUrl(runData)) {
272
+ if (this._options.lightweightMode?.disableResults && !mustClearPreviousStepResults && canSendRunDataOverUrl(runData)) {
264
273
  return Promise.resolve();
265
274
  }
266
275
 
@@ -574,7 +583,7 @@ class TestRun {
574
583
  this._originalTestResultId = this._originalTestResultId || this._previousTestResultId;
575
584
  this._testResultId = utils.guid();
576
585
 
577
- if (this._options.lightweightMode && this._options.lightweightMode.onlyTestIdsNoSuite) {
586
+ if (this._options.lightweightMode?.onlyTestIdsNoSuite) {
578
587
  return;
579
588
  }
580
589