@testomatio/reporter 2.3.0-beta.4-playwright-tags → 2.3.0-beta.5-links

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.
@@ -399,10 +399,10 @@ function formatHookStep(step) {
399
399
  // For hook steps, construct title from available properties
400
400
  let title = step.name;
401
401
  if (step.actor && step.name) {
402
- title = `${step.actor}.${step.name}`;
402
+ title = `${step.actor} ${step.name}`;
403
403
  if (step.args && step.args.length > 0) {
404
404
  const argsStr = step.args.map(arg => JSON.stringify(arg)).join(', ');
405
- title += `(${argsStr})`;
405
+ title += ` ${argsStr}`;
406
406
  }
407
407
  }
408
408
  return {
@@ -240,17 +240,6 @@ function extractTags(test) {
240
240
  tagsSet.add(normalizedTag);
241
241
  });
242
242
  }
243
- // Extract tags from suite/describe level (inherited tags)
244
- let parent = test.parent;
245
- while (parent) {
246
- if (parent.tags && Array.isArray(parent.tags)) {
247
- parent.tags.forEach(tag => {
248
- const normalizedTag = typeof tag === 'string' ? tag.replace('@', '').toLowerCase() : String(tag).toLowerCase();
249
- tagsSet.add(normalizedTag);
250
- });
251
- }
252
- parent = parent.parent;
253
- }
254
243
  return Array.from(tagsSet);
255
244
  }
