@testomatio/reporter 2.3.8 → 2.3.9-beta-bin-fix

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.
package/src/xmlReader.js CHANGED
@@ -6,7 +6,6 @@ import { XMLParser } from 'fast-xml-parser';
6
6
  import { APP_PREFIX, STATUS } from './constants.js';
7
7
  import { randomUUID } from 'crypto';
8
8
  import { fileURLToPath } from 'url';
9
- import { NUnitXmlParser } from './junit-adapter/nunit-parser.js';
10
9
  import {
11
10
  fetchFilesFromStackTrace,
12
11
  fetchIdFromOutput,
@@ -15,7 +14,6 @@ import {
15
14
  fetchIdFromCode,
16
15
  humanize,
17
16
  TEST_ID_REGEX,
18
- transformEnvVarToBoolean,
19
17
  } from './utils/utils.js';
20
18
  import { pipesFactory } from './pipe/index.js';
21
19
  import adapterFactory from './junit-adapter/index.js';
@@ -37,7 +35,6 @@ const {
37
35
  TESTOMATIO_ENV,
38
36
  TESTOMATIO_RUN,
39
37
  TESTOMATIO_MARK_DETACHED,
40
- TESTOMATIO_LEGACY_NUNIT,
41
38
  } = process.env;
42
39
 
43
40
  const options = {
@@ -78,11 +75,6 @@ class XmlReader {
78
75
  this.stats.language = opts.lang?.toLowerCase();
79
76
  this.uploader = new S3Uploader();
80
77
 
81
- // Enhanced NUnit parsing - enabled by default for NUnit XML
82
- // Can be disabled via opts.enhancedNunit = false or TESTOMATIO_LEGACY_NUNIT=1
83
- this.enhancedNunit = !transformEnvVarToBoolean(TESTOMATIO_LEGACY_NUNIT);
84
- this.groupParameterized = opts.groupParameterized !== false; // Default true, can be disabled
85
-
86
78
  // @ts-ignore
87
79
  const packageJsonPath = path.resolve(__dirname, '..', 'package.json');
88
80
  this.version = JSON.parse(fs.readFileSync(packageJsonPath).toString()).version;
@@ -134,8 +126,7 @@ class XmlReader {
134
126
  }
135
127
 
136
128
  processJUnit(jsonSuite) {
137
- const { testsuite, name, failures, errors } = jsonSuite;
138
- const tests = testsuite?.tests || jsonSuite.tests;
129
+ const { testsuite, name, tests, failures, errors } = jsonSuite;
139
130
 
140
131
  reduceOptions.preferClassname = this.stats.language === 'python';
141
132
  const resultTests = processTestSuite(testsuite);
@@ -166,14 +157,6 @@ class XmlReader {
166
157
  }
167
158
 
168
159
  processNUnit(jsonSuite) {
169
- // Use enhanced NUnit parser if enabled and this is actually NUnit XML
170
- if (this.enhancedNunit && this.isNUnitXml(jsonSuite)) {
171
- debug('Using enhanced NUnit parser');
172
- return this.processNUnitEnhanced(jsonSuite);
173
- }
174
-
175
- // Fallback to legacy parser for backward compatibility
176
- debug('Using legacy NUnit parser');
177
160
  const { result, total, passed, failed, inconclusive, skipped } = jsonSuite;
178
161
 
179
162
  reduceOptions.preferClassname = this.stats.language === 'python';
@@ -192,71 +175,63 @@ class XmlReader {
192
175
  };
193
176
  }
194
177
 
195
- /**
196
- * Check if the XML is actually NUnit format (has test-suite hierarchy)
197
- * @param {Object} jsonSuite - Parsed XML suite object
198
- * @returns {boolean} - True if this is NUnit XML format
199
- */
200
- isNUnitXml(jsonSuite) {
201
- // NUnit XML has test-suite elements with type attributes
202
- if (jsonSuite['test-suite']) {
203
- const testSuite = Array.isArray(jsonSuite['test-suite']) ? jsonSuite['test-suite'][0] : jsonSuite['test-suite'];
204
-
205
- // Check for NUnit-specific test-suite types
206
- return (
207
- testSuite &&
208
- testSuite.type &&
209
- ['Assembly', 'TestSuite', 'TestFixture', 'ParameterizedMethod'].includes(testSuite.type)
210
- );
211
- }
212
- return false;
213
- }
214
-
215
- processNUnitEnhanced(jsonSuite) {
216
- debug('Processing NUnit XML with enhanced parser');
217
-
218
- try {
219
- const nunitParser = new NUnitXmlParser({
220
- groupParameterized: this.groupParameterized,
221
- ...this.opts,
222
- });
223
-
224
- const result = nunitParser.parseTestRun(jsonSuite);
225
-
226
- // Add parsed tests to our collection
227
- this.tests = this.tests.concat(result.tests);
228
-
229
- debug(`Enhanced NUnit parser processed ${result.tests.length} tests`);
230
-
231
- return result;
232
- } catch (error) {
233
- debug('Enhanced NUnit parser failed, falling back to legacy parser:', error.message);
234
- console.warn(`${APP_PREFIX} Enhanced NUnit parsing failed, using legacy parser: ${error.message}`);
235
-
236
- // Fallback to legacy parser
237
- this.enhancedNunit = false;
238
- return this.processNUnit(jsonSuite);
239
- }
240
- }
241
-
242
178
  processTRX(jsonSuite) {
243
179
  let defs = jsonSuite?.TestRun?.TestDefinitions?.UnitTest;
244
180
  if (!Array.isArray(defs)) defs = [defs].filter(d => !!d);
245
181
 
246
- // Parse test definitions
247
- const tests = defs.map(td => this._parseTRXTestDefinition(td));
182
+ const tests =
183
+ defs.map(td => {
184
+ const title = td.name.replace(/\(.*?\)/, '').trim();
185
+ let example = td.name.match(/\((.*?)\)/);
186
+ if (example) example = { ...example[1].split(',') };
187
+ const suite = td.TestMethod.className.split(', ')[0].split('.');
188
+ const suite_title = suite.pop();
189
+ return {
190
+ title,
191
+ example,
192
+ file: suite.join('/'),
193
+ description: td.Description,
194
+ suite_title,
195
+ id: td.Execution.id,
196
+ };
197
+ }) || [];
248
198
 
249
- // Parse test results
250
199
  let result = jsonSuite?.TestRun?.Results?.UnitTestResult;
251
200
  if (!Array.isArray(result)) result = [result].filter(d => !!d);
252
201
 
253
- const results = result.map(td => this._parseTRXTestResult(td, tests));
202
+ const results = result.map(td => ({
203
+ id: td.executionId,
204
+ // seconds are used in junit reports, but ms are used by testomatio
205
+ run_time: parseFloat(td.duration) * 1000,
206
+ status: td.outcome,
207
+ stack: td.Output.StdOut,
208
+ files: td?.ResultFiles?.ResultFile?.map(rf => rf.path),
209
+ }));
210
+
211
+ results.forEach(r => {
212
+ const test = tests.find(t => t.id === r.id) || {};
213
+ r.suite_title = test.suite_title;
214
+ r.title = test.title?.trim();
215
+ if (test.code) r.code = test.code;
216
+ if (test.description) r.description = test.description;
217
+ if (test.example) r.example = test.example;
218
+ if (test.file) r.file = test.file;
219
+ r.create = true;
220
+ r.overwrite = true;
221
+ if (r.status === 'Passed') r.status = STATUS.PASSED;
222
+ if (r.status === 'Failed') r.status = STATUS.FAILED;
223
+ if (r.status === 'Skipped') r.status = STATUS.SKIPPED;
224
+ delete r.id;
225
+ });
254
226
 
255
227
  debug(results);
256
228
 
257
229
  const counters = jsonSuite?.TestRun?.ResultSummary?.Counters || {};
230
+
258
231
  const failed_count = parseInt(counters.failed, 10) + parseInt(counters.error, 10);
259
- const status = failed_count > 0 ? STATUS.FAILED : STATUS.PASSED.toString();
232
+
233
+ let status = STATUS.PASSED.toString();
234
+ if (failed_count > 0) status = STATUS.FAILED;
260
235
 
261
236
  this.tests = results.filter(t => !!t.title);
262
237
 
@@ -271,69 +246,6 @@ class XmlReader {
271
246
  };
272
247
  }
273
248
 
274
- _parseTRXTestDefinition(td) {
275
- const title = td.name.replace(/\(.*?\)/, '').trim();
276
- const exampleMatch = td.name.match(/\((.*?)\)/);
277
- const example = exampleMatch ? {
278
- ...exampleMatch[1].split(',').map(p => p.trim()).filter(p => p !== '')
279
- } : null;
280
-
281
- const suite = td.TestMethod.className.split(', ')[0].split('.');
282
- const suite_title = suite.pop();
283
-
284
- // Convert namespace to file path for C#
285
- const file = `${suite.join('/')}.cs`;
286
-
287
- return {
288
- title, // Base name without parameters for test import
289
- example, // Parameters object for parameterized tests
290
- file, // File path with .cs extension
291
- description: td.Description,
292
- suite_title,
293
- id: td.Execution.id,
294
- };
295
- }
296
-
297
- _parseTRXTestResult(td, tests) {
298
- const test = tests.find(t => t.id === td.executionId) || {};
299
-
300
- const result = {
301
- suite_title: test.suite_title,
302
- title: test.title?.trim(),
303
- file: test.file,
304
- description: test.description,
305
- code: test.code,
306
- run_time: parseFloat(td.duration) * 1000,
307
- stack: td.Output?.StdOut || '',
308
- files: td?.ResultFiles?.ResultFile?.map(rf => rf.path),
309
- create: true,
310
- overwrite: true,
311
- };
312
-
313
- // Add example for parameterized tests
314
- if (test.example) {
315
- result.example = test.example;
316
- }
317
-
318
- // Map TRX status to Testomat.io status
319
- result.status = this._mapTRXStatus(td.outcome);
320
-
321
- return result;
322
- }
323
-
324
- _mapTRXStatus(outcome) {
325
- switch (outcome) {
326
- case 'Passed':
327
- return STATUS.PASSED;
328
- case 'Failed':
329
- return STATUS.FAILED;
330
- case 'Skipped':
331
- return STATUS.SKIPPED;
332
- default:
333
- return STATUS.PASSED;
334
- }
335
- }
336
-
337
249
  processXUnit(assemblies) {
338
250
  const tests = [];
339
251
 
@@ -600,7 +512,7 @@ function reduceTestCases(prev, item) {
600
512
 
601
513
  const exampleMatches = testCaseItem.name?.match(/\S\((.*?)\)/);
602
514
  if (exampleMatches) {
603
- example = { ...exampleMatches[1].split(',').map(v => v.trim().replace(/[^\w\s-]/g, '')).filter(v => v !== '') };
515
+ example = { ...exampleMatches[1].split(',').map(v => v.trim().replace(/[^\w\s-]/g, '')) };
604
516
  title = title.replace(/\(.*?\)/, '').trim();
605
517
  }
606
518
 
@@ -1,82 +0,0 @@
1
- /**
2
- * Enhanced NUnit XML Parser that properly handles test-suite hierarchy
3
- * and parameterized tests
4
- */
5
- export class NUnitXmlParser {
6
- constructor(options?: {});
7
- options: {};
8
- tests: any[];
9
- stats: {
10
- total: number;
11
- passed: number;
12
- failed: number;
13
- skipped: number;
14
- inconclusive: number;
15
- };
16
- /**
17
- * Parse NUnit XML test-run structure
18
- * @param {Object} testRun - Parsed XML test-run object
19
- * @returns {Object} - Parsed test results
20
- */
21
- parseTestRun(testRun: any): any;
22
- /**
23
- * Recursively parse test-suite elements based on their type
24
- * @param {Object|Array} testSuite - Test suite object or array
25
- * @param {Array} parentPath - Current path in the hierarchy
26
- */
27
- parseTestSuite(testSuite: any | any[], parentPath?: any[]): void;
28
- /**
29
- * Process child elements of a test suite
30
- * @param {Object} testSuite - Test suite object
31
- * @param {Array} currentPath - Current path in hierarchy
32
- */
33
- processChildren(testSuite: any, currentPath: any[]): void;
34
- /**
35
- * Parse test-case elements (actual tests)
36
- * @param {Object|Array} testCases - Test case object or array
37
- * @param {Array} suitePath - Path to the test suite
38
- * @param {Object} parentSuite - Parent test suite for context
39
- */
40
- parseTestCases(testCases: any | any[], suitePath: any[], parentSuite: any): void;
41
- /**
42
- * Parse individual test case
43
- * @param {Object} testCase - Test case object
44
- * @param {Array} suitePath - Path to the test suite
45
- * @param {Object} parentSuite - Parent test suite for context
46
- * @returns {Object|null} - Parsed test object
47
- */
48
- parseTestCase(testCase: any, suitePath: any[], parentSuite: any): any | null;
49
- /**
50
- * Extract method name and parameters from test name
51
- * @param {string} testName - Full test name
52
- * @returns {Object} - Extracted information
53
- */
54
- extractParameters(testName: string): any;
55
- /**
56
- * Parse parameter string into array of parameters
57
- * @param {string} paramString - Parameter string
58
- * @returns {Array} - Array of parameters
59
- */
60
- parseParameterString(paramString: string): any[];
61
- /**
62
- * Extract method name from test name (fallback)
63
- * @param {string} testName - Test name
64
- * @returns {string} - Method name
65
- */
66
- extractMethodName(testName: string): string;
67
- /**
68
- * Build file path from suite path and class name
69
- * @param {Array} suitePath - Suite path array
70
- * @param {string} className - Class name
71
- * @param {Object} parentSuite - Parent suite for context
72
- * @returns {string} - File path
73
- */
74
- buildFilePath(suitePath: any[], className: string, parentSuite: any): string;
75
- /**
76
- * Group parameterized tests by base method name
77
- * @param {Array} tests - Array of parsed tests
78
- * @returns {Object} - Grouped tests
79
- */
80
- groupParameterizedTests(tests: any[]): any;
81
- }
82
- export default NUnitXmlParser;