@testomatio/reporter 2.3.2-beta.3-xml-import → 2.3.3

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.
@@ -11,4 +11,10 @@ declare class PlaywrightReporter {
11
11
  onEnd(result: any): Promise<void>;
12
12
  #private;
13
13
  }
14
+ /**
15
+ * Extracts and normalizes tags from test title, test options, and suite level
16
+ * @param {*} test - testInfo object from Playwright
17
+ * @returns {string[]} - array of normalized tags
18
+ */
19
+ export function extractTags(test: any): string[];
14
20
  import TestomatioClient from '../client.js';
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extractTags = extractTags;
6
7
  const picocolors_1 = __importDefault(require("picocolors"));
7
8
  const crypto_1 = __importDefault(require("crypto"));
8
9
  const os_1 = __importDefault(require("os"));
@@ -253,3 +254,5 @@ function getTestContextName(test) {
253
254
  return `${test._requireFile || ''}_${test.title}`;
254
255
  }
255
256
  module.exports = PlaywrightReporter;
257
+
258
+ module.exports.extractTags = extractTags;
package/lib/bin/cli.js CHANGED
@@ -61,7 +61,6 @@ program
61
61
  const client = new client_js_1.default({ apiKey });
62
62
  // @ts-ignore
63
63
  client.updateRunStatus(constants_js_1.STATUS.FINISHED).then(() => {
64
- console.log(picocolors_1.default.yellow(`Run ${process.env.TESTOMATIO_RUN} was finished`));
65
64
  process.exit(0);
66
65
  });
67
66
  });
@@ -1,4 +1,5 @@
1
1
  export default CSharpAdapter;
2
2
  declare class CSharpAdapter extends Adapter {
3
+ getFilePath(t: any): string;
3
4
  }
4
5
  import Adapter from './adapter.js';
@@ -7,53 +7,24 @@ const path_1 = __importDefault(require("path"));
7
7
  const adapter_js_1 = __importDefault(require("./adapter.js"));
8
8
  class CSharpAdapter extends adapter_js_1.default {
9
9
  formatTest(t) {
10
- // Don't override example if it already exists from NUnit XML processing
11
- // The xmlReader.js already extracts parameters correctly from <arguments>
12
- if (!t.example) {
13
- const title = t.title.replace(/\(.*?\)/, '').trim();
14
- const exampleMatch = t.title.match(/\((.*?)\)/);
15
- if (exampleMatch) {
16
- // Keep as array for consistency with NUnit XML processing
17
- t.example = exampleMatch[1].split(',').map(param => param.trim());
18
- }
19
- t.title = title.trim();
20
- }
10
+ const title = t.title.replace(/\(.*?\)/, '').trim();
11
+ const example = t.title.match(/\((.*?)\)/);
12
+ if (example)
13
+ t.example = { ...example[1].split(',') };
21
14
  const suite = t.suite_title.split('.');
22
15
  t.suite_title = suite.pop();
23
16
  t.file = namespaceToFileName(t.file);
17
+ t.title = title.trim();
24
18
  return t;
25
19
  }
26
20
  getFilePath(t) {
27
- if (!t.file)
28
- return null;
29
- // Normalize path separators for cross-platform compatibility
30
- let filePath = t.file.replace(/\\/g, '/');
31
- // If file already has .cs extension, use it directly
32
- if (filePath.endsWith('.cs')) {
33
- // Make relative path if it's absolute
34
- if (path_1.default.isAbsolute(filePath)) {
35
- // Try to find project-relative path
36
- const cwd = process.cwd().replace(/\\/g, '/');
37
- if (filePath.startsWith(cwd)) {
38
- filePath = path_1.default.relative(cwd, filePath).replace(/\\/g, '/');
39
- }
40
- }
41
- return filePath;
42
- }
43
- // Convert namespace path to file path
44
- const fileName = namespaceToFileName(filePath);
21
+ const fileName = namespaceToFileName(t.file);
45
22
  return fileName;
46
23
  }
47
24
  }
48
25
  module.exports = CSharpAdapter;
49
26
  function namespaceToFileName(fileName) {
50
- if (!fileName)
51
- return '';
52
- // If already a .cs file path, clean it up
53
- if (fileName.endsWith('.cs')) {
54
- return fileName.replace(/\\/g, '/');
55
- }
56
27
  const fileParts = fileName.split('.');
57
28
  fileParts[fileParts.length - 1] = fileParts[fileParts.length - 1]?.replace(/\$.*/, '');
58
- return `${fileParts.join('/')}.cs`;
29
+ return `${fileParts.join(path_1.default.sep)}.cs`;
59
30
  }
@@ -31,7 +31,7 @@ declare class TestomatioPipe implements Pipe {
31
31
  env: string;
32
32
  label: string;
33
33
  client: Gaxios;
34
- proceed: string;
34
+ proceed: boolean;
35
35
  jiraId: string;
36
36
  runId: any;
37
37
  createNewTests: any;
@@ -78,7 +78,7 @@ class TestomatioPipe {
78
78
  });