256
245
  /**
@@ -41,6 +41,7 @@ const client_js_1 = __importDefault(require("../client.js"));
41
41
  const utils_js_1 = require("../utils/utils.js");
42
42
  const index_js_1 = require("../services/index.js");
43
43
  const constants_js_1 = require("../constants.js");
44
+ const data_storage_js_1 = require("../data-storage.js");
44
45
  class WebdriverReporter extends reporter_1.default {
45
46
  constructor(options) {
46
47
  super(options);
@@ -77,9 +78,7 @@ class WebdriverReporter extends reporter_1.default {
77
78
  onTestEnd(test) {
78
79
  test.suite = test.parent;
79
80
  const logs = getTestLogs(test.fullTitle);
80
- // TODO: FIX: artifacts for some reason leads to empty report on Testomat.io
81
- // ^ not reproduced anymore (Jul 2025)
82
- // but still be under investigation
81
+ // still be under investigation
83
82
  const artifacts = index_js_1.services.artifacts.get(test.fullTitle);
84
83
  const keyValues = index_js_1.services.keyValues.get(test.fullTitle);
85
84
  test.logs = logs;
@@ -102,8 +101,9 @@ class WebdriverReporter extends reporter_1.default {
102
101
  const screenshotsBuffers = output
103
102
  .filter(el => el.endpoint === screenshotEndpoint && el.result && el.result.value)
104
103
  .map(el => Buffer.from(el.result.value, 'base64'));
104
+ const rid = (0, data_storage_js_1.stringToMD5Hash)(test.fullTitle);
105
105
  await this.client.addTestRun(state, {
106
- rid: test.uid || '',
106
+ rid,
107
107
  manuallyAttachedArtifacts: test.artifacts,
108
108
  error,
109
109
  logs: test.logs,
package/lib/bin/cli.js CHANGED
@@ -78,7 +78,7 @@ program
78
78
  console.log(constants_js_1.APP_PREFIX, `No command provided. Use -c option to launch a test runner.`);
79
79
  return process.exit(255);
80
80
  }
81
- const client = new client_js_1.default({ apiKey, title, parallel: true });
81
+ const client = new client_js_1.default({ apiKey, title });
82
82
  if (opts.filter) {
83
83
  const [pipe, ...optsArray] = opts.filter.split(':');
84
84
  const pipeOptions = optsArray.join(':');
@@ -95,13 +95,16 @@ program
95
95
  console.log(constants_js_1.APP_PREFIX, `🚀 Running`, picocolors_1.default.green(command));
96
96
  const runTests = async () => {
97
97
  const testCmds = command.split(' ');
98
- const cmd = (0, cross_spawn_1.spawn)(testCmds[0], testCmds.slice(1), { stdio: 'inherit' });
98
+ const cmd = (0, cross_spawn_1.spawn)(testCmds[0], testCmds.slice(1), {
99
+ stdio: 'inherit',
100
+ env: { ...process.env, TESTOMATIO_PROCEED: 'true', runId: client.runId },
101
+ });
99
102
  cmd.on('close', async (code) => {
100
103
  const emoji = code === 0 ? '🟢' : '🔴';
101
104
  console.log(constants_js_1.APP_PREFIX, emoji, `Runner exited with ${picocolors_1.default.bold(code)}`);
102
105
  if (apiKey) {
103
106
  const status = code === 0 ? 'passed' : 'failed';
104
- await client.updateRunStatus(status, true);
107
+ await client.updateRunStatus(status);
105
108
  }
106
109
  process.exit(code);
107
110
  });
@@ -257,13 +260,13 @@ program
257
260
  const replayService = new replay_js_1.default({
258
261
  apiKey: config_js_1.config.TESTOMATIO,
259
262
  dryRun: opts.dryRun,
260
- onLog: (message) => console.log(constants_js_1.APP_PREFIX, message),
261
- onError: (message) => console.error(constants_js_1.APP_PREFIX, '⚠️ ', message),
263
+ onLog: message => console.log(constants_js_1.APP_PREFIX, message),
264
+ onError: message => console.error(constants_js_1.APP_PREFIX, '⚠️ ', message),
262
265
  onProgress: ({ current, total }) => {
263
266
  if (current % 10 === 0 || current === total) {
264
267
  console.log(constants_js_1.APP_PREFIX, `📊 Progress: ${current}/${total} tests processed`);
265
268
  }
266
- }
269
+ },
267
270
  });
268
271
  const result = await replayService.replay(debugFile);
269
272
  if (result.dryRun) {
package/lib/client.d.ts CHANGED
@@ -58,10 +58,9 @@ export class Client {
58
58
  * Updates the status of the current test run and finishes the run.
59
59
  * @param {'passed' | 'failed' | 'skipped' | 'finished'} status - The status of the current test run.
60
60
  * Must be one of "passed", "failed", or "finished"
61
- * @param {boolean} [isParallel] - Whether the current test run was executed in parallel with other tests.
62
61
  * @returns {Promise<any>} - A Promise that resolves when finishes the run.
63
62
  */
64
- updateRunStatus(status: "passed" | "failed" | "skipped" | "finished", isParallel?: boolean): Promise<any>;
63
+ updateRunStatus(status: "passed" | "failed" | "skipped" | "finished"): Promise<any>;
65
64
  /**
66
65
  * Returns the formatted stack including the stack trace, steps, and logs.
67
66
  * @returns {string}
package/lib/client.js CHANGED
@@ -295,17 +295,16 @@ class Client {
295
295
  * Updates the status of the current test run and finishes the run.
296
296
  * @param {'passed' | 'failed' | 'skipped' | 'finished'} status - The status of the current test run.
297
297
  * Must be one of "passed", "failed", or "finished"
298
- * @param {boolean} [isParallel] - Whether the current test run was executed in parallel with other tests.
299
298
  * @returns {Promise<any>} - A Promise that resolves when finishes the run.
300
299
  */
