@testomatio/reporter 1.0.12 → 1.0.13
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 +322 -0
- package/lib/bin/reportXml.js +1 -0
- package/lib/util.js +39 -4
- package/lib/xmlReader.js +50 -30
- package/package.json +1 -1
package/Changelog.md
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
<!-- pending release updates -->
|
|
2
|
+
# 1.0.13
|
|
3
|
+
|
|
4
|
+
* JUnit improvements
|
|
5
|
+
* Match test from source code by adding Test ID as a comment:
|
|
6
|
+
|
|
7
|
+
```java
|
|
8
|
+
// @T8acca9eb
|
|
9
|
+
```
|
|
10
|
+
* Match test from output by adding Test ID as output:
|
|
11
|
+
|
|
12
|
+
```java
|
|
13
|
+
System.out.println("tid://@T8acca9eb");
|
|
14
|
+
```
|
|
15
|
+
* Support for suite before and after output
|
|
16
|
+
* Improved support for artifacts
|
|
17
|
+
|
|
18
|
+
# 1.0.12
|
|
19
|
+
|
|
20
|
+
& Logger refactoring by @olexandr13 in #208
|
|
21
|
+
* fix undefined logs by @olexandr13 in #210
|
|
22
|
+
|
|
23
|
+
# 1.0.11
|
|
24
|
+
|
|
25
|
+
* fix steps duplication for codecept report by @olexandr13 in #209
|
|
26
|
+
|
|
27
|
+
# 1.0.10
|
|
28
|
+
|
|
29
|
+
* Added `TESTOMATIO_PUBLISH=1` variable to automatically publish run report
|
|
30
|
+
|
|
31
|
+
# 1.0.9
|
|
32
|
+
|
|
33
|
+
* Support XUnit format
|
|
34
|
+
* Improved support for parametrized Java tests
|
|
35
|
+
|
|
36
|
+
# 1.0.8
|
|
37
|
+
|
|
38
|
+
* Fixed `Can't read push of undefined` when logging steps
|
|
39
|
+
|
|
40
|
+
# 1.0.6
|
|
41
|
+
|
|
42
|
+
* Testomat.io. Auto-detect current build url and report it to Testomat.io. Manually url can be set with `BUILD_URL` variable:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
BUILD_URL=https://.... TESTOMATIO=apiKey <actual test command>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
# 1.0.5
|
|
49
|
+
|
|
50
|
+
* Fix "create tests" params processing for testomatio pipe
|
|
51
|
+
|
|
52
|
+
# 1.0.4
|
|
53
|
+
|
|
54
|
+
* Fixed parallel run
|
|
55
|
+
|
|
56
|
+
# 1.0.3
|
|
57
|
+
|
|
58
|
+
* Fixed reporting parallel runs
|
|
59
|
+
|
|
60
|
+
# 1.0.0
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
* Added [`TESTOMATIO_SHARED_RUN` option](https://github.com/testomatio/reporter/blob/master/docs/pipes.md#reporting-parallel-execution-to-to-same-run) to use a shared run for parallel executions
|
|
64
|
+
* Reworked [documentation](https://github.com/testomatio/reporter/tree/master#readme).
|
|
65
|
+
* Added an option to obtain [S3 configuration](https://github.com/testomatio/reporter/blob/master/docs/artifacts.md#configuration) from Testomat.io
|
|
66
|
+
* Introduced [pipes](https://github.com/testomatio/reporter/blob/master/docs/pipes.md):
|
|
67
|
+
* GitHub
|
|
68
|
+
* GitLab
|
|
69
|
+
* CSV Pipe
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# 0.7.6
|
|
73
|
+
|
|
74
|
+
* Updated to use AWS S3 3.0 SDK for uploading
|
|
75
|
+
|
|
76
|
+
# 0.7.5
|
|
77
|
+
|
|
78
|
+
* Fixed reporting skipped tests in mocha
|
|
79
|
+
|
|
80
|
+
# 0.7.4
|
|
81
|
+
|
|
82
|
+
* Fixed parsing source code in JUnit files
|
|
83
|
+
|
|
84
|
+
# 0.7.3
|
|
85
|
+
|
|
86
|
+
* CodeceptJS: Upload all traces and videos from artifacts
|
|
87
|
+
* Fixed reporting skipped test in XML
|
|
88
|
+
* added `--timelimit` option to `report-xml` command line
|
|
89
|
+
|
|
90
|
+
# 0.7.2
|
|
91
|
+
|
|
92
|
+
* Fixed uploading non-existing file
|
|
93
|
+
|
|
94
|
+
# 0.7.1
|
|
95
|
+
|
|
96
|
+
* Support for NUnit XML v3 format
|
|
97
|
+
|
|
98
|
+
# 0.7.0
|
|
99
|
+
|
|
100
|
+
* Support for `@cucumber/cucumber` (>= 7.0) added
|
|
101
|
+
* Initial support for C# and NUnit
|
|
102
|
+
|
|
103
|
+
# 0.6.10
|
|
104
|
+
|
|
105
|
+
* Fixed uploading multilpe artifacts in Playwright
|
|
106
|
+
|
|
107
|
+
# 0.6.9
|
|
108
|
+
|
|
109
|
+
* Fixed pending tests reports for Cypress
|
|
110
|
+
|
|
111
|
+
# 0.6.8
|
|
112
|
+
# 0.6.7
|
|
113
|
+
|
|
114
|
+
* Pytest: fixed creating suites from reports
|
|
115
|
+
|
|
116
|
+
# 0.6.6
|
|
117
|
+
|
|
118
|
+
* JUnit reporter: prefer suite title over testcase classname in a report
|
|
119
|
+
|
|
120
|
+
# 0.6.5
|
|
121
|
+
|
|
122
|
+
* Fixed test statuses for runs in JUnit reporter
|
|
123
|
+
|
|
124
|
+
# 0.6.4
|
|
125
|
+
|
|
126
|
+
* Added `TESTOMATIO_PROCEED=1` param to not close current run
|
|
127
|
+
* Fixed priority of commands from `npx @testomatio/reporter`
|
|
128
|
+
|
|
129
|
+
# 0.6.3
|
|
130
|
+
|
|
131
|
+
* Fixed `npx start-test-run` to launch commands
|
|
132
|
+
|
|
133
|
+
# 0.6.2
|
|
134
|
+
|
|
135
|
+
* Added `--env-file` option to load env variables from env file
|
|
136
|
+
|
|
137
|
+
# 0.6.1
|
|
138
|
+
|
|
139
|
+
* Fixed creating RunGroup with JUnit reporter
|
|
140
|
+
|
|
141
|
+
# 0.6.0
|
|
142
|
+
|
|
143
|
+
* JUnit reporter support
|
|
144
|
+
|
|
145
|
+
# 0.5.10
|
|
146
|
+
|
|
147
|
+
* Fixed reporting Scenario Outline in Cypress-Cucumber
|
|
148
|
+
* Fixed error reports for Cypress when running in Chrome
|
|
149
|
+
|
|
150
|
+
# 0.5.9
|
|
151
|
+
|
|
152
|
+
* Added environment on Cypress report
|
|
153
|
+
|
|
154
|
+
# 0.5.8
|
|
155
|
+
|
|
156
|
+
* Fixed Cypress.io reporting
|
|
157
|
+
|
|
158
|
+
# 0.5.7
|
|
159
|
+
|
|
160
|
+
* Fixed webdriverio artifacts
|
|
161
|
+
|
|
162
|
+
# 0.5.6
|
|
163
|
+
|
|
164
|
+
* Unmark failed CodeceptJS tests as skipped
|
|
165
|
+
|
|
166
|
+
# 0.5.5
|
|
167
|
+
|
|
168
|
+
* Fixed `BeforeSuite` failures in CodeceptJS
|
|
169
|
+
|
|
170
|
+
# 0.5.4
|
|
171
|
+
|
|
172
|
+
Added `TESTOMATIO_CREATE=1` option to create unmatched tests on report
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
TESTOMATIO_CREATE=1 TESTOMATIO=apiKey npx codeceptjs run
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
# 0.5.3
|
|
179
|
+
|
|
180
|
+
* Fixed parsing suites
|
|
181
|
+
|
|
182
|
+
# 0.5.2
|
|
183
|
+
|
|
184
|
+
* Fixed multiple upload of artifacts in Cypress.io
|
|
185
|
+
|
|
186
|
+
# 0.5.1
|
|
187
|
+
|
|
188
|
+
* Fixed Cypress.io to report tests inside nested suites
|
|
189
|
+
|
|
190
|
+
# 0.5.0
|
|
191
|
+
|
|
192
|
+
* Added Cypress.io plugin
|
|
193
|
+
* Added artifacts upload to webdriverio
|
|
194
|
+
|
|
195
|
+
# 0.4.6
|
|
196
|
+
|
|
197
|
+
- Fixed CodeceptJS reporter to report tests failed in hooks
|
|
198
|
+
|
|
199
|
+
# 0.4.5
|
|
200
|
+
|
|
201
|
+
- Fixed "Total XX artifacts publicly uploaded to S3 bucket" when no S3 bucket is configured
|
|
202
|
+
- Improved S3 connection error messages
|
|
203
|
+
|
|
204
|
+
# 0.4.4
|
|
205
|
+
|
|
206
|
+
- Fixed returning 0 exit code when a process fails when running tests in parallel via `start-test-run`. Previously was using the last exit code returned by a process. Currently prefers the highest exit code that was returned by a process.
|
|
207
|
+
|
|
208
|
+
# 0.4.3
|
|
209
|
+
|
|
210
|
+
- Added `TESTOMATIO_DISABLE_ARTIFACTS` env variable to disable publishing artifacts.
|
|
211
|
+
|
|
212
|
+
# 0.4.2
|
|
213
|
+
|
|
214
|
+
- print version of reporter
|
|
215
|
+
- print number of uploaded artifacts
|
|
216
|
+
- print access mode for uploaded artifacts
|
|
217
|
+
|
|
218
|
+
# 0.4.1
|
|
219
|
+
|
|
220
|
+
Added `global.testomatioArtifacts = []` array which can be used to add arbitrary artifacts to a report.
|
|
221
|
+
|
|
222
|
+
```js
|
|
223
|
+
// inside a running test:
|
|
224
|
+
global.testomatioArtifacts.push('file/to/upload.png');
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
# 0.4.0
|
|
228
|
+
|
|
229
|
+
- Playwright: Introduced playwright/test support with screenshots and video artifacts
|
|
230
|
+
|
|
231
|
+
> Known issues: reporting using projects configured in Playwright does not work yet
|
|
232
|
+
|
|
233
|
+
- CodeceptJS: added video uploads
|
|
234
|
+
|
|
235
|
+
# 0.3.16
|
|
236
|
+
|
|
237
|
+
- CodeceptJS: fixed reporting tests with empty steps (on retry)
|
|
238
|
+
|
|
239
|
+
# 0.3.15
|
|
240
|
+
|
|
241
|
+
- Finish Run via API:
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
TESTOMATIO={apiKey} TESTOMATIO_RUN={runId} npx @testomatio/reporter@latest --finish
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
# 0.3.14
|
|
248
|
+
|
|
249
|
+
- Create an empty Run via API:
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
TESTOMATIO={apiKey} npx @testomatio/reporter@latest --launch
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
# 0.3.13
|
|
256
|
+
|
|
257
|
+
- Checking for a valid report URL
|
|
258
|
+
- Sending unlimited data on test report
|
|
259
|
+
|
|
260
|
+
# 0.3.12
|
|
261
|
+
|
|
262
|
+
- Fixed submitting arbitrary data on a test run
|
|
263
|
+
- Jest: fixed sending errors with stack traces
|
|
264
|
+
- Cypress: fixed sending reports
|
|
265
|
+
|
|
266
|
+
# 0.3.11
|
|
267
|
+
|
|
268
|
+
- Fixed circular JSON reference when submitting data to Testomatio
|
|
269
|
+
|
|
270
|
+
# 0.3.10
|
|
271
|
+
|
|
272
|
+
- Minor fixes
|
|
273
|
+
|
|
274
|
+
# 0.3.9
|
|
275
|
+
|
|
276
|
+
- Making all reporters to run without API key
|
|
277
|
+
|
|
278
|
+
# 0.3.8
|
|
279
|
+
|
|
280
|
+
- Fixed `npx start-test-run` to work with empty API keys
|
|
281
|
+
|
|
282
|
+
# 0.3.7
|
|
283
|
+
|
|
284
|
+
- Fixed release
|
|
285
|
+
|
|
286
|
+
# 0.3.6
|
|
287
|
+
|
|
288
|
+
- Update title and rungroup on start for scheduled runs.
|
|
289
|
+
|
|
290
|
+
# 0.3.5
|
|
291
|
+
|
|
292
|
+
- Added `TESTOMATIO_RUN` environment variable to pass id of a specific run to report
|
|
293
|
+
|
|
294
|
+
# 0.3.4
|
|
295
|
+
|
|
296
|
+
- Minor fixes
|
|
297
|
+
|
|
298
|
+
# 0.3.3
|
|
299
|
+
|
|
300
|
+
- [CodeceptJS] Fixed stack trace reporting
|
|
301
|
+
- [CodeceptJS] Fixed displaying of nested steps
|
|
302
|
+
- [CodeceptJS][mocha] Added assertion diff to report
|
|
303
|
+
|
|
304
|
+
# 0.3.2
|
|
305
|
+
|
|
306
|
+
- Fixed error message for S3 uploading
|
|
307
|
+
|
|
308
|
+
# 0.3.1
|
|
309
|
+
|
|
310
|
+
- [CodeceptJS] Better formatter for nested structures and BDD tests
|
|
311
|
+
|
|
312
|
+
# 0.3.0
|
|
313
|
+
|
|
314
|
+
- Added `TESTOMATIO_TITLE` env variable to set a name for Run
|
|
315
|
+
- Added `TESTOMATIO_RUNGROUP_TITLE` env variable to attach Run to RunGroup
|
|
316
|
+
- Added `TESTOMATIO_ENV` env variable to attach additional env values to report
|
|
317
|
+
- [CodeceptJS] **CodeceptJS v3 support**
|
|
318
|
+
- [CodeceptJS] Dropped support for CodeceptJS 2
|
|
319
|
+
- [CodeceptJS] Added support for before hooks
|
|
320
|
+
- [CodeceptJS] Log of steps
|
|
321
|
+
- [CodeceptJS] Upload screenshots of failed tests to S3
|
|
322
|
+
- [CodeceptJS] Updated to use with parallel execution
|
package/lib/bin/reportXml.js
CHANGED
package/lib/util.js
CHANGED
|
@@ -55,11 +55,21 @@ const isValidUrl = s => {
|
|
|
55
55
|
}
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
+
const fileMatchRegex = /file:(\/\/?[^:\s]+?\.(png|avi|webm|jpg|html|txt))/ig;
|
|
59
|
+
|
|
58
60
|
const fetchFilesFromStackTrace = (stack = '') => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
|
|
62
|
+
const files = Array.from(stack.matchAll(fileMatchRegex))
|
|
63
|
+
.map(f => f[1].trim())
|
|
64
|
+
.map(f => f.startsWith('//') ? f.substring(1) : f )
|
|
65
|
+
|
|
66
|
+
debug('Found files in stack trace: ', files);
|
|
67
|
+
|
|
68
|
+
return files.filter(f => {
|
|
69
|
+
const isFile = fs.existsSync(f);
|
|
70
|
+
if (!isFile) debug('File %s could not be found and uploaded as artifact', f);
|
|
71
|
+
return isFile;
|
|
72
|
+
});
|
|
63
73
|
};
|
|
64
74
|
|
|
65
75
|
const fetchSourceCodeFromStackTrace = (stack = '') => {
|
|
@@ -96,6 +106,29 @@ const fetchSourceCodeFromStackTrace = (stack = '') => {
|
|
|
96
106
|
.join('\n');
|
|
97
107
|
};
|
|
98
108
|
|
|
109
|
+
const TEST_ID_REGEX = /@T([\w\d]{8})/;
|
|
110
|
+
|
|
111
|
+
const fetchIdFromCode = (code, opts = {}) => {
|
|
112
|
+
const comments = code.split('\n').map(l => l.trim()).filter(l => {
|
|
113
|
+
switch (opts.lang) {
|
|
114
|
+
case 'ruby':
|
|
115
|
+
case 'python':
|
|
116
|
+
return l.startsWith('# ');
|
|
117
|
+
default:
|
|
118
|
+
return l.startsWith('// ');
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
return comments.find(c => c.match(TEST_ID_REGEX))?.match(TEST_ID_REGEX)?.[1];
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
const fetchIdFromOutput = (output) => {
|
|
127
|
+
const lines = output.split('\n').map(l => l.trim()).filter(l => l.startsWith('tid://'));
|
|
128
|
+
|
|
129
|
+
return lines.find(c => c.match(TEST_ID_REGEX))?.match(TEST_ID_REGEX)?.[1];
|
|
130
|
+
}
|
|
131
|
+
|
|
99
132
|
const fetchSourceCode = (contents, opts = {}) => {
|
|
100
133
|
if (!opts.title && !opts.line) return '';
|
|
101
134
|
|
|
@@ -252,6 +285,8 @@ module.exports = {
|
|
|
252
285
|
isSameTest,
|
|
253
286
|
fetchSourceCode,
|
|
254
287
|
fetchSourceCodeFromStackTrace,
|
|
288
|
+
fetchIdFromCode,
|
|
289
|
+
fetchIdFromOutput,
|
|
255
290
|
fetchFilesFromStackTrace,
|
|
256
291
|
fileSystem,
|
|
257
292
|
getCurrentDateTime,
|
package/lib/xmlReader.js
CHANGED
|
@@ -4,7 +4,12 @@ const chalk = require('chalk');
|
|
|
4
4
|
const fs = require("fs");
|
|
5
5
|
const { XMLParser } = require("fast-xml-parser");
|
|
6
6
|
const { APP_PREFIX, STATUS } = require('./constants');
|
|
7
|
-
const { fetchFilesFromStackTrace,
|
|
7
|
+
const { fetchFilesFromStackTrace,
|
|
8
|
+
fetchIdFromOutput,
|
|
9
|
+
fetchSourceCode,
|
|
10
|
+
fetchSourceCodeFromStackTrace,
|
|
11
|
+
fetchIdFromCode
|
|
12
|
+
} = require('./util');
|
|
8
13
|
const upload = require('./fileUploader');
|
|
9
14
|
const pipesFactory = require('./pipe');
|
|
10
15
|
const adapterFactory = require('./junit-adapter');
|
|
@@ -25,7 +30,7 @@ const options = {
|
|
|
25
30
|
const reduceOptions = {};
|
|
26
31
|
|
|
27
32
|
class XmlReader {
|
|
28
|
-
|
|
33
|
+
|
|
29
34
|
constructor(opts = {}) {
|
|
30
35
|
this.requestParams = {
|
|
31
36
|
apiKey: opts.apiKey || TESTOMATIO,
|
|
@@ -39,8 +44,8 @@ class XmlReader {
|
|
|
39
44
|
if (!this.adapter) throw new Error('XML adapter for this format not found');
|
|
40
45
|
|
|
41
46
|
this.opts = opts || {};
|
|
42
|
-
|
|
43
|
-
this.pipes = pipesFactory(opts, store);
|
|
47
|
+
this.store = {}
|
|
48
|
+
this.pipes = pipesFactory(opts, this.store);
|
|
44
49
|
|
|
45
50
|
this.parser = new XMLParser(options);
|
|
46
51
|
this.tests = []
|
|
@@ -49,7 +54,7 @@ class XmlReader {
|
|
|
49
54
|
this.filesToUpload = {}
|
|
50
55
|
|
|
51
56
|
this.version = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json')).toString()).version;
|
|
52
|
-
console.log(APP_PREFIX, `Testomatio Reporter v${this.version}`);
|
|
57
|
+
console.log(APP_PREFIX, `Testomatio Reporter v${this.version}`);
|
|
53
58
|
}
|
|
54
59
|
|
|
55
60
|
connectAdapter() {
|
|
@@ -61,21 +66,21 @@ class XmlReader {
|
|
|
61
66
|
return this.adapter;
|
|
62
67
|
}
|
|
63
68
|
|
|
64
|
-
parse(fileName) {
|
|
69
|
+
parse(fileName) {
|
|
65
70
|
const xmlData = fs.readFileSync(path.resolve(fileName));
|
|
66
71
|
const jsonResult = this.parser.parse(xmlData);
|
|
67
72
|
let jsonSuite;
|
|
68
|
-
|
|
73
|
+
|
|
69
74
|
if (jsonResult.testsuites) {
|
|
70
75
|
jsonSuite = jsonResult.testsuites;
|
|
71
76
|
} else if (jsonResult.testsuite) {
|
|
72
77
|
jsonSuite = jsonResult;
|
|
73
78
|
} else if (jsonResult.TestRun) {
|
|
74
|
-
return this.processTRX(jsonResult);
|
|
79
|
+
return this.processTRX(jsonResult);
|
|
75
80
|
} else if (jsonResult['test-run']) {
|
|
76
81
|
return this.processNUnit(jsonResult['test-run']);
|
|
77
82
|
} else if (jsonResult.assemblies) {
|
|
78
|
-
return this.processXUnit(jsonResult.assemblies);
|
|
83
|
+
return this.processXUnit(jsonResult.assemblies);
|
|
79
84
|
} else {
|
|
80
85
|
console.log(jsonResult)
|
|
81
86
|
throw new Error("Format can't be parsed")
|
|
@@ -89,9 +94,9 @@ class XmlReader {
|
|
|
89
94
|
|
|
90
95
|
reduceOptions.preferClassname = this.stats.language === 'python';
|
|
91
96
|
const resultTests = processTestSuite(testsuite);
|
|
92
|
-
|
|
97
|
+
|
|
93
98
|
const hasFailures = resultTests.filter(t => t.status === 'failed').length > 0;
|
|
94
|
-
const status = (
|
|
99
|
+
const status = (failures > 0 || errors > 0 || hasFailures) ? 'failed' : 'passed';
|
|
95
100
|
|
|
96
101
|
this.tests = this.tests.concat(resultTests);
|
|
97
102
|
|
|
@@ -124,7 +129,7 @@ class XmlReader {
|
|
|
124
129
|
skipped_count: parseInt(inconclusive + skipped, 10),
|
|
125
130
|
tests: resultTests,
|
|
126
131
|
};
|
|
127
|
-
}
|
|
132
|
+
}
|
|
128
133
|
|
|
129
134
|
processTRX(jsonSuite) {
|
|
130
135
|
let defs = jsonSuite?.TestRun?.TestDefinitions?.UnitTest;
|
|
@@ -133,10 +138,10 @@ class XmlReader {
|
|
|
133
138
|
const tests = defs.map(td => {
|
|
134
139
|
const title = td.name.replace(/\(.*?\)/, '').trim();
|
|
135
140
|
let example = td.name.match(/\((.*?)\)/);
|
|
136
|
-
if (example) example = { ...example[1].split(',')};
|
|
141
|
+
if (example) example = { ...example[1].split(',') };
|
|
137
142
|
const suite = td.TestMethod.className.split(', ')[0].split('.');
|
|
138
143
|
const suite_title = suite.pop();
|
|
139
|
-
return {
|
|
144
|
+
return {
|
|
140
145
|
title,
|
|
141
146
|
example,
|
|
142
147
|
file: suite.join('/'),
|
|
@@ -149,18 +154,18 @@ class XmlReader {
|
|
|
149
154
|
let result = jsonSuite?.TestRun?.Results?.UnitTestResult;
|
|
150
155
|
if (!Array.isArray(result)) result = [result].filter(d => !!d);
|
|
151
156
|
|
|
152
|
-
const results = result.map(td => ({
|
|
157
|
+
const results = result.map(td => ({
|
|
153
158
|
id: td.executionId,
|
|
154
159
|
// seconds are used in junit reports, but ms are used by testomatio
|
|
155
160
|
run_time: parseFloat(td.duration) * 1000,
|
|
156
|
-
status: td.outcome,
|
|
161
|
+
status: td.outcome,
|
|
157
162
|
stack: td.Output.StdOut,
|
|
158
163
|
files: td?.ResultFiles?.ResultFile?.map(rf => rf.path)
|
|
159
164
|
}));
|
|
160
165
|
|
|
161
|
-
|
|
166
|
+
|
|
162
167
|
results.forEach(r => {
|
|
163
|
-
const test = tests.find(t => t.id === r.id) || {
|
|
168
|
+
const test = tests.find(t => t.id === r.id) || {};
|
|
164
169
|
r.suite_title = test.suite_title;
|
|
165
170
|
r.title = test.title?.trim();
|
|
166
171
|
if (test.code) r.code = test.code;
|
|
@@ -175,7 +180,7 @@ class XmlReader {
|
|
|
175
180
|
});
|
|
176
181
|
|
|
177
182
|
debug(results);
|
|
178
|
-
|
|
183
|
+
|
|
179
184
|
const counters = jsonSuite?.TestRun?.ResultSummary?.Counters || {};
|
|
180
185
|
|
|
181
186
|
const failed_count = parseInt(counters.failed, 10) + parseInt(counters.error, 10);
|
|
@@ -193,7 +198,7 @@ class XmlReader {
|
|
|
193
198
|
skipped_count: parseInt(counters.notExecuted, 10),
|
|
194
199
|
failed_count,
|
|
195
200
|
tests: results,
|
|
196
|
-
};
|
|
201
|
+
};
|
|
197
202
|
}
|
|
198
203
|
|
|
199
204
|
processXUnit(assemblies) {
|
|
@@ -227,7 +232,7 @@ class XmlReader {
|
|
|
227
232
|
let status = STATUS.PASSED;
|
|
228
233
|
if (result === 'Pass') status = STATUS.PASSED;
|
|
229
234
|
if (result === 'Fail') status = STATUS.FAILED;
|
|
230
|
-
if (result === 'Skip') status = STATUS.SKIPPED;
|
|
235
|
+
if (result === 'Skip') status = STATUS.SKIPPED;
|
|
231
236
|
|
|
232
237
|
const pathParts = type.split('.');
|
|
233
238
|
const suite_title = pathParts[pathParts.length - 1];
|
|
@@ -300,12 +305,19 @@ class XmlReader {
|
|
|
300
305
|
if (file.endsWith('.py')) this.stats.language = 'python';
|
|
301
306
|
if (file.endsWith('.java')) this.stats.language = 'java';
|
|
302
307
|
if (file.endsWith('.rb')) this.stats.language = 'ruby';
|
|
303
|
-
if (file.endsWith('.js')) this.stats.language
|
|
308
|
+
if (file.endsWith('.js')) this.stats.language = 'js';
|
|
304
309
|
if (file.endsWith('.ts')) this.stats.language = 'ts';
|
|
305
310
|
}
|
|
306
311
|
|
|
312
|
+
if (!fs.existsSync(file)) {
|
|
313
|
+
debug('Failed to open file with the source code', file)
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
307
316
|
const contents = fs.readFileSync(file).toString();
|
|
308
317
|
t.code = fetchSourceCode(contents, { ...t, lang: this.stats.language })
|
|
318
|
+
if (t.code) debug('Fetched code for test %s', t.title);
|
|
319
|
+
t.test_id = fetchIdFromCode(t.code, { lang: this.stats.language })
|
|
320
|
+
if (t.test_id) debug('Fetched test id %s for test %s', t.test_id, t.title);
|
|
309
321
|
} catch (err) {
|
|
310
322
|
debug(err)
|
|
311
323
|
}
|
|
@@ -349,8 +361,12 @@ class XmlReader {
|
|
|
349
361
|
let files = [];
|
|
350
362
|
if (test.files?.length) files = test.files.map(f => path.join(process.cwd(), f))
|
|
351
363
|
files = [...files, ...fetchFilesFromStackTrace(test.stack)];
|
|
352
|
-
|
|
353
|
-
|
|
364
|
+
|
|
365
|
+
if (!files.length) continue;
|
|
366
|
+
|
|
367
|
+
const runId = this.runId || this.store.runId || Date.now().toString();
|
|
368
|
+
test.artifacts = await Promise.all(files.map(f => upload.uploadFileByPath(f, runId)));
|
|
369
|
+
console.log(APP_PREFIX, `🗄️ Uploaded ${chalk.bold(`${files.length} artifacts`)} for test ${test.title}`);
|
|
354
370
|
}
|
|
355
371
|
}
|
|
356
372
|
|
|
@@ -360,7 +376,7 @@ class XmlReader {
|
|
|
360
376
|
title: this.requestParams.title,
|
|
361
377
|
env: this.requestParams.env,
|
|
362
378
|
group_title: this.requestParams.group_title,
|
|
363
|
-
};
|
|
379
|
+
};
|
|
364
380
|
|
|
365
381
|
debug("Run", runParams);
|
|
366
382
|
|
|
@@ -378,9 +394,9 @@ class XmlReader {
|
|
|
378
394
|
debug(
|
|
379
395
|
'Uploading data',
|
|
380
396
|
{
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
397
|
+
...this.stats,
|
|
398
|
+
tests: this.tests,
|
|
399
|
+
})
|
|
384
400
|
|
|
385
401
|
const dataString = {
|
|
386
402
|
...this.stats,
|
|
@@ -402,6 +418,8 @@ function reduceTestCases(prev, item) {
|
|
|
402
418
|
if (!Array.isArray(testCases)) {
|
|
403
419
|
testCases = [testCases]
|
|
404
420
|
}
|
|
421
|
+
const suiteOutput = item['system-out'] || item.output || item.log || '';
|
|
422
|
+
const suiteErr = item['system-err'] || item.output || item.log || '';
|
|
405
423
|
testCases.filter(t => !!t).forEach(testCaseItem => {
|
|
406
424
|
const file = testCaseItem.file || item.filepath || '';
|
|
407
425
|
|
|
@@ -417,8 +435,9 @@ function reduceTestCases(prev, item) {
|
|
|
417
435
|
if (testCaseItem.error && testCaseItem.error['#text']) stack = testCaseItem.error['#text'];
|
|
418
436
|
if (!message) message = stack.trim().split('\n')[0];
|
|
419
437
|
|
|
420
|
-
//
|
|
421
|
-
stack = `${testCaseItem['system-out'] || testCaseItem.output || testCaseItem.log || ''}\n\n${stack}`.trim()
|
|
438
|
+
// eslint-disable-next-line
|
|
439
|
+
stack = `${testCaseItem['system-out'] || testCaseItem.output || testCaseItem.log || ''}\n\n${stack}\n\n${suiteOutput}\n\n${suiteErr}`.trim()
|
|
440
|
+
const testId = fetchIdFromOutput(stack);
|
|
422
441
|
|
|
423
442
|
let status = STATUS.PASSED.toString();
|
|
424
443
|
if ('failure' in testCaseItem || 'error' in testCaseItem) status = STATUS.FAILED;
|
|
@@ -428,6 +447,7 @@ function reduceTestCases(prev, item) {
|
|
|
428
447
|
create: true,
|
|
429
448
|
file,
|
|
430
449
|
stack,
|
|
450
|
+
test_id: testId,
|
|
431
451
|
message,
|
|
432
452
|
line: testCaseItem.lineno,
|
|
433
453
|
// seconds are used in junit reports, but ms are used by testomatio
|