79
79
  this.isEnabled = true;
80
80
  // do not finish this run (for parallel testing)
81
- this.proceed = process.env.TESTOMATIO_PROCEED;
81
+ this.proceed = (0, utils_js_1.transformEnvVarToBoolean)(process.env.TESTOMATIO_PROCEED);
82
82
  this.jiraId = process.env.TESTOMATIO_JIRA_ID;
83
83
  this.runId = params.runId || process.env.TESTOMATIO_RUN;
84
84
  this.createNewTests = params.createNewTests ?? !!process.env.TESTOMATIO_CREATE;
@@ -396,6 +396,7 @@ class TestomatioPipe {
396
396
  tests: params.tests,
397
397
  }
398
398
  });
399
+ console.log(constants_js_1.APP_PREFIX, '✅ Testrun finished');
399
400
  if (this.runUrl) {
400
401
  console.log(constants_js_1.APP_PREFIX, '📊 Report Saved. Report URL:', picocolors_1.default.magenta(this.runUrl));
401
402
  }
@@ -2,7 +2,7 @@ export function getPackageVersion(): any;
2
2
  export const TEST_ID_REGEX: RegExp;
3
3
  export const SUITE_ID_REGEX: RegExp;
4
4
  export function ansiRegExp(): RegExp;
5
- export function cleanLatestRunId(): void;
5
+ export function cleanLatestRunId(): any;
6
6
  export function isSameTest(test: any, t: any): boolean;
7
7
  export function fetchSourceCode(contents: any, opts?: {}): string;
8
8
  export function fetchSourceCodeFromStackTrace(stack?: string): string;
@@ -47,10 +47,11 @@ export function removeColorCodes(input: any): any;
47
47
  * @returns {String|null} testInfo as one string
48
48
  */
49
49
  export function specificTestInfo(test: any): string | null;
50
- export function storeRunId(runId: any): void;
50
+ export function storeRunId(runId: any): any;
51
51
  export namespace testRunnerHelper {
52
52
  function getNameOfCurrentlyRunningTest(): any;
53
53
  }
