@testomatio/reporter 1.0.8 → 1.0.9

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.
@@ -10,24 +10,42 @@ class JavaAdapter extends Adapter {
10
10
 
11
11
  formatTest(t) {
12
12
  const fileParts = t.suite_title.split('.')
13
- const example = t.title.match(/\[(.*)\]/)?.[1];
14
- if (example) t.example = { "#": example }
15
13
 
16
14
  t.file = namespaceToFileName(t.suite_title);
17
15
  t.title = t.title.split('(')[0];
16
+
17
+ // detect params
18
+ const paramMatches = t.title.match(/\[(.*?)\]/g);
19
+
20
+ if (paramMatches) {
21
+ const params = paramMatches.map((_match, index) => `param${index + 1}`);
22
+ if (params.length === 1) params[0] = 'param';
23
+ let paramIndex = 0;
24
+
25
+ t.title = t.title.replace(/: \[(.*?)\]/g, () => {
26
+ if (params.length < 2) return `\${param}`
27
+ const paramName = params[paramIndex] || `param${paramIndex + 1}`;
28
+ paramIndex++;
29
+ return `\${${paramName}}`;
30
+ });
31
+ const example = {};
32
+ paramMatches.forEach((match, index) => { example[params[index]] = match.replace(/[[\]]/g, '') });
33
+ t.example = example;
34
+ }
35
+
18
36
  t.suite_title = fileParts[fileParts.length - 1].replace(/\$/g, ' | ')
19
37
  return t;
20
38
  }
21
39
 
22
- formatStack(t) {
23
- const stack = super.formatStack(t);
40
+ // formatStack(t) {
41
+ // const stack = super.formatStack(t);
24
42
 
25
- const file = t.suite_title.split('.');
43
+ // const file = t.suite_title.split('.');
26
44
 
27
- const fileLine = `at .*${file[file.length - 1]}\.java:(\\d+)` // eslint-disable-line no-useless-escape
28
- const regexp = new RegExp(fileLine,"g")
29
- return stack.replace(regexp, `${this.opts.javaTests}${path.sep}${namespaceToFileName(t.suite_title)}:$1:`);
30
- }
45
+ // const fileLine = `at .*${file[file.length - 1]}\.java:(\\d+)` // eslint-disable-line no-useless-escape
46
+ // const regexp = new RegExp(fileLine,"g")
47
+ // return stack.replace(regexp, `${this.opts.javaTests}${path.sep}${namespaceToFileName(t.suite_title)}:$1:`);
48
+ // }
31
49
  }
32
50
 
33
51
  function namespaceToFileName(fileName) {
package/lib/util.js CHANGED
@@ -192,6 +192,51 @@ const fileSystem = {
192
192
  }
193
193
  };
194
194
 
