@testomatio/reporter 2.15.0 → 2.16.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.
@@ -34,7 +34,8 @@ const HOOK_EXECUTION_ORDER = {
34
34
  };
35
35
  // codeceptjs workers are self-contained
36
36
  data_storage_js_1.dataStorage.isFileStorage = false;
37
- const DATA_REGEXP = /[|\s]+?(\{".*\}|\[.*\])/;
37
+ // CodeceptJS appends the serialized data row of a data-driven test to its title
38
+ const DATA_REGEXP = / \| (\{.*\}|\[.*\]|null|"(?:\\.|[^"\\])*")((?:\s+@[a-zA-Z0-9-_]+)*)$/;
38
39
  if (MAJOR_VERSION < 3) {
39
40
  console.log('🔴 This reporter works with CodeceptJS 3+, please update your tests');
40
41
  }
@@ -298,16 +299,31 @@ function stripExampleFromTitle(title) {
298
299
  const res = title.match(DATA_REGEXP);
299
300
  if (!res)
300
301
  return { title, example: null };
302
+ let example = null;
303
+ let exampleParsed = false;
301
304
  try {
302
- const example = JSON.parse(res[1]);
303
- title = title.replace(DATA_REGEXP, '').trim();
304
- return { title, example };
305
+ example = JSON.parse(res[1]);
306
+ exampleParsed = true;
305
307
  }
306
308
  catch (e) {
307
- // If JSON parsing fails, return title without example
308
- debug('Failed to parse example JSON:', res[1], e.message);
309
- return { title: title.replace(DATA_REGEXP, '').trim(), example: null };
309
+ try {
310
+ example = JSON.parse(res[1].slice(1, -1));
311
+ exampleParsed = true;
312
+ }
313
+ catch (e2) {
314
+ debug('Failed to parse example from title:', res[1]);
315
+ }
310
316
  }
317
+ let baseTitle = title.slice(0, res.index).trim();
318
+ if (exampleParsed && baseTitle.includes('${current}')) {
319
+ baseTitle = baseTitle.replaceAll('${current}', formatExample(example));
320
+ }
321
+ return { title: `${baseTitle}${res[2]}`, example };
322
+ }
323
+ function formatExample(example) {
324
+ if (example !== null && typeof example === 'object')
325
+ return JSON.stringify(example);
326
+ return String(example);
311
327
  }
312
328
  function stripTagsFromTitle(title) {
313
329
  // Remove @tags from the end of titles (e.g., "Hooks Test Suite @hooks" -> "Hooks Test Suite")
@@ -36,6 +36,7 @@ declare class TestomatioPipe implements Pipe {
36
36
  store: any;
37
37
  title: any;
38
38
  sharedRun: boolean;
39
+ sharedRunShards: number;
39
40
  sharedRunTimeout: number;
40
41
  groupTitle: any;
41
42
  env: string;
@@ -76,11 +76,14 @@ class TestomatioPipe {
76
76
  this.store = store || {};
77
77
  this.title = params.title || process.env.TESTOMATIO_TITLE;
78
78
  this.sharedRun = !!process.env.TESTOMATIO_SHARED_RUN;
79
+ this.sharedRunShards = process.env.TESTOMATIO_SHARDS
80
+ ? parseInt(process.env.TESTOMATIO_SHARDS, 10) || undefined
81
+ : undefined;
79
82
  this.sharedRunTimeout = process.env.TESTOMATIO_SHARED_RUN_TIMEOUT
80
83
  ? parseInt(process.env.TESTOMATIO_SHARED_RUN_TIMEOUT, 10)
81
84
  : undefined;
82
- if (this.sharedRunTimeout && !this.sharedRun) {
83
- debug('Auto-enabling sharedRun because sharedRunTimeout is set');
85
+ if ((this.sharedRunTimeout || this.sharedRunShards) && !this.sharedRun) {
86
+ debug('Auto-enabling sharedRun because sharedRunTimeout or sharedRunShards is set');
84
87
  this.sharedRun = true;
85
88
  }
86
89
  if (!this.title && (this.sharedRun || this.sharedRunTimeout)) {
@@ -290,6 +293,7 @@ class TestomatioPipe {
290
293
  label: this.label,
291
294
  shared_run: this.sharedRun,
292
295
  shared_run_timeout: this.sharedRunTimeout,
296
+ shared_run_shards: this.sharedRunShards,
293
297
  kind: params.kind,
294
298
  status: params.status,
295
299
  configuration,
@@ -527,6 +531,8 @@ class TestomatioPipe {
527
531
  status_event = 'pass';
528
532
  if (status === constants_js_1.STATUS.FAILED)
529
533
  status_event = 'fail';
534
+ if (this.sharedRun)
535
+ status_event = 'finish';
530
536
  try {
531
537
  if (this.runId && !this.proceed) {
532
538
  await this.client.request({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testomatio/reporter",
3
- "version": "2.15.0",
3
+ "version": "2.16.0",
4
4
  "description": "Testomatio Reporter Client",
5
5
  "engines": {
6
6
  "node": ">=18"
@@ -34,7 +34,8 @@ const HOOK_EXECUTION_ORDER = {
34
34
  // codeceptjs workers are self-contained
35
35
  dataStorage.isFileStorage = false;
36
36
 
37
- const DATA_REGEXP = /[|\s]+?(\{".*\}|\[.*\])/;
37
+ // CodeceptJS appends the serialized data row of a data-driven test to its title
38
+ const DATA_REGEXP = / \| (\{.*\}|\[.*\]|null|"(?:\\.|[^"\\])*")((?:\s+@[a-zA-Z0-9-_]+)*)$/;
38
39
 
39
40
  if (MAJOR_VERSION < 3) {
40
41
  console.log('🔴 This reporter works with CodeceptJS 3+, please update your tests');
@@ -349,15 +350,30 @@ function stripExampleFromTitle(title) {
349
350
  const res = title.match(DATA_REGEXP);
350
351
  if (!res) return { title, example: null };
351
352
 
353
+ let example = null;
354
+ let exampleParsed = false;
352
355
  try {
353
- const example = JSON.parse(res[1]);
354
- title = title.replace(DATA_REGEXP, '').trim();
355
- return { title, example };
356
+ example = JSON.parse(res[1]);
357
+ exampleParsed = true;
356
358
  } catch (e) {
357
- // If JSON parsing fails, return title without example
358
- debug('Failed to parse example JSON:', res[1], e.message);
359
- return { title: title.replace(DATA_REGEXP, '').trim(), example: null };
359
+ try {
360
+ example = JSON.parse(res[1].slice(1, -1));
361
+ exampleParsed = true;
362
+ } catch (e2) {
363
+ debug('Failed to parse example from title:', res[1]);
364
+ }
365
+ }
366
+
367
+ let baseTitle = title.slice(0, res.index).trim();
368
+ if (exampleParsed && baseTitle.includes('${current}')) {
369
+ baseTitle = baseTitle.replaceAll('${current}', formatExample(example));
360
370
  }
371
+ return { title: `${baseTitle}${res[2]}`, example };
372
+ }
373
+
374
+ function formatExample(example) {
375
+ if (example !== null && typeof example === 'object') return JSON.stringify(example);
376
+ return String(example);
361
377
  }
362
378
 
363
379
  function stripTagsFromTitle(title) {
@@ -88,12 +88,15 @@ class TestomatioPipe {
88
88
  this.store = store || {};
89
89
  this.title = params.title || process.env.TESTOMATIO_TITLE;
90
90
  this.sharedRun = !!process.env.TESTOMATIO_SHARED_RUN;
91
+ this.sharedRunShards = process.env.TESTOMATIO_SHARDS
92
+ ? parseInt(process.env.TESTOMATIO_SHARDS, 10) || undefined
93
+ : undefined;
91
94
  this.sharedRunTimeout = process.env.TESTOMATIO_SHARED_RUN_TIMEOUT
92
95
  ? parseInt(process.env.TESTOMATIO_SHARED_RUN_TIMEOUT, 10)
93
96
  : undefined;
94
97
 
95
- if (this.sharedRunTimeout && !this.sharedRun) {
96
- debug('Auto-enabling sharedRun because sharedRunTimeout is set');
98
+ if ((this.sharedRunTimeout || this.sharedRunShards) && !this.sharedRun) {
99
+ debug('Auto-enabling sharedRun because sharedRunTimeout or sharedRunShards is set');
97
100
  this.sharedRun = true;
98
101
  }
99
102
 
@@ -323,6 +326,7 @@ class TestomatioPipe {
323
326
  label: this.label,
324
327
  shared_run: this.sharedRun,
325
328
  shared_run_timeout: this.sharedRunTimeout,
329
+ shared_run_shards: this.sharedRunShards,
326
330
  kind: params.kind,
327
331
  status: params.status,
328
332
  configuration,
@@ -570,6 +574,7 @@ class TestomatioPipe {
570
574
  if (status === STATUS.FINISHED) status_event = 'finish';
571
575
  if (status === STATUS.PASSED) status_event = 'pass';
572
576
  if (status === STATUS.FAILED) status_event = 'fail';
577
+ if (this.sharedRun) status_event = 'finish';
573
578
 
574
579
  try {
575
580
  if (this.runId && !this.proceed) {