@testomatio/reporter 1.1.0-beta.codeceptjs-before-suite-logs → 1.1.0-beta.fix-junit-reporter

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/Changelog.md CHANGED
@@ -1,4 +1,12 @@
1
1
  <!-- pending release updates -->
2
+ # 1.1.0
3
+
4
+ * Assign Run by label:
5
+
6
+ ```
7
+ TESTOMATIO={API_KEY} TESTOMATIO_LABEL="release,module:checkout" <actual run command>
8
+ ```
9
+
2
10
  # 1.0.18
3
11
 
4
12
  * Fixed stack traces for CodeceptJS
@@ -78,35 +78,8 @@ function CodeceptReporter(config) {
78
78
  global.testomatioDataStore.steps = [];
79
79
  });
80
80
 
81
- let hookSteps = [];
82
- let suiteHookRunning = false;
83
-
84
- event.dispatcher.on(event.suite.before, (suite) => {
85
- suiteHookRunning = true;
86
- hookSteps = [];
87
- global.testomatioDataStore.steps = [];
88
- });
89
-
90
- event.dispatcher.on(event.test.before, () => {
91
- suiteHookRunning = false;
92
- global.testomatioDataStore.steps = []
93
- });
94
-
95
- event.dispatcher.on(event.hook.started, (suite) => {
96
- // global.testomatioDataStore.steps = [];
97
- });
98
-
99
- event.dispatcher.on(event.hook.passed, (suite) => {
100
- if (suiteHookRunning) hookSteps.push(...global.testomatioDataStore.steps);
101
- });
102
-
103
- event.dispatcher.on(event.hook.failed, (suite) => {
104
- if (suiteHookRunning) hookSteps.push(...global.testomatioDataStore.steps);
105
- });
106
-
107
81
  event.dispatcher.on(event.test.started, test => {
108
82
  testTimeMap[test.id] = Date.now();
109
-
110
83
  if (global.testomatioDataStore) global.testomatioDataStore.currentlyRunningTestId = getIdFromTestTitle(test.title);
111
84
  });
112
85
 
@@ -116,7 +89,7 @@ function CodeceptReporter(config) {
116
89
  await Promise.all(reportTestPromises);
117
90
 
118
91
  if (upload.isArtifactsEnabled()) {
119
- uploadAttachments(client, videos, '🎞️ Uploading', 'video');
92
+ uploadAttachments(client, videos, '🎞️ Uploading', 'video');
120
93
  uploadAttachments(client, traces, '📁 Uploading', 'trace');
121
94
  }
122
95
 
@@ -136,7 +109,7 @@ function CodeceptReporter(config) {
136
109
  suite_title: test.parent && test.parent.title,
137
110
  message: testObj.message,
138
111
  time: getDuration(test),
139
- steps: [...hookSteps, ...global.testomatioDataStore.steps].join('\n') || null,
112
+ steps: global.testomatioDataStore.steps.join('\n') || null,
140
113
  test_id: testId,
141
114
  });
142
115
  // output.stop();
@@ -160,7 +133,6 @@ function CodeceptReporter(config) {
160
133
  ...stripExampleFromTitle(title),
161
134
  suite_title: suite.title,
162
135
  test_id: testId,
163
- steps: hookSteps.join('\n') || null,
164
136
  error,
165
137
  time: 0,
166
138
  });
@@ -189,7 +161,7 @@ function CodeceptReporter(config) {
189
161
  message: testObj.message,
190
162
  time: getDuration(test),
191
163
  files,
192
- steps: [...hookSteps, ...global.testomatioDataStore.steps].join('\n') || null,
164
+ steps: global.testomatioDataStore?.steps?.join('\n') || null,
193
165
  })