195
+ const humanize = (text) => {
196
+ text = decamelize(text);
197
+ return text.replace(/_./g, match => ` ${ match.charAt(1).toUpperCase()}`)
198
+ .trim()
199
+ .replace(/^(.)|\s(.)/g, ($1) => $1.toUpperCase()).trim()
200
+ .replace(/\sA\s/g, ' a ') // replace a|the
201
+ .replace(/\sThe\s/g, ' the ') // replace a|the
202
+ .replace(/^Test\s/, '')
203
+ .replace(/^Should\s/, '')
204
+ }
205
+
206
+ /**
207
+ * From https://github.com/sindresorhus/decamelize/blob/main/index.js
208
+ * @param {*} text
209
+ * @returns
210
+ */
211
+ const decamelize = (text) => {
212
+ const separator = '_';
213
+ const replacement = `$1${separator}$2`;
214
+
215
+ // Split lowercase sequences followed by uppercase character.
216
+ // `dataForUSACounties` → `data_For_USACounties`
217
+ // `myURLstring → `my_URLstring`
218
+ let decamelized = text.replace(
219
+ /([\p{Lowercase_Letter}\d])(\p{Uppercase_Letter})/gu,
220
+ replacement,
221
+ );
222
+
223
+ // Lowercase all single uppercase characters. As we
224
+ // want to preserve uppercase sequences, we cannot
225
+ // simply lowercase the separated string at the end.
226
+ // `data_For_USACounties` → `data_for_USACounties`
227
+ decamelized = decamelized.replace(
228
+ /((?<![\p{Uppercase_Letter}\d])[\p{Uppercase_Letter}\d](?![\p{Uppercase_Letter}\d]))/gu,
229
+ $0 => $0.toLowerCase(),
230
+ );
231
+
232
+ // Remaining uppercase sequences will be separated from lowercase sequences.
233
+ // `data_For_USACounties` → `data_for_USA_counties`
234
+ return decamelized.replace(
235
+ /(\p{Uppercase_Letter}+)(\p{Uppercase_Letter}\p{Lowercase_Letter}+)/gu,
236
+ (_, $1, $2) => $1 + separator + $2.toLowerCase(),
237
+ );
238
+ };
239
+
195
240
  module.exports = {
196
241
  isSameTest,
197
242
  fetchSourceCode,
@@ -204,4 +249,5 @@ module.exports = {
204
249
  ansiRegExp,
205
250
  parseTest,
206
251
  parseSuite,
252
+ humanize,
207
253
  };
package/lib/xmlReader.js CHANGED
@@ -8,7 +8,7 @@ const { fetchFilesFromStackTrace, fetchSourceCode, fetchSourceCodeFromStackTrace
8
8
  const upload = require('./fileUploader');
9
9
  const pipesFactory = require('./pipe');
10
10
  const adapterFactory = require('./junit-adapter');
11
-
11
+ const { humanize } = require('./util')
12
12
 
13
13
  const TESTOMATIO_URL = process.env.TESTOMATIO_URL || "https://app.testomat.io";
14
14
  const TESTOMATIO = process.env.TESTOMATIO; // key?
@@ -35,7 +35,7 @@ class XmlReader {
35
35
  group_title: TESTOMATIO_RUNGROUP_TITLE,
36
36
  };
37
37
  this.runId = opts.runId || TESTOMATIO_RUN;
38
- this.adapter = adapterFactory(null, opts)
38
+ this.adapter = adapterFactory(opts.lang?.toLowerCase(), opts)
39
39
  if (!this.adapter) throw new Error('XML adapter for this format not found');
40
40
 
41
41
  this.opts = opts || {};
@@ -53,8 +53,12 @@ class XmlReader {
53
53
  }
54
54
 
55
55
  connectAdapter() {
56
- if (this.opts.javaTests) return adapterFactory('java', this.opts);
57
- return adapterFactory(this.stats.language, this.opts);
56
+ if (this.opts.javaTests) {
57
+ this.adapter = adapterFactory('java', this.opts);
58
+ return this.adapter;
59
+ }
60
+ this.adapter = adapterFactory(this.stats.language, this.opts);
61
+ return this.adapter;
58
62
  }
59
63
 
60
64
  parse(fileName) {
@@ -70,6 +74,8 @@ class XmlReader {
70
74
  return this.processTRX(jsonResult);
71
75
  } else if (jsonResult['test-run']) {
72
76
  return this.processNUnit(jsonResult['test-run']);
77
+ } else if (jsonResult.assemblies) {
78
+ return this.processXUnit(jsonResult.assemblies);
73
79
  } else {
74
80
  console.log(jsonResult)
75
81
  throw new Error("Format can't be parsed")
@@ -190,6 +196,79 @@ class XmlReader {
190
196
  };
191
197
  }
192
198
 
199
+ processXUnit(assemblies) {
200
+ const tests = [];
201
+
202
+ assemblies = Array.isArray(assemblies.assembly) ? assemblies.assembly : [assemblies.assembly];
203
+
204
+ assemblies.forEach(assembly => {
205
+ const { collection } = assembly;
206
+
207
+ const suites = Array.isArray(collection) ? collection : [collection];
208
+
209
+ suites.forEach(suite => {
210
+ const { test } = suite;
211
+ if (!test) return;
212
+ const cases = Array.isArray(test) ? test : [test];
213
+ cases.forEach(testCase => {
214
+ const { type, time, result } = testCase;
215
+
216
+ let message = '';
217
+ let stack = '';
218
+
219
+ if (testCase.failure) {
220
+ message = testCase.failure.message;
221
+ stack = testCase.failure['stack-trace']
222
+ }
223
+ if (testCase.reason) {
224
+ message = testCase.reason.message;
225
+ }
226
+
227
+ let status = STATUS.PASSED;
228
+ if (result === 'Pass') status = STATUS.PASSED;
229
+ if (result === 'Fail') status = STATUS.FAILED;
230
+ if (result === 'Skip') status = STATUS.SKIPPED;
231
+
232
+ const pathParts = type.split('.');
233
+ const suite_title = pathParts[pathParts.length - 1];
234
+ const file = pathParts.slice(0, -1).join('/');
235
+ const title = testCase.method || testCase.name.split('.').pop();
236
+ const run_time = parseFloat(time) * 1000;
237
+
238
+ tests.push({
239
+ create: true,
240
+ stack,
241
+ message,
242
+ file,
243
+ status,
244
+ title,
245
+ suite_title,
246
+ run_time,
247
+ });
248
+
249
+ });
250
+ });
251
+ });
252
+
253
+ const hasFailures = tests.filter(t => t.status === STATUS.FAILED).length > 0;
254
+ const status = hasFailures ? STATUS.FAILED : STATUS.PASSED;
255
+
256
+ this.tests = tests;
257
+
258
+ debug(tests);
259
+
260
+ return {
261
+ status,
262
+ create_tests: true,
263
+ name: 'xUnit',
264
+ tests_count: tests.length,
265
+ passed_count: tests.filter(t => t.status === STATUS.PASSED).length,
266
+ failed_count: tests.filter(t => t.status === STATUS.FAILED).length,
267
+ skipped_count: tests.filter(t => t.status === STATUS.SKIPPED).length,
268
+ tests,
269
+ };
270
+ }
271
+
193
272
  calculateStats() {
194
273
  this.stats = {
195
274
  ...this.stats,
@@ -241,18 +320,7 @@ class XmlReader {
241
320
 
242
321
  this.adapter.formatTest(t)
243
322
 
244
- t.title = t.title
245
- // insert a space before all caps
246
- .replace(/([A-Z])/g, ' $1')
247
- // _ chars to spaces
248
- .replace(/_/g, ' ')
249
- // uppercase the first character
250
- .replace(/^(.)|\s(.)/g, $1 => $1.toLowerCase())
251
-
252
- // remove standard prefixes
253
- .replace(/^test\s/, '')
254
- .replace(/^should\s/, '')
255
- .trim();
323
+ t.title = humanize(t.title);
256
324
  });
257
325
  }
258
326
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testomatio/reporter",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Testomatio Reporter Client",
5
5
  "main": "./lib/reporter.js",
6
6
  "typings": "typings/index.d.ts",