54
+ export function transformEnvVarToBoolean(value: any): boolean;
54
55
  /**
55
56
  * Validates TESTOMATIO_SUITE environment variable format
56
57
  * @param {String} suiteId - suite ID to validate
@@ -43,6 +43,7 @@ exports.formatStep = formatStep;
43
43
  exports.readLatestRunId = readLatestRunId;
44
44
  exports.removeColorCodes = removeColorCodes;
45
45
  exports.storeRunId = storeRunId;
46
+ exports.transformEnvVarToBoolean = transformEnvVarToBoolean;
46
47
  const url_1 = require("url");
47
48
  const path_1 = __importStar(require("path"));
48
49
  const picocolors_1 = __importDefault(require("picocolors"));
@@ -172,8 +173,6 @@ exports.fetchSourceCodeFromStackTrace = fetchSourceCodeFromStackTrace;
172
173
  exports.TEST_ID_REGEX = /@T([\w\d]{8})/;
173
174
  exports.SUITE_ID_REGEX = /@S([\w\d]{8})/;
174
175
  const fetchIdFromCode = (code, opts = {}) => {
175
- if (!code)
176
- return null;
177
176
  const comments = code
178
177
  .split('\n')
179
178
  .map(l => l.trim())
@@ -216,29 +215,10 @@ const fetchSourceCode = (contents, opts = {}) => {
216
215
  lineIndex = lines.findIndex(l => l.includes(`${title}(`));
217
216
  }
218
217
  else if (opts.lang === 'csharp') {
219
- // Enhanced C# method detection for NUnit tests
220
- lineIndex = lines.findIndex(l => l.includes(`public void ${title}(`));
221
- if (lineIndex === -1) {
222
- lineIndex = lines.findIndex(l => l.includes(`public async Task ${title}(`));
223
- }
224
- if (lineIndex === -1) {
218
+ if (lineIndex === -1)
219
+ lineIndex = lines.findIndex(l => l.includes(`public void ${title}`));
220
+ if (lineIndex === -1)
225
221
  lineIndex = lines.findIndex(l => l.includes(`${title}(`));
226
- }
227
- // Look for TestCase or Test attributes above the method
228
- if (lineIndex === -1) {
229
- const testAttributeIndex = lines.findIndex((l, index) => {
230
- if (l.includes('[TestCase') || l.includes('[Test')) {
231
- // Check next few lines for the method
232
- const nextLines = lines.slice(index, Math.min(lines.length, index + 5));
233
- const hasMethod = nextLines.some(nextLine => nextLine.includes(`${title}(`));
234
- return hasMethod;
235
- }
236
- return false;
237
- });
238
- if (testAttributeIndex !== -1) {
239
- lineIndex = testAttributeIndex;
240
- }
241
- }
242
222
  }
243
223
  else {
244
224
  lineIndex = lines.findIndex(l => l.includes(title));
@@ -247,7 +227,7 @@ const fetchSourceCode = (contents, opts = {}) => {
247
227
  if (opts.prepend) {
248
228
  lineIndex -= opts.prepend;
249
229
  }
250
- if (lineIndex !== -1 && lineIndex !== undefined) {
230
+ if (lineIndex) {
251
231
  const result = [];
252
232
  for (let i = lineIndex; i < lineIndex + limit; i++) {
253
233
  if (lines[i] === undefined)
@@ -290,14 +270,6 @@ const fetchSourceCode = (contents, opts = {}) => {
290
270
  break;
291
271
  if (opts.lang === 'java' && lines[i].includes(' class '))
292
272
  break;
293
- if (opts.lang === 'csharp' && lines[i].trim().match(/^\[Test/))
294
- break;
295
- if (opts.lang === 'csharp' && lines[i].includes(' public void '))
296
- break;
297
- if (opts.lang === 'csharp' && lines[i].includes(' public async Task '))
298
- break;
299
- if (opts.lang === 'csharp' && lines[i].includes(' class ') && lines[i].includes('public'))
300
- break;
301
273
  }
302
274
  result.push(lines[i]);
303
275
  }
@@ -419,7 +391,14 @@ function storeRunId(runId) {
419
391
  if (!runId || runId === 'undefined')
420
392
  return;
421
393
  const filePath = path_1.default.join(os_1.default.tmpdir(), `testomatio.latest.run`);
422
- fs_1.default.writeFileSync(filePath, runId);
394
+ try {
395
+ fs_1.default.writeFileSync(filePath, runId);
396
+ }
397
+ catch (e) {
398
+ if (e.code === 'ENOENT')
399
+ return null;
400
+ debug('Could not store latest run ID file: ', e.message);
401
+ }
423
402
  }
424
403
  /**
425
404
  *
@@ -438,7 +417,6 @@ function readLatestRunId() {
438
417
  return fs_1.default.readFileSync(filePath)?.toString()?.trim() ?? null;
439
418
  }
440
419
  catch (e) {
441
- console.warn('Could not read latest run ID from file: ', e);
442
420
  return null;
443
421
  }
444
422
  }
@@ -452,6 +430,8 @@ function cleanLatestRunId() {
452
430
  debug(`Cleaned latest run ID (${runId}) file`, filePath);
453
431
  }
454
432
  catch (e) {
433
+ if (e.code === 'ENOENT')
434
+ return null;
455
435
  console.warn('Could not clean latest run ID file: ', e);
456
436
  }
457
437
  }
@@ -474,6 +454,21 @@ function getPackageVersion() {
474
454
  const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf8'));
475
455
  return packageJson.version;
476
456
  }
457
+ function transformEnvVarToBoolean(value) {
458
+ if (value === undefined || value === null || value === 'undefined')
459
+ return false;
460
+ if (typeof value === 'boolean')
461
+ return value;
462
+ if (typeof value !== 'string')
463
+ value = String(value);
464
+ value = value.trim();
465
+ if (['1', 'true', 'yes', 'on'].includes(value.toLowerCase()))
466
+ return true;
467
+ if (['0', 'false', 'no', 'off'].includes(value.toLowerCase()))
468
+ return false;
469
+ // if not recognized, return truthy if any value is set
470
+ return Boolean(value);
471
+ }
477
472
 
478
473
  module.exports.getPackageVersion = getPackageVersion;
479
474
 
@@ -487,6 +482,8 @@ module.exports.removeColorCodes = removeColorCodes;
487
482
 
488
483
  module.exports.storeRunId = storeRunId;
489
484
 
485
+ module.exports.transformEnvVarToBoolean = transformEnvVarToBoolean;
486
+
490
487
  module.exports.getTestomatIdFromTestTitle = getTestomatIdFromTestTitle;
491
488
 
492
489
  module.exports.parseSuite = parseSuite;
@@ -46,7 +46,7 @@ declare class XmlReader {
46
46
  passed_count: number;
47
47
  skipped_count: number;
48
48
  status: string;
49
- tests: any;
49
+ tests: any[];
50
50
  tests_count: number;
51
51
  };
52
52
  processNUnit(jsonSuite: any): {
@@ -77,13 +77,6 @@ declare class XmlReader {
77
77
  skipped_count: number;
78
78
  tests: any[];
79
79
  };
80
- deduplicateTestsByFQN(tests: any): any[];
81
- generateFQN(test: any): string;
82
- generateNormalizedFQN(test: any): string;
83
- extractAssemblyName(test: any): any;
84
- extractNamespace(test: any): any;
85
- extractClassName(test: any): any;
86
- extractCsFileFromPath(test: any): any;
87
80
  calculateStats(): {};
88
81
  fetchSourceCode(): void;
89
82
  formatTests(): void;