301
- async updateRunStatus(status, isParallel = false) {
300
+ async updateRunStatus(status) {
302
301
  this.pipes ||= await (0, index_js_1.pipesFactory)(this.paramsForPipesFactory || {}, this.pipeStore);
303
302
  this.runId ||= (0, utils_js_1.readLatestRunId)();
304
303
  debug('Updating run status...');
305
304
  // all pipes disabled, skipping
306
305
  if (!this.pipes?.filter(p => p.isEnabled).length)
307
306
  return Promise.resolve();
308
- const runParams = { status, parallel: isParallel };
307
+ const runParams = { status };
309
308
  this.queue = this.queue
310
309
  .then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
311
310
  .then(() => {
@@ -23,7 +23,6 @@ declare class TestomatioPipe implements Pipe {
23
23
  isEnabled: boolean;
24
24
  url: any;
25
25
  apiKey: any;
26
- parallel: any;
27
26
  store: any;
28
27
  title: any;
29
28
  sharedRun: boolean;
@@ -43,7 +43,6 @@ class TestomatioPipe {
43
43
  debug('Testomatio Pipe: Enabled');
44
44
  const proxyUrl = process.env.HTTP_PROXY || process.env.HTTPS_PROXY;
45
45
  const proxy = proxyUrl ? new URL(proxyUrl) : null;
46
- this.parallel = params.parallel;
47
46
  this.store = store || {};
48
47
  this.title = params.title || process.env.TESTOMATIO_TITLE;
49
48
  this.sharedRun = !!process.env.TESTOMATIO_SHARED_RUN;
@@ -154,7 +153,6 @@ class TestomatioPipe {
154
153
  const accessEvent = process.env.TESTOMATIO_PUBLISH ? 'publish' : null;
155
154
  const runParams = Object.fromEntries(Object.entries({
156
155
  ci_build_url: buildUrl,
157
- parallel: this.parallel,
158
156
  api_key: this.apiKey.trim(),
159
157
  group_title: this.groupTitle,
160
158
  access_event: accessEvent,
@@ -377,7 +375,7 @@ class TestomatioPipe {
377
375
  const errorMessage = picocolors_1.default.red(`⚠️ Due to request failures, ${this.notReportedTestsCount} test(s) were not reported to Testomat.io`);
378
376
  console.warn(`${constants_js_1.APP_PREFIX} ${errorMessage}`);
379
377
  }
380
- const { status, parallel } = params;
378
+ const { status } = params;
381
379
  let status_event;
382
380
  if (status === constants_js_1.STATUS.FINISHED)
383
381
  status_event = 'finish';
@@ -385,8 +383,6 @@ class TestomatioPipe {
385
383
  status_event = 'pass';
386
384
  if (status === constants_js_1.STATUS.FAILED)
387
385
  status_event = 'fail';
388
- if (parallel)
389
- status_event += '_parallel';
390
386
  try {
391
387
  if (this.runId && !this.proceed) {
392
388
  await this.client.request({
package/lib/replay.js CHANGED
@@ -238,7 +238,7 @@ class Replay {
238
238
  });
239
239
  }
240
240
  }
241
- await client.updateRunStatus(finishParams.status || constants_js_1.STATUS.FINISHED, finishParams.parallel || false);
241
+ await client.updateRunStatus(finishParams.status || constants_js_1.STATUS.FINISHED);
242
242
  const result = {
243
243
  success: true,
244
244
  testsCount: tests.length,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testomatio/reporter",
3
- "version": "2.3.0-beta.4-playwright-tags",
3
+ "version": "2.3.0-beta.5-links",
4
4
  "description": "Testomatio Reporter Client",
5
5
  "engines": {
6
6
  "node": ">=18"
@@ -464,10 +464,10 @@ function formatHookStep(step) {
464
464
  // For hook steps, construct title from available properties
465
465
  let title = step.name;
466
466
  if (step.actor && step.name) {
467
- title = `${step.actor}.${step.name}`;
467
+ title = `${step.actor} ${step.name}`;
468
468
  if (step.args && step.args.length > 0) {
469
469
  const argsStr = step.args.map(arg => JSON.stringify(arg)).join(', ');
470
- title += `(${argsStr})`;
470
+ title += ` ${argsStr}`;
471
471
  }
472
472
  }
473
473
 
@@ -268,19 +268,6 @@ function extractTags(test) {
268
268
  tagsSet.add(normalizedTag);
269
269
  });
270
270
  }
271
-
272
- // Extract tags from suite/describe level (inherited tags)
273
- let parent = test.parent;
274
- while (parent) {
275
- if (parent.tags && Array.isArray(parent.tags)) {
276
- parent.tags.forEach(tag => {
277
- const normalizedTag = typeof tag === 'string' ? tag.replace('@', '').toLowerCase() : String(tag).toLowerCase();
278
- tagsSet.add(normalizedTag);
279
- });
280
- }
281
- parent = parent.parent;
282
- }
283
-
284
271
  return Array.from(tagsSet);
285
272
  }
286
273
 
@@ -3,6 +3,7 @@ import TestomatClient from '../client.js';
3
3
  import { getTestomatIdFromTestTitle, fileSystem } from '../utils/utils.js';
4
4
  import { services } from '../services/index.js';
5
5
  import { TESTOMAT_TMP_STORAGE_DIR } from '../constants.js';
6
+ import { stringToMD5Hash } from '../data-storage.js';
6
7
 
7
8
  class WebdriverReporter extends WDIOReporter {
8
9
  constructor(options) {
@@ -52,9 +53,7 @@ class WebdriverReporter extends WDIOReporter {
52
53
  onTestEnd(test) {
53
54
  test.suite = test.parent;
54
55
  const logs = getTestLogs(test.fullTitle);
55
- // TODO: FIX: artifacts for some reason leads to empty report on Testomat.io
56
- // ^ not reproduced anymore (Jul 2025)
57
- // but still be under investigation
56
+ // still be under investigation
58
57
  const artifacts = services.artifacts.get(test.fullTitle);
59
58
  const keyValues = services.keyValues.get(test.fullTitle);
60
59
  test.logs = logs;
@@ -83,8 +82,10 @@ class WebdriverReporter extends WDIOReporter {
83
82
  .filter(el => el.endpoint === screenshotEndpoint && el.result && el.result.value)
84
83
  .map(el => Buffer.from(el.result.value, 'base64'));
85
84
 
85
+ const rid = stringToMD5Hash(test.fullTitle);
86
+
86
87
  await this.client.addTestRun(state, {
87
- rid: test.uid || '',
88
+ rid,
88
89
  manuallyAttachedArtifacts: test.artifacts,
89
90
  error,
90
91
  logs: test.logs,
package/src/bin/cli.js CHANGED
@@ -85,7 +85,7 @@ program
85
85
  return process.exit(255);
86
86
  }
87
87
 
88
- const client = new TestomatClient({ apiKey, title, parallel: true });
88
+ const client = new TestomatClient({ apiKey, title });
89
89
 
90
90
  if (opts.filter) {
91
91
  const [pipe, ...optsArray] = opts.filter.split(':');
@@ -105,14 +105,17 @@ program
105
105
 
106
106
  const runTests = async () => {
107
107
  const testCmds = command.split(' ');
108
- const cmd = spawn(testCmds[0], testCmds.slice(1), { stdio: 'inherit' });
108
+ const cmd = spawn(testCmds[0], testCmds.slice(1), {
109
+ stdio: 'inherit',
110
+ env: { ...process.env, TESTOMATIO_PROCEED: 'true', runId: client.runId },
111
+ });
109
112
 
110
113
  cmd.on('close', async code => {
111
114
  const emoji = code === 0 ? '🟢' : '🔴';
112
115
  console.log(APP_PREFIX, emoji, `Runner exited with ${pc.bold(code)}`);
113
116
  if (apiKey) {
114
117
  const status = code === 0 ? 'passed' : 'failed';
115
- await client.updateRunStatus(status, true);
118
+ await client.updateRunStatus(status);
116
119
  }
117
120
  process.exit(code);
118
121
  });
@@ -310,13 +313,13 @@ program
310
313
  const replayService = new Replay({
311
314
  apiKey: config.TESTOMATIO,
312
315
  dryRun: opts.dryRun,
313
- onLog: (message) => console.log(APP_PREFIX, message),
314
- onError: (message) => console.error(APP_PREFIX, '⚠️ ', message),
316
+ onLog: message => console.log(APP_PREFIX, message),
317
+ onError: message => console.error(APP_PREFIX, '⚠️ ', message),
315
318
  onProgress: ({ current, total }) => {
316
319
  if (current % 10 === 0 || current === total) {
317
320
  console.log(APP_PREFIX, `📊 Progress: ${current}/${total} tests processed`);
318
321
  }
319
- }
322
+ },
320
323
  });
321
324
 
322
325
  const result = await replayService.replay(debugFile);
package/src/client.js CHANGED
@@ -314,10 +314,9 @@ class Client {
314
314
  * Updates the status of the current test run and finishes the run.
315
315
  * @param {'passed' | 'failed' | 'skipped' | 'finished'} status - The status of the current test run.
316
316
  * Must be one of "passed", "failed", or "finished"
317
- * @param {boolean} [isParallel] - Whether the current test run was executed in parallel with other tests.
318
317
  * @returns {Promise<any>} - A Promise that resolves when finishes the run.
319
318
  */
320
- async updateRunStatus(status, isParallel = false) {
319
+ async updateRunStatus(status) {
321
320
  this.pipes ||= await pipesFactory(this.paramsForPipesFactory || {}, this.pipeStore);
322
321
  this.runId ||= readLatestRunId();
323
322
 
@@ -325,7 +324,7 @@ class Client {
325
324
  // all pipes disabled, skipping
326
325
  if (!this.pipes?.filter(p => p.isEnabled).length) return Promise.resolve();
327
326
 
328
- const runParams = { status, parallel: isParallel };
327
+ const runParams = { status };
329
328
 
330
329
  this.queue = this.queue
331
330
  .then(() => Promise.all(this.pipes.map(p => p.finishRun(runParams))))
@@ -43,7 +43,6 @@ class TestomatioPipe {
43
43
  const proxyUrl = process.env.HTTP_PROXY || process.env.HTTPS_PROXY;
44
44
  const proxy = proxyUrl ? new URL(proxyUrl) : null;
45
45
 
46
- this.parallel = params.parallel;
47
46
  this.store = store || {};
48
47
  this.title = params.title || process.env.TESTOMATIO_TITLE;
49
48
  this.sharedRun = !!process.env.TESTOMATIO_SHARED_RUN;
@@ -167,7 +166,6 @@ class TestomatioPipe {
167
166
  const runParams = Object.fromEntries(
168
167
  Object.entries({
169
168
  ci_build_url: buildUrl,
170
- parallel: this.parallel,
171
169
  api_key: this.apiKey.trim(),
172
170
  group_title: this.groupTitle,
173
171
  access_event: accessEvent,
@@ -419,14 +417,13 @@ class TestomatioPipe {
419
417
  console.warn(`${APP_PREFIX} ${errorMessage}`);
420
418
  }
421
419
 
422
- const { status, parallel } = params;
420
+ const { status } = params;
423
421
 
424
422
  let status_event;
425
423
 
426
424
  if (status === STATUS.FINISHED) status_event = 'finish';
427
425
  if (status === STATUS.PASSED) status_event = 'pass';
428
426
  if (status === STATUS.FAILED) status_event = 'fail';
429
- if (parallel) status_event += '_parallel';
430
427
 
431
428
  try {
432
429
  if (this.runId && !this.proceed) {
package/src/replay.js CHANGED
@@ -246,7 +246,7 @@ export class Replay {
246
246
  }
247
247
  }
248
248
 
249
- await client.updateRunStatus(finishParams.status || STATUS.FINISHED, finishParams.parallel || false);
249
+ await client.updateRunStatus(finishParams.status || STATUS.FINISHED);
250
250
 
251
251
  const result = {
252
252
  success: true,