@testomatio/reporter 2.3.5-beta-6-xml-import β†’ 2.3.5-beta.8-xml-import

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/README.md CHANGED
@@ -13,7 +13,7 @@ Testomat.io Reporter (this npm package) supports:
13
13
  - πŸ”Ž [Stack traces](./docs/stacktrace.md) and error messages
14
14
  - πŸ™ [GitHub](./docs/pipes/github.md), [GitLab](./docs/pipes/gitlab.md) & [Bitbucket](./docs/pipes/bitbucket.md) integration
15
15
  - πŸš… Realtime reports
16
- - πŸ—ƒοΈ Other test frameworks supported via [JUnit XML](./docs/junit.md) with [XML import configuration](./docs/xml-imports.md)
16
+ - πŸ—ƒοΈ Other test frameworks supported via [JUNit XML](./docs/junit.md)
17
17
  - πŸšΆβ€β™€οΈ Steps _(work in progress)_
18
18
  - πŸ“„ [Logger](./docs/logger.md) _(work in progress, supports Jest for now)_
19
19
  - ☁️ Custom properties and metadata _(work in progress)_
@@ -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
  }
package/lib/pipe/debug.js CHANGED
@@ -18,7 +18,7 @@ class DebugPipe {
18
18
  this.isEnabled = !!process.env.TESTOMATIO_DEBUG || !!process.env.DEBUG;
19
19
  if (this.isEnabled) {
20
20
  this.batch = {
21
- isEnabled: this.params.isBatchEnabled ?? (process.env.TESTOMATIO_DISABLE_BATCH_UPLOAD ? false : true),
21
+ isEnabled: this.params.isBatchEnabled ?? !process.env.TESTOMATIO_DISABLE_BATCH_UPLOAD ?? true,
22
22
  intervalFunction: null,
23
23
  intervalTime: 5000,
24
24
  tests: [],
@@ -23,7 +23,7 @@ if (process.env.TESTOMATIO_RUN)
23
23
  class TestomatioPipe {
24
24
  constructor(params, store) {
25
25
  this.batch = {
26
- isEnabled: params?.isBatchEnabled ?? (process.env.TESTOMATIO_DISABLE_BATCH_UPLOAD ? false : true),
26
+ isEnabled: params?.isBatchEnabled ?? !process.env.TESTOMATIO_DISABLE_BATCH_UPLOAD ?? true,
27
27
  intervalFunction: null, // will be created in createRun by setInterval function
28
28
  intervalTime: 5000, // how often tests are sent
29
29
  tests: [], // array of tests in batch
@@ -60,7 +60,7 @@ class TestomatioPipe {
60
60
  retry: constants_js_1.REPORTER_REQUEST_RETRIES.retriesPerRequest,
61
61
  retryDelay: constants_js_1.REPORTER_REQUEST_RETRIES.retryTimeout,
62
62
  httpMethodsToRetry: ['GET', 'PUT', 'HEAD', 'OPTIONS', 'DELETE', 'POST'],
63
- shouldRetry: error => {
63
+ shouldRetry: (error) => {
64
64
  if (!error.response)
65
65
  return false;
66
66
  switch (error.response?.status) {
@@ -73,8 +73,8 @@ class TestomatioPipe {
73
73
  break;
74
74
  }
75
75
  return error.response?.status >= 401; // Retry on 401+ and 5xx
76
- },
77
- },
76
+ }
77
+ }
78
78
  });
79
79
  this.isEnabled = true;
80
80
  // do not finish this run (for parallel testing)
@@ -193,7 +193,7 @@ class TestomatioPipe {
193
193
  method: 'PUT',
194
194
  url: `/api/reporter/${this.runId}`,
195
195
  data: runParams,
196
- responseType: 'json',
196
+ responseType: 'json'
197
197
  });
198
198
  if (resp.data.artifacts)
199
199
  (0, pipe_utils_js_1.setS3Credentials)(resp.data.artifacts);
@@ -206,7 +206,7 @@ class TestomatioPipe {
206
206
  url: '/api/reporter',
207
207
  data: runParams,
208
208
  maxContentLength: Infinity,
209
- responseType: 'json',
209
+ responseType: 'json'
210
210
  });
211
211
  this.runId = resp.data.uid;
212
212
  this.runUrl = `${this.url}/${resp.data.url.split('/').splice(3).join('/')}`;
@@ -259,17 +259,15 @@ class TestomatioPipe {
259
259
  this.#formatData(data);
260
260
  const json = json_cycle_1.default.stringify(data);
261
261
  debug('Adding test', json);
262
- return this.client
263
- .request({
262
+ return this.client.request({
264
263
  method: 'POST',
265
264
  url: `/api/reporter/${this.runId}/testrun`,
266
265
  data: json,
267
266
  headers: {
268
267
  'Content-Type': 'application/json',
269
268
  },
270
- maxContentLength: Infinity,
271
- })
272
- .catch(err => {
269
+ maxContentLength: Infinity
270
+ }).catch(err => {
273
271
  this.requestFailures++;
274
272
  this.notReportedTestsCount++;
275
273
  if (err.response) {
@@ -314,21 +312,19 @@ class TestomatioPipe {
314
312
  // get tests from batch and clear batch
315
313
  const testsToSend = this.batch.tests.splice(0);
316
314
  debug('πŸ“¨ Batch upload', testsToSend.length, 'tests');
317
- return this.client
318
- .request({
315
+ return this.client.request({
319
316
  method: 'POST',
320
317
  url: `/api/reporter/${this.runId}/testrun`,
321
318
  data: {
322
319
  api_key: this.apiKey,
323
320
  tests: testsToSend,
324
- batch_index: this.batch.batchIndex,
321
+ batch_index: this.batch.batchIndex
325
322
  },
326
323
  headers: {
327
324
  'Content-Type': 'application/json',
328
325
  },
329
- maxContentLength: Infinity,
330
- })
331
- .catch(err => {
326
+ maxContentLength: Infinity
327
+ }).catch(err => {
332
328
  this.requestFailures++;
333
329
  this.notReportedTestsCount += testsToSend.length;
334
330
  if (err.response) {
@@ -412,7 +408,7 @@ class TestomatioPipe {
412
408
  status_event,
413
409
  detach: params.detach,
414
410
  tests: params.tests,
415
- },
411
+ }
416
412
  });
417
413
  console.log(constants_js_1.APP_PREFIX, 'βœ… Testrun finished');
418
414
  if (this.runUrl) {
@@ -173,8 +173,6 @@ exports.fetchSourceCodeFromStackTrace = fetchSourceCodeFromStackTrace;
173
173
  exports.TEST_ID_REGEX = /@T([\w\d]{8})/;
174
174
  exports.SUITE_ID_REGEX = /@S([\w\d]{8})/;
175
175
  const fetchIdFromCode = (code, opts = {}) => {
176
- if (!code)
177
- return null;
178
176
  const comments = code
179
177
  .split('\n')
180
178
  .map(l => l.trim())
@@ -217,29 +215,10 @@ const fetchSourceCode = (contents, opts = {}) => {
217
215
  lineIndex = lines.findIndex(l => l.includes(`${title}(`));
218
216
  }
219
217
  else if (opts.lang === 'csharp') {
220
- // Enhanced C# method detection for NUnit tests
221
- lineIndex = lines.findIndex(l => l.includes(`public void ${title}(`));
222
- if (lineIndex === -1) {
223
- lineIndex = lines.findIndex(l => l.includes(`public async Task ${title}(`));
224
- }
225
- if (lineIndex === -1) {
218
+ if (lineIndex === -1)
219
+ lineIndex = lines.findIndex(l => l.includes(`public void ${title}`));
220
+ if (lineIndex === -1)
226
221
  lineIndex = lines.findIndex(l => l.includes(`${title}(`));
227
- }
228
- // Look for TestCase or Test attributes above the method
229
- if (lineIndex === -1) {
230
- const testAttributeIndex = lines.findIndex((l, index) => {
231
- if (l.includes('[TestCase') || l.includes('[Test')) {
232
- // Check next few lines for the method
233
- const nextLines = lines.slice(index, Math.min(lines.length, index + 5));
234
- const hasMethod = nextLines.some(nextLine => nextLine.includes(`${title}(`));
235
- return hasMethod;
236
- }
237
- return false;
238
- });
239
- if (testAttributeIndex !== -1) {
240
- lineIndex = testAttributeIndex;
241
- }
242
- }
243
222
  }
244
223
  else {
245
224
  lineIndex = lines.findIndex(l => l.includes(title));
@@ -248,7 +227,7 @@ const fetchSourceCode = (contents, opts = {}) => {
248
227
  if (opts.prepend) {
249
228
  lineIndex -= opts.prepend;
250
229
  }
251
- if (lineIndex !== -1 && lineIndex !== undefined) {
230
+ if (lineIndex) {
252
231
  const result = [];
253
232
  for (let i = lineIndex; i < lineIndex + limit; i++) {
254
233
  if (lines[i] === undefined)
@@ -291,14 +270,6 @@ const fetchSourceCode = (contents, opts = {}) => {
291
270
  break;
292
271
  if (opts.lang === 'java' && lines[i].includes(' class '))
293
272
  break;
294
- if (opts.lang === 'csharp' && lines[i].trim().match(/^\[Test/))
295
- break;
296
- if (opts.lang === 'csharp' && lines[i].includes(' public void '))
297
- break;
298
- if (opts.lang === 'csharp' && lines[i].includes(' public async Task '))
299
- break;
300
- if (opts.lang === 'csharp' && lines[i].includes(' class ') && lines[i].includes('public'))
301
- break;
302
273
  }
303
274
  result.push(lines[i]);
304
275
  }
@@ -13,8 +13,6 @@ declare class XmlReader {
13
13
  runId: any;
14
14
  adapter: import("./junit-adapter/adapter.js").default;
15
15
  opts: {};
16
- disableSourceCodeFetching: any;
17
- suiteOrganization: any;
18
16
  store: {};
19
17
  pipesPromise: Promise<any[]>;
20
18
  parser: XMLParser;
@@ -79,13 +77,6 @@ declare class XmlReader {
79
77
  skipped_count: number;
80
78
  tests: any[];
81
79
  };
82
- deduplicateTestsByFQN(tests: any): any[];
83
- generateFQN(test: any): string;
84
- generateNormalizedFQN(test: any): string;
85
- extractAssemblyName(test: any): any;
86
- extractNamespace(test: any): any;
87
- extractClassName(test: any): any;
88
- extractCsFileFromPath(test: any): any;
89
80
  calculateStats(): {};
90
81
  fetchSourceCode(): void;
91
82
  formatTests(): void;