194
166
  .then(pipes => {
195
167
  testId = pipes.filter(p => p.pipe.includes('Testomatio'))[0]?.result?.data?.test_id;
@@ -6,6 +6,7 @@ const { STATUS, TESTOMAT_TMP_STORAGE_DIR } = require('../../constants');
6
6
  const TestomatClient = require('../../client');
7
7
  const logger = require('../../storages/logger');
8
8
  const { parseTest, fileSystem } = require('../../utils/utils');
9
+ const { TESTOMATIO } = require('../../config');
9
10
 
10
11
  const { GherkinDocumentParser, PickleParser } = formatterHelpers;
11
12
  const { getGherkinScenarioLocationMap, getGherkinStepMap } = GherkinDocumentParser;
@@ -29,7 +30,7 @@ class CucumberReporter extends Formatter {
29
30
  this.failures = [];
30
31
  this.cases = [];
31
32
 
32
- this.client = new TestomatClient({ apiKey: options.apiKey || process.env.TESTOMATIO });
33
+ this.client = new TestomatClient({ apiKey: options.apiKey || TESTOMATIO });
33
34
  this.status = STATUS.PASSED;
34
35
 
35
36
  global.testomatioRunningEnvironment = 'cucumber:current';
@@ -4,6 +4,7 @@ const chalk = require('chalk');
4
4
  const { parseTest, fileSystem } = require('../../utils/utils');
5
5
  const { STATUS, TESTOMAT_TMP_STORAGE_DIR } = require('../../constants');
6
6
  const TestomatClient = require('../../client');
7
+ const { TESTOMATIO } = require('../../config');
7
8
 
8
9
  const createTestomatFormatter = apiKey => {
9
10
  if (!apiKey || apiKey === '') {
@@ -151,4 +152,4 @@ const createTestomatFormatter = apiKey => {
151
152
  };
152
153
  };
153
154
 
154
- module.exports = createTestomatFormatter(process.env.TESTOMATIO);
155
+ module.exports = createTestomatFormatter(TESTOMATIO);
@@ -1,18 +1,19 @@
1
1
  const { STATUS } = require('../../constants');
2
2
  const { parseTest, parseSuite } = require('../../utils/utils');
3
3
  const TestomatClient = require('../../client');
4
+ const { TESTOMATIO } = require('../../config');
4
5
 
5
6
  const testomatioReporter = on => {
6
- if (!process.env.TESTOMATIO) {
7
+ if (!TESTOMATIO) {
7
8
  console.log('TESTOMATIO key is empty, ignoring reports');
8
- return
9
+ return;
9
10
  }
10
- const client = new TestomatClient({ apiKey: process.env.TESTOMATIO });
11
+ const client = new TestomatClient({ apiKey: TESTOMATIO });
11
12
 
12
- on('before:run', async (run) => {
13
+ on('before:run', async run => {
13
14
  // TODO: looks like client.env does not exist
14
15
  if (!client.env) {
15
- client.env = `${run.browser.displayName},${run.system.osName}`
16
+ client.env = `${run.browser.displayName},${run.system.osName}`;
16
17
  }
17
18
  await client.createRun();
18
19
  });
@@ -26,8 +27,9 @@ const testomatioReporter = on => {
26
27
  const lastAttemptIndex = test.attempts.length - 1;
27
28
  const latestAttempt = test.attempts[lastAttemptIndex];
28
29
 
29
- const time = latestAttempt.duration;
30
- const error = latestAttempt.error;
30
+ // latestAttempt.duration && latestAttempt.error were available in adapters version up to 13 JFYI
31
+ const time = latestAttempt.duration || latestAttempt.wallClockDuration || test.duration;
32
+ let error = latestAttempt.error;
31
33
 
32
34
  let title = test.title.pop();
33
35
  const examples = title.match(/\(example (#\d+)\)/);
@@ -40,23 +42,28 @@ const testomatioReporter = on => {
40
42
  const testId = parseTest(title);
41
43
  const suiteId = parseSuite(suiteTitle);
42
44
 
43
- if (error) {
44
- error.inspect = function() { // eslint-disable-line func-names
45
- if (this && this.codeFrame) {
46
- return this.codeFrame.frame;
47
- }
48
- return '';
49
- }
45
+ if (!error && test.displayError) {
46
+ error = { message: test.displayError };
47
+ error.inspect = function () {
48
+ // eslint-disable-line func-names
49
+ return this.message;
50
+ };
50
51
  }
51
52
 
53
+ const formattedError = error
54
+ ? {
55
+ message: error.message,
56
+ inspect:
57
+ error.inspect ||
58
+ function () {
59
+ return this.message;
60
+ },
61
+ }
62
+ : '';
63
+
52
64
  const screenshots = Array.isArray(results.screenshots)
53
65
  ? results.screenshots
54
- .filter(
55
- screenshot =>
56
- screenshot?.path &&
57
- screenshot?.path.includes(title) &&
58
- screenshot?.takenAt
59
- )
66
+ .filter(screenshot => screenshot?.path && screenshot?.path.includes(title) && screenshot?.takenAt)
60
67
  .map(screenshot => screenshot.path)
61
68
  : [];
62
69
 
@@ -64,17 +71,30 @@ const testomatioReporter = on => {
64
71
 
65
72
  let state;
66
73
  switch (test.state) {
67
- case 'passed': state = STATUS.PASSED; break;
68
- case 'failed': state = STATUS.FAILED; break;
74
+ case 'passed':
75
+ state = STATUS.PASSED;
76
+ break;
77
+ case 'failed':
78
+ state = STATUS.FAILED;
79
+ break;
69
80
  case 'skipped':
70
- case 'pending':
81
+ case 'pending':
71
82
  default:
72
83
  state = STATUS.SKIPPED;
73
84
  }
74
85
 
75
- addSpecTestsPromises.push(client.addTestRun(state, {
76
- title, time, example, error, files, suite_title: suiteTitle, test_id: testId, suite_id: suiteId
77
- }));
86
+ addSpecTestsPromises.push(
87
+ client.addTestRun(state, {
88
+ title,
89
+ time,
90
+ example,
91
+ error: formattedError,
92
+ files,
93
+ suite_title: suiteTitle,
94
+ test_id: testId,
95
+ suite_id: suiteId,
96
+ }),
97
+ );
78
98
  }
79
99
 
80
100
  await Promise.all(addSpecTestsPromises);
@@ -4,6 +4,7 @@ const chalk = require('chalk');
4
4
  const TestomatClient = require('../client');
5
5
  const { STATUS, TESTOMAT_TMP_STORAGE_DIR } = require('../constants');
6
6
  const { parseTest, fileSystem } = require('../utils/utils');
7
+ const { TESTOMATIO } = require('../config');
7
8
 
8
9
  const { EVENT_RUN_BEGIN, EVENT_RUN_END, EVENT_TEST_FAIL, EVENT_TEST_PASS, EVENT_TEST_PENDING } =
9
10
  Mocha.Runner.constants;
@@ -15,7 +16,7 @@ function MochaReporter(runner, opts) {
15
16
  let skipped = 0;
16
17
  // let artifactStore;
17
18
 
18
- const apiKey = opts?.reporterOptions?.apiKey || process.env.TESTOMATIO;
19
+ const apiKey = opts?.reporterOptions?.apiKey || TESTOMATIO;
19
20
 
20
21
  const client = new TestomatClient({ apiKey });
21
22
 
@@ -5,6 +5,7 @@ const chalk = require('chalk');
5
5
  const TestomatClient = require('../client');
6
6
  const { APP_PREFIX, STATUS } = require('../constants');
7
7
  const { version } = require('../../package.json');
8
+ const { TESTOMATIO } = require('../config');
8
9
 
9
10
  console.log(chalk.cyan.bold(` 🤩 Testomat.io Reporter v${version}`));
10
11
 
@@ -20,7 +21,7 @@ program
20
21
 
21
22
  if (opts.envFile) require('dotenv').config(opts.envFile); // eslint-disable-line
22
23
 
23
- const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || process.env.TESTOMATIO;
24
+ const apiKey = process.env['INPUT_TESTOMATIO-KEY'] || TESTOMATIO;
24
25
  const title = process.env.TESTOMATIO_TITLE;
25
26
 
26
27
  if (launch) {
package/lib/config.js CHANGED
@@ -8,6 +8,10 @@ const debug = require('debug')('@testomatio/reporter:config');
8
8
  const dotenv = require('dotenv');
9
9
  const envFileVars = dotenv.config({ path: '.env' }).parsed; */
10
10
 
11
+ const TESTOMATIO = process.env.TESTOMATIO || process.env.TESTOMATIO_API_KEY || process.env.TESTOMATIO_TOKEN || '';
12
+ if (TESTOMATIO === 'undefined') console.error('TESTOMATIO is "undefined". Something went wrong. Contact dev team.');
13
+ process.env.TESTOMATIO = TESTOMATIO;
14
+
11
15
  // select only TESTOMATIO related variables (only to print them in debug)
12
16
  const testomatioEnvVars =
13
17
  Object.keys(process.env)
@@ -22,3 +26,4 @@ debug('TESTOMATIO variables:', testomatioEnvVars);
22
26
  const config = process.env;
23
27
 
24
28
  module.exports = config;
29
+ module.exports.TESTOMATIO = TESTOMATIO;
@@ -5,6 +5,7 @@ const JsonCycle = require('json-cycle');
5
5
  const { APP_PREFIX, STATUS } = require('../constants');
6
6
  const { isValidUrl, foundedTestLog } = require('../utils/utils');
7
7
  const { parseFilterParams, generateFilterRequestParams, setS3Credentials, } = require('../utils/pipe_utils');
8
+ const { TESTOMATIO } = require('../config');
8
9
 
9
10
  if (process.env.TESTOMATIO_RUN) {
10
11
  process.env.runId = process.env.TESTOMATIO_RUN;
@@ -20,7 +21,7 @@ class TestomatioPipe {
20
21
  constructor(params, store) {
21
22
  this.isEnabled = false;
22
23
  this.url = params.testomatioUrl || process.env.TESTOMATIO_URL || 'https://app.testomat.io';
23
- this.apiKey = params.apiKey || process.env.TESTOMATIO;
24
+ this.apiKey = params.apiKey || TESTOMATIO;
24
25
  debug('Testomatio Pipe: ', this.apiKey ? 'API KEY' : '*no api key*');
25
26
  if (!this.apiKey) {
26
27
  return;
@@ -32,6 +33,7 @@ class TestomatioPipe {
32
33
  this.sharedRun = !!process.env.TESTOMATIO_SHARED_RUN;
33
34
  this.groupTitle = params.groupTitle || process.env.TESTOMATIO_RUNGROUP_TITLE;
34
35
  this.env = process.env.TESTOMATIO_ENV;
36
+ this.label = process.env.TESTOMATIO_LABEL;
35
37
 
36
38
  this.axios = axios.create({
37
39
  baseURL: `${this.url.trim()}`,
@@ -130,6 +132,7 @@ class TestomatioPipe {
130
132
  jira_id: this.jiraId,
131
133
  env: this.env,
132
134
  title: this.title,
135
+ label: this.label,
133
136
  shared_run: this.sharedRun,
134
137
  }).filter(([, value]) => !!value),
135
138
  );
@@ -141,7 +141,12 @@ const fetchSourceCode = (contents, opts = {}) => {
141
141
  // remove special chars from title
142
142
  if (!lineIndex && opts.title) {
143
143
  const title = opts.title.replace(/[([@].*/g, '');
144
- lineIndex = lines.findIndex(l => l.includes(title));
144
+
145
+ if (opts.lang === 'java') {
146
+ lineIndex = lines.findIndex(l => l.includes(`test${title}`));
147
+ } else {
148
+ lineIndex = lines.findIndex(l => l.includes(title));
149
+ }
145
150
  }
146
151
 
147
152
  if (opts.prepend) {
package/lib/xmlReader.js CHANGED
@@ -1,35 +1,36 @@
1
1
  const debug = require('debug')('@testomatio/reporter:xml');
2
- const path = require("path");
2
+ const path = require('path');
3
3
  const chalk = require('chalk');
4
- const fs = require("fs");
5
- const { XMLParser } = require("fast-xml-parser");
4
+ const fs = require('fs');
5
+ const { XMLParser } = require('fast-xml-parser');
6
6
  const { APP_PREFIX, STATUS } = require('./constants');
7
- const { fetchFilesFromStackTrace,
8
- fetchIdFromOutput,
9
- fetchSourceCode,
10
- fetchSourceCodeFromStackTrace,
11
- fetchIdFromCode,
12
- humanize
13
- } = require('./utils/utils');
7
+ const {
8
+ fetchFilesFromStackTrace,
9
+ fetchIdFromOutput,
10
+ fetchSourceCode,
11
+ fetchSourceCodeFromStackTrace,
12
+ fetchIdFromCode,
13
+ humanize,
14
+ } = require('./utils/utils');
14
15
  const upload = require('./fileUploader');
15
16
  const pipesFactory = require('./pipe');
16
17
  const adapterFactory = require('./junit-adapter');
18
+ const { TESTOMATIO } = require('./config');
17
19
 
18
- const TESTOMATIO_URL = process.env.TESTOMATIO_URL || "https://app.testomat.io";
19
- const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_TITLE, TESTOMATIO_ENV, TESTOMATIO_RUN, TESTOMATIO } = process.env;
20
+ const TESTOMATIO_URL = process.env.TESTOMATIO_URL || 'https://app.testomat.io';
21
+ const { TESTOMATIO_RUNGROUP_TITLE, TESTOMATIO_TITLE, TESTOMATIO_ENV, TESTOMATIO_RUN } = process.env;
20
22
 
21
23
  const options = {
22
24
  ignoreDeclaration: true,
23
25
  ignoreAttributes: false,
24
26
  alwaysCreateTextNode: false,
25
- attributeNamePrefix: "",
27
+ attributeNamePrefix: '',
26
28
  parseTagValue: true,
27
29
  };
28
30
 
29
31
  const reduceOptions = {};
30
32
 
31
33
  class XmlReader {
32
-
33
34
  constructor(opts = {}) {
34
35
  this.requestParams = {
35
36
  apiKey: opts.apiKey || TESTOMATIO,
@@ -39,18 +40,18 @@ class XmlReader {
39
40
  group_title: TESTOMATIO_RUNGROUP_TITLE,
40
41
  };
41
42
  this.runId = opts.runId || TESTOMATIO_RUN;
42
- this.adapter = adapterFactory(opts.lang?.toLowerCase(), opts)
43
+ this.adapter = adapterFactory(opts.lang?.toLowerCase(), opts);
43
44
  if (!this.adapter) throw new Error('XML adapter for this format not found');
44
45
 
45
46
  this.opts = opts || {};
46
- this.store = {}
47
+ this.store = {};
47
48
  this.pipes = pipesFactory(opts, this.store);
48
49
 
49
50
  this.parser = new XMLParser(options);
50
- this.tests = []
51
- this.stats = {}
51
+ this.tests = [];
52
+ this.stats = {};
52
53
  this.stats.language = opts.lang?.toLowerCase();
53
- this.filesToUpload = {}
54
+ this.filesToUpload = {};
54
55
 
55
56
  this.version = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json')).toString()).version;
56
57
  console.log(APP_PREFIX, `Testomatio Reporter v${this.version}`);
@@ -81,8 +82,8 @@ class XmlReader {
81
82
  } else if (jsonResult.assemblies) {
82
83
  return this.processXUnit(jsonResult.assemblies);
83
84
  } else {
84
- console.log(jsonResult)
85
- throw new Error("Format can't be parsed")
85
+ console.log(jsonResult);
86
+ throw new Error("Format can't be parsed");
86
87
  }
87
88
 
88
89
  return this.processJUnit(jsonSuite);
@@ -95,7 +96,7 @@ class XmlReader {
95
96
  const resultTests = processTestSuite(testsuite);
96
97
 
97
98
  const hasFailures = resultTests.filter(t => t.status === 'failed').length > 0;
98
- const status = (failures > 0 || errors > 0 || hasFailures) ? 'failed' : 'passed';
99
+ const status = failures > 0 || errors > 0 || hasFailures ? 'failed' : 'passed';
99
100
 
100
101
  this.tests = this.tests.concat(resultTests);
101
102
 
@@ -134,21 +135,22 @@ class XmlReader {
134
135
  let defs = jsonSuite?.TestRun?.TestDefinitions?.UnitTest;
135
136
  if (!Array.isArray(defs)) defs = [defs].filter(d => !!d);
136
137
 
137
- const tests = defs.map(td => {
138
- const title = td.name.replace(/\(.*?\)/, '').trim();
139
- let example = td.name.match(/\((.*?)\)/);
140
- if (example) example = { ...example[1].split(',') };
141
- const suite = td.TestMethod.className.split(', ')[0].split('.');
142
- const suite_title = suite.pop();
143
- return {
144
- title,
145
- example,
146
- file: suite.join('/'),
147
- description: td.Description,
148
- suite_title,
149
- id: td.Execution.id,
150
- }
151
- }) || [];
138
+ const tests =
139
+ defs.map(td => {
140
+ const title = td.name.replace(/\(.*?\)/, '').trim();
141
+ let example = td.name.match(/\((.*?)\)/);
142
+ if (example) example = { ...example[1].split(',') };
143
+ const suite = td.TestMethod.className.split(', ')[0].split('.');
144
+ const suite_title = suite.pop();
145
+ return {
146
+ title,
147
+ example,
148
+ file: suite.join('/'),
149
+ description: td.Description,
150
+ suite_title,
151
+ id: td.Execution.id,
152
+ };
153
+ }) || [];
152
154
 
153
155
  let result = jsonSuite?.TestRun?.Results?.UnitTestResult;
154
156
  if (!Array.isArray(result)) result = [result].filter(d => !!d);
@@ -159,10 +161,9 @@ class XmlReader {
159
161
  run_time: parseFloat(td.duration) * 1000,
160
162
  status: td.outcome,
161
163
  stack: td.Output.StdOut,
162
- files: td?.ResultFiles?.ResultFile?.map(rf => rf.path)
164
+ files: td?.ResultFiles?.ResultFile?.map(rf => rf.path),
163
165
  }));
164
166
 
165
-
166
167
  results.forEach(r => {
167
168
  const test = tests.find(t => t.id === r.id) || {};
168
169
  r.suite_title = test.suite_title;
@@ -222,7 +223,7 @@ class XmlReader {
222
223
 
223
224
  if (testCase.failure) {
224
225
  message = testCase.failure.message;
225
- stack = testCase.failure['stack-trace']
226
+ stack = testCase.failure['stack-trace'];
226
227
  }
227
228
  if (testCase.reason) {
228
229
  message = testCase.reason.message;
@@ -249,7 +250,6 @@ class XmlReader {
249
250
  suite_title,
250
251
  run_time,
251
252
  });
252
-
253
253
  });
254
254
  });
255
255
  });
@@ -282,12 +282,12 @@ class XmlReader {
282
282
  passed_count: 0,
283
283
  failed_count: 0,
284
284
  skipped_count: 0,
285
- }
285
+ };
286
286
  this.tests.forEach(t => {
287
287
  this.stats.tests_count++;
288
288
  if (t.status === 'passed') this.stats.passed_count++;
289
289
  if (t.status === 'failed') this.stats.failed_count++;
290
- })
290
+ });
291
291
  if (this.stats.failed_count) this.stats.status = 'failed';
292
292
 
293
293
  return this.stats;
@@ -296,7 +296,7 @@ class XmlReader {
296
296
  fetchSourceCode() {
297
297
  this.tests.forEach(t => {
298
298
  try {
299
- const file = this.adapter.getFilePath(t)
299
+ const file = this.adapter.getFilePath(t);
300
300
  if (!file) return;
301
301
 
302
302
  if (!this.stats.language) {
@@ -309,16 +309,16 @@ class XmlReader {
309
309
  }
310
310
 
311
311
  if (!fs.existsSync(file)) {
312
- debug('Failed to open file with the source code', file)
312
+ debug('Failed to open file with the source code', file);
313
313
  return;
314
314
  }
315
315
  const contents = fs.readFileSync(file).toString();
316
- t.code = fetchSourceCode(contents, { ...t, lang: this.stats.language })
316
+ t.code = fetchSourceCode(contents, { ...t, lang: this.stats.language });
317
317
  if (t.code) debug('Fetched code for test %s', t.title);
318
- t.test_id = fetchIdFromCode(t.code, { lang: this.stats.language })
318
+ t.test_id = fetchIdFromCode(t.code, { lang: this.stats.language });
319
319
  if (t.test_id) debug('Fetched test id %s for test %s', t.test_id, t.title);
320
320
  } catch (err) {
321
- debug(err)
321
+ debug(err);
322
322
  }
323
323
  });
324
324
  }
@@ -326,21 +326,22 @@ class XmlReader {
326
326
  formatTests() {
327
327
  this.tests.forEach(t => {
328
328
  if (t.file) {
329
- t.file = t.file.replace(process.cwd() + path.sep, '')
329
+ t.file = t.file.replace(process.cwd() + path.sep, '');
330
330
  }
331
331
 
332
- this.adapter.formatTest(t)
332
+ this.adapter.formatTest(t);
333
333
 
334
334
  t.title = humanize(t.title);
335
335
  });
336
336
  }
337
337
 
338
338
  formatErrors() {
339
- this.tests.filter(t => !!t.stack).forEach(t => {
340
- t.stack = this.formatStack(t)
341
- t.message = this.adapter.formatMessage(t);
342
- });
343
-
339
+ this.tests
340
+ .filter(t => !!t.stack)
341
+ .forEach(t => {
342
+ t.stack = this.formatStack(t);
343
+ t.message = this.adapter.formatMessage(t);
344
+ });
344
345
  }
345
346
 
346
347
  formatStack(t) {
@@ -358,7 +359,7 @@ class XmlReader {
358
359
  async uploadArtifacts() {
359
360
  for (const test of this.tests.filter(t => !!t.stack)) {
360
361
  let files = [];
361
- if (test.files?.length) files = test.files.map(f => path.join(process.cwd(), f))
362
+ if (test.files?.length) files = test.files.map(f => path.join(process.cwd(), f));
362
363
  files = [...files, ...fetchFilesFromStackTrace(test.stack)];
363
364
 
364
365
  if (!files.length) continue;
@@ -377,7 +378,7 @@ class XmlReader {
377
378
  group_title: this.requestParams.group_title,
378
379
  };
379
380
 
380
- debug("Run", runParams);
381
+ debug('Run', runParams);
381
382
 
382
383
  return Promise.all(this.pipes.map(p => p.createRun(runParams)));
383
384
  }
@@ -390,12 +391,10 @@ class XmlReader {
390
391
  this.formatErrors();
391
392
  this.formatTests();
392
393
 
393
- debug(
394
- 'Uploading data',
395
- {
396
- ...this.stats,
397
- tests: this.tests,
398
- })
394
+ debug('Uploading data', {
395
+ ...this.stats,
396
+ tests: this.tests,
397
+ });
399
398
 
400
399
  const dataString = {
401
400
  ...this.stats,
@@ -410,59 +409,62 @@ class XmlReader {
410
409
 
411
410
  module.exports = XmlReader;
412
411
 
413
-
414
412
  function reduceTestCases(prev, item) {
415
413
  let testCases = item.testcase;
416
414
  if (!testCases) testCases = item['test-case'];
417
415
  if (!Array.isArray(testCases)) {
418
- testCases = [testCases]
416
+ testCases = [testCases];
419
417
  }
420
418
  const suiteOutput = item['system-out'] || item.output || item.log || '';
421
419
  const suiteErr = item['system-err'] || item.output || item.log || '';
422
- testCases.filter(t => !!t).forEach(testCaseItem => {
423
- const file = testCaseItem.file || item.filepath || '';
424
-
425
- let stack = '';
426
- let message = '';
427
- if (testCaseItem.error) stack = testCaseItem.error;
428
- if (testCaseItem.failure) stack = testCaseItem.failure;
429
- if (testCaseItem?.failure?.['stack-trace']) stack = testCaseItem.failure['stack-trace'];
430
- if (testCaseItem?.failure?.message) message = testCaseItem.failure.message;
431
- if (testCaseItem?.error?.message) message = testCaseItem.error.message;
432
-
433
- if (testCaseItem.failure && testCaseItem.failure['#text']) stack = testCaseItem.failure['#text'];
434
- if (testCaseItem.error && testCaseItem.error['#text']) stack = testCaseItem.error['#text'];
435
- if (!message) message = stack.trim().split('\n')[0];
436
-
437
- // eslint-disable-next-line
438
- stack = `${testCaseItem['system-out'] || testCaseItem.output || testCaseItem.log || ''}\n\n${stack}\n\n${suiteOutput}\n\n${suiteErr}`.trim()
439
- const testId = fetchIdFromOutput(stack);
440
-
441
- let status = STATUS.PASSED.toString();
442
- if ('failure' in testCaseItem || 'error' in testCaseItem) status = STATUS.FAILED;
443
- if ('skipped' in testCaseItem) status = STATUS.SKIPPED;
444
-
445
- prev.push({
446
- create: true,
447
- file,
448
- stack,
449
- test_id: testId,
450
- message,
451
- line: testCaseItem.lineno,
452
- // seconds are used in junit reports, but ms are used by testomatio
453
- run_time: parseFloat(testCaseItem.time || testCaseItem.duration) * 1000,
454
- status,
455
- title: testCaseItem.name,
456
- suite_title: reduceOptions.preferClassname ? testCaseItem.classname : (item.name || testCaseItem.classname),
457
- })
458
- });
420
+ testCases
421
+ .filter(t => !!t)
422
+ .forEach(testCaseItem => {
423
+ const file = testCaseItem.file || item.filepath || '';
424
+
425
+ let stack = '';
426
+ let message = '';
427
+ if (testCaseItem.error) stack = testCaseItem.error;
428
+ if (testCaseItem.failure) stack = testCaseItem.failure;
429
+ if (testCaseItem?.failure?.['stack-trace']) stack = testCaseItem.failure['stack-trace'];
430
+ if (testCaseItem?.failure?.message) message = testCaseItem.failure.message;
431
+ if (testCaseItem?.error?.message) message = testCaseItem.error.message;
432
+
433
+ if (testCaseItem.failure && testCaseItem.failure['#text']) stack = testCaseItem.failure['#text'];
434
+ if (testCaseItem.error && testCaseItem.error['#text']) stack = testCaseItem.error['#text'];
435
+ if (!message) message = stack.trim().split('\n')[0];
436
+
437
+ // eslint-disable-next-line
438
+ stack = `${
439
+ testCaseItem['system-out'] || testCaseItem.output || testCaseItem.log || ''
440
+ }\n\n${stack}\n\n${suiteOutput}\n\n${suiteErr}`.trim();
441
+ const testId = fetchIdFromOutput(stack);
442
+
443
+ let status = STATUS.PASSED.toString();
444
+ if ('failure' in testCaseItem || 'error' in testCaseItem) status = STATUS.FAILED;
445
+ if ('skipped' in testCaseItem) status = STATUS.SKIPPED;
446
+
447
+ prev.push({
448
+ create: true,
449
+ file,
450
+ stack,
451
+ test_id: testId,
452
+ message,
453
+ line: testCaseItem.lineno,
454
+ // seconds are used in junit reports, but ms are used by testomatio
455
+ run_time: parseFloat(testCaseItem.time || testCaseItem.duration) * 1000,
456
+ status,
457
+ title: testCaseItem.name,
458
+ suite_title: reduceOptions.preferClassname ? testCaseItem.classname : item.name || testCaseItem.classname,
459
+ });
460
+ });
459
461
  return prev;
460
462
  }
461
463
 
462
464
  function processTestSuite(testsuite) {
463
465
  if (!testsuite) return [];
464
- if (testsuite.testsuite) return processTestSuite(testsuite.testsuite)
465
- if (testsuite['test-suite']) return processTestSuite(testsuite['test-suite'])
466
+ if (testsuite.testsuite) return processTestSuite(testsuite.testsuite);
467
+ if (testsuite['test-suite']) return processTestSuite(testsuite['test-suite']);
466
468
 
467
469
  let suites = testsuite;
468
470
  if (!Array.isArray(testsuite)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testomatio/reporter",
3
- "version": "1.1.0-beta.codeceptjs-before-suite-logs",
3
+ "version": "1.1.0-beta.fix-junit-reporter",
4
4
  "description": "Testomatio Reporter Client",
5
5
  "main": "./lib/reporter.js",
6
6
  "typings": "typings/index.d.ts",