@testomatio/reporter 2.3.7-beta.3-xml-import β 2.3.7-beta.5-stack-artifacts
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 +1 -1
- package/lib/bin/cli.js +1 -1
- package/lib/bin/reportXml.js +2 -5
- package/lib/client.js +3 -7
- package/lib/junit-adapter/csharp.d.ts +1 -0
- package/lib/junit-adapter/csharp.js +7 -40
- package/lib/pipe/debug.js +1 -1
- package/lib/pipe/testomatio.js +14 -18
- package/lib/uploader.js +0 -4
- package/lib/utils/utils.js +11 -90
- package/lib/xmlReader.d.ts +26 -32
- package/lib/xmlReader.js +50 -106
- package/package.json +1 -1
- package/src/bin/cli.js +1 -1
- package/src/bin/reportXml.js +2 -5
- package/src/client.js +4 -7
- package/src/junit-adapter/csharp.js +6 -45
- package/src/pipe/debug.js +3 -2
- package/src/pipe/testomatio.js +80 -74
- package/src/uploader.js +0 -5
- package/src/utils/utils.js +9 -96
- package/src/xmlReader.js +45 -128
- package/lib/junit-adapter/nunit-parser.d.ts +0 -82
- package/lib/junit-adapter/nunit-parser.js +0 -369
- package/src/junit-adapter/nunit-parser.js +0 -404
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 [
|
|
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)_
|
package/lib/bin/cli.js
CHANGED
|
@@ -145,7 +145,7 @@ program
|
|
|
145
145
|
.option('--lang <lang>', 'Language used (python, ruby, java)')
|
|
146
146
|
.option('--timelimit <time>', 'default time limit in seconds to kill a stuck process')
|
|
147
147
|
.action(async (pattern, opts) => {
|
|
148
|
-
if (!pattern.endsWith('.xml')
|
|
148
|
+
if (!pattern.endsWith('.xml')) {
|
|
149
149
|
pattern += '.xml';
|
|
150
150
|
}
|
|
151
151
|
let { javaTests, lang } = opts;
|
package/lib/bin/reportXml.js
CHANGED
|
@@ -25,7 +25,7 @@ program
|
|
|
25
25
|
.option('--timelimit <time>', 'default time limit in seconds to kill a stuck process')
|
|
26
26
|
.option('--env-file <envfile>', 'Load environment variables from env file')
|
|
27
27
|
.action(async (pattern, opts) => {
|
|
28
|
-
if (!pattern.endsWith('.xml')
|
|
28
|
+
if (!pattern.endsWith('.xml')) {
|
|
29
29
|
pattern += '.xml';
|
|
30
30
|
}
|
|
31
31
|
let { javaTests, lang } = opts;
|
|
@@ -37,10 +37,7 @@ program
|
|
|
37
37
|
lang = lang?.toLowerCase();
|
|
38
38
|
if (javaTests === true || (lang === 'java' && !javaTests))
|
|
39
39
|
javaTests = 'src/test/java';
|
|
40
|
-
const runReader = new xmlReader_js_1.default({
|
|
41
|
-
javaTests,
|
|
42
|
-
lang,
|
|
43
|
-
});
|
|
40
|
+
const runReader = new xmlReader_js_1.default({ javaTests, lang });
|
|
44
41
|
const files = glob_1.glob.sync(pattern, { cwd: opts.dir || process.cwd() });
|
|
45
42
|
if (!files.length) {
|
|
46
43
|
console.log(constants_js_1.APP_PREFIX, `Report can't be created. No XML files found π₯`);
|
package/lib/client.js
CHANGED
|
@@ -70,8 +70,8 @@ class Client {
|
|
|
70
70
|
this.pipeStore = {};
|
|
71
71
|
this.runId = '';
|
|
72
72
|
this.queue = Promise.resolve();
|
|
73
|
-
//
|
|
74
|
-
const pathToPackageJSON = path_1.default.join(
|
|
73
|
+
// @ts-ignore this line will be removed in compiled code, because __dirname is defined in commonjs
|
|
74
|
+
const pathToPackageJSON = path_1.default.join(__dirname, '../package.json');
|
|
75
75
|
try {
|
|
76
76
|
this.version = JSON.parse(fs_1.default.readFileSync(pathToPackageJSON).toString()).version;
|
|
77
77
|
console.log(constants_js_1.APP_PREFIX, `Testomatio Reporter v${this.version}`);
|
|
@@ -329,11 +329,7 @@ class Client {
|
|
|
329
329
|
*/
|
|
330
330
|
formatLogs({ error, steps, logs }) {
|
|
331
331
|
error = error?.trim();
|
|
332
|
-
logs = logs
|
|
333
|
-
?.trim()
|
|
334
|
-
.split('\n')
|
|
335
|
-
.map(l => (0, utils_js_1.truncate)(l))
|
|
336
|
-
.join('\n');
|
|
332
|
+
logs = logs?.trim().split('\n').map(l => (0, utils_js_1.truncate)(l)).join('\n');
|
|
337
333
|
if (Array.isArray(steps)) {
|
|
338
334
|
steps = steps
|
|
339
335
|
.map(step => (0, utils_js_1.formatStep)(step))
|
|
@@ -7,57 +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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// Extract parameters as object with numeric keys for API
|
|
15
|
-
const params = exampleMatch[1].split(',').map(param => param.trim());
|
|
16
|
-
t.example = {};
|
|
17
|
-
params.forEach((param, index) => {
|
|
18
|
-
t.example[index] = param;
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
// Remove parameters from title to avoid duplicates in Test Suite
|
|
23
|
-
// The example field will be used for grouping on import
|
|
24
|
-
t.title = t.title.replace(/\(.*?\)/, '').trim();
|
|
10
|
+
const title = t.title.replace(/\(.*?\)/, '').trim();
|
|
11
|
+
const example = t.title.match(/\((.*?)\)/);
|
|
12
|
+
if (example)
|
|
13
|
+
t.example = { ...example[1].split(',') };
|
|
25
14
|
const suite = t.suite_title.split('.');
|
|
26
15
|
t.suite_title = suite.pop();
|
|
27
16
|
t.file = namespaceToFileName(t.file);
|
|
17
|
+
t.title = title.trim();
|
|
28
18
|
return t;
|
|
29
19
|
}
|
|
30
20
|
getFilePath(t) {
|
|
31
|
-
|
|
32
|
-
return null;
|
|
33
|
-
// Normalize path separators for cross-platform compatibility
|
|
34
|
-
let filePath = t.file.replace(/\\/g, '/');
|
|
35
|
-
// If file already has .cs extension, use it directly
|
|
36
|
-
if (filePath.endsWith('.cs')) {
|
|
37
|
-
// Make relative path if it's absolute
|
|
38
|
-
if (path_1.default.isAbsolute(filePath)) {
|
|
39
|
-
// Try to find project-relative path
|
|
40
|
-
const cwd = process.cwd().replace(/\\/g, '/');
|
|
41
|
-
if (filePath.startsWith(cwd)) {
|
|
42
|
-
filePath = path_1.default.relative(cwd, filePath).replace(/\\/g, '/');
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return filePath;
|
|
46
|
-
}
|
|
47
|
-
// Convert namespace path to file path
|
|
48
|
-
const fileName = namespaceToFileName(filePath);
|
|
21
|
+
const fileName = namespaceToFileName(t.file);
|
|
49
22
|
return fileName;
|
|
50
23
|
}
|
|
51
24
|
}
|
|
52
25
|
module.exports = CSharpAdapter;
|
|
53
26
|
function namespaceToFileName(fileName) {
|
|
54
|
-
if (!fileName)
|
|
55
|
-
return '';
|
|
56
|
-
// If already a .cs file path, clean it up
|
|
57
|
-
if (fileName.endsWith('.cs')) {
|
|
58
|
-
return fileName.replace(/\\/g, '/');
|
|
59
|
-
}
|
|
60
27
|
const fileParts = fileName.split('.');
|
|
61
28
|
fileParts[fileParts.length - 1] = fileParts[fileParts.length - 1]?.replace(/\$.*/, '');
|
|
62
|
-
return `${fileParts.join(
|
|
29
|
+
return `${fileParts.join(path_1.default.sep)}.cs`;
|
|
63
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 ??
|
|
21
|
+
isEnabled: this.params.isBatchEnabled ?? !process.env.TESTOMATIO_DISABLE_BATCH_UPLOAD ?? true,
|
|
22
22
|
intervalFunction: null,
|
|
23
23
|
intervalTime: 5000,
|
|
24
24
|
tests: [],
|
package/lib/pipe/testomatio.js
CHANGED
|
@@ -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 ??
|
|
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
|
if (this.runUrl) {
|
|
418
414
|
console.log(constants_js_1.APP_PREFIX, 'π Report Saved. Report URL:', picocolors_1.default.magenta(this.runUrl));
|
package/lib/uploader.js
CHANGED
|
@@ -170,10 +170,6 @@ class S3Uploader {
|
|
|
170
170
|
if (typeof filePath === 'string' && !path_1.default.isAbsolute(filePath)) {
|
|
171
171
|
filePath = path_1.default.join(process.cwd(), filePath);
|
|
172
172
|
}
|
|
173
|
-
// Normalize path separators for cross-platform compatibility
|
|
174
|
-
if (typeof filePath === 'string') {
|
|
175
|
-
filePath = filePath.replace(/\\/g, '/');
|
|
176
|
-
}
|
|
177
173
|
const data = { rid, file: filePath, uploaded };
|
|
178
174
|
const jsonLine = `${JSON.stringify(data)}\n`;
|
|
179
175
|
fs_1.default.appendFileSync(tempFilePath, jsonLine);
|
package/lib/utils/utils.js
CHANGED
|
@@ -122,8 +122,12 @@ const fetchFilesFromStackTrace = (stack = '', checkExists = true) => {
|
|
|
122
122
|
.map(f => f[1].trim())
|
|
123
123
|
.map(f => f.replace(/^\/+/, '/').replace(/^\/([A-Za-z]:)/, '$1')) // Remove extra slashes, handle Windows paths
|
|
124
124
|
.map(f => {
|
|
125
|
-
//
|
|
126
|
-
|
|
125
|
+
// Convert Windows paths to Linux paths for testing purposes
|
|
126
|
+
if (f.match(/^[A-Za-z]:[\\\/]/)) {
|
|
127
|
+
// Convert Windows path to Linux equivalent for test scenarios
|
|
128
|
+
return f.replace(/^[A-Za-z]:[\\\/]/, '/').replace(/\\/g, '/');
|
|
129
|
+
}
|
|
130
|
+
return f;
|
|
127
131
|
});
|
|
128
132
|
debug('Found files in stack trace: ', files);
|
|
129
133
|
return files.filter(f => {
|
|
@@ -170,8 +174,6 @@ exports.fetchSourceCodeFromStackTrace = fetchSourceCodeFromStackTrace;
|
|
|
170
174
|
exports.TEST_ID_REGEX = /@T([\w\d]{8})/;
|
|
171
175
|
exports.SUITE_ID_REGEX = /@S([\w\d]{8})/;
|
|
172
176
|
const fetchIdFromCode = (code, opts = {}) => {
|
|
173
|
-
if (!code)
|
|
174
|
-
return null;
|
|
175
177
|
const comments = code
|
|
176
178
|
.split('\n')
|
|
177
179
|
.map(l => l.trim())
|
|
@@ -214,58 +216,10 @@ const fetchSourceCode = (contents, opts = {}) => {
|
|
|
214
216
|
lineIndex = lines.findIndex(l => l.includes(`${title}(`));
|
|
215
217
|
}
|
|
216
218
|
else if (opts.lang === 'csharp') {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
if (methodLineIndex === -1) {
|
|
223
|
-
methodLineIndex = lines.findIndex(l => l.includes(`${title}(`));
|
|
224
|
-
}
|
|
225
|
-
// If found, scan upwards to find [TestCase], [Test] attributes and XML comments
|
|
226
|
-
if (methodLineIndex !== -1) {
|
|
227
|
-
lineIndex = methodLineIndex;
|
|
228
|
-
// Scan upwards to find the start of attributes and comments
|
|
229
|
-
for (let i = methodLineIndex - 1; i >= 0; i--) {
|
|
230
|
-
const trimmedLine = lines[i].trim();
|
|
231
|
-
// Include [TestCase], [Test], and other attributes
|
|
232
|
-
if (trimmedLine.startsWith('[')) {
|
|
233
|
-
lineIndex = i;
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
// Include XML documentation comments
|
|
237
|
-
if (trimmedLine.startsWith('///')) {
|
|
238
|
-
lineIndex = i;
|
|
239
|
-
continue;
|
|
240
|
-
}
|
|
241
|
-
// Stop at empty lines (with some tolerance)
|
|
242
|
-
if (trimmedLine === '') {
|
|
243
|
-
// Check if next non-empty line is an attribute or comment
|
|
244
|
-
let hasMoreAttributes = false;
|
|
245
|
-
for (let j = i - 1; j >= 0; j--) {
|
|
246
|
-
const nextTrimmed = lines[j].trim();
|
|
247
|
-
if (nextTrimmed === '')
|
|
248
|
-
continue;
|
|
249
|
-
if (nextTrimmed.startsWith('[') || nextTrimmed.startsWith('///')) {
|
|
250
|
-
hasMoreAttributes = true;
|
|
251
|
-
lineIndex = j;
|
|
252
|
-
}
|
|
253
|
-
break;
|
|
254
|
-
}
|
|
255
|
-
if (!hasMoreAttributes)
|
|
256
|
-
break;
|
|
257
|
-
continue;
|
|
258
|
-
}
|
|
259
|
-
// Stop at other method declarations or class-level elements
|
|
260
|
-
if (trimmedLine.includes('public ') ||
|
|
261
|
-
trimmedLine.includes('private ') ||
|
|
262
|
-
trimmedLine.includes('protected ') ||
|
|
263
|
-
trimmedLine.includes('internal ')) {
|
|
264
|
-
if (!trimmedLine.startsWith('['))
|
|
265
|
-
break;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
219
|
+
if (lineIndex === -1)
|
|
220
|
+
lineIndex = lines.findIndex(l => l.includes(`public void ${title}`));
|
|
221
|
+
if (lineIndex === -1)
|
|
222
|
+
lineIndex = lines.findIndex(l => l.includes(`${title}(`));
|
|
269
223
|
}
|
|
270
224
|
else {
|
|
271
225
|
lineIndex = lines.findIndex(l => l.includes(title));
|
|
@@ -274,28 +228,11 @@ const fetchSourceCode = (contents, opts = {}) => {
|
|
|
274
228
|
if (opts.prepend) {
|
|
275
229
|
lineIndex -= opts.prepend;
|
|
276
230
|
}
|
|
277
|
-
if (lineIndex
|
|
231
|
+
if (lineIndex) {
|
|
278
232
|
const result = [];
|
|
279
|
-
let braceDepth = 0; // Track brace depth for C# methods
|
|
280
|
-
let methodStartFound = false; // Flag to indicate we've found the method opening brace
|
|
281
233
|
for (let i = lineIndex; i < lineIndex + limit; i++) {
|
|
282
234
|
if (lines[i] === undefined)
|
|
283
235
|
continue;
|
|
284
|
-
// Track brace depth for C# to stop after method closes
|
|
285
|
-
if (opts.lang === 'csharp') {
|
|
286
|
-
const line = lines[i];
|
|
287
|
-
// Count opening and closing braces
|
|
288
|
-
const openBraces = (line.match(/\{/g) || []).length;
|
|
289
|
-
const closeBraces = (line.match(/\}/g) || []).length;
|
|
290
|
-
if (openBraces > 0)
|
|
291
|
-
methodStartFound = true;
|
|
292
|
-
braceDepth += openBraces - closeBraces;
|
|
293
|
-
// If we've started the method and depth returns to 0, method is complete
|
|
294
|
-
if (methodStartFound && braceDepth === 0 && closeBraces > 0) {
|
|
295
|
-
result.push(lines[i]);
|
|
296
|
-
break;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
236
|
if (i > lineIndex + 2 && !opts.prepend) {
|
|
300
237
|
// annotation
|
|
301
238
|
if (opts.lang === 'php' && lines[i].trim().startsWith('#['))
|
|
@@ -334,22 +271,6 @@ const fetchSourceCode = (contents, opts = {}) => {
|
|
|
334
271
|
break;
|
|
335
272
|
if (opts.lang === 'java' && lines[i].includes(' class '))
|
|
336
273
|
break;
|
|
337
|
-
// For C#, additional checks if brace tracking didn't stop us
|
|
338
|
-
if (opts.lang === 'csharp') {
|
|
339
|
-
const trimmed = lines[i].trim();
|
|
340
|
-
// Stop at attribute that marks beginning of next test
|
|
341
|
-
if (trimmed.match(/^\[(Test|TestCase|Theory|Fact)/))
|
|
342
|
-
break;
|
|
343
|
-
// Stop at XML documentation comments that belong to next method
|
|
344
|
-
if (trimmed.startsWith('///'))
|
|
345
|
-
break;
|
|
346
|
-
// Stop at another method declaration
|
|
347
|
-
if (trimmed.match(/^\s*(public|private|protected|internal)\s+(\w+|async\s+\w+)\s+\w+\s*\(/))
|
|
348
|
-
break;
|
|
349
|
-
// Stop at class declaration
|
|
350
|
-
if (trimmed.includes(' class ') && trimmed.includes('public'))
|
|
351
|
-
break;
|
|
352
|
-
}
|
|
353
274
|
}
|
|
354
275
|
result.push(lines[i]);
|
|
355
276
|
}
|
package/lib/xmlReader.d.ts
CHANGED
|
@@ -19,11 +19,25 @@ declare class XmlReader {
|
|
|
19
19
|
tests: any[];
|
|
20
20
|
stats: {};
|
|
21
21
|
uploader: S3Uploader;
|
|
22
|
-
enhancedNunit: boolean;
|
|
23
|
-
groupParameterized: boolean;
|
|
24
22
|
version: any;
|
|
25
23
|
connectAdapter(): import("./junit-adapter/adapter.js").default;
|
|
26
|
-
parse(fileName: any):
|
|
24
|
+
parse(fileName: any): {
|
|
25
|
+
status: string;
|
|
26
|
+
create_tests: boolean;
|
|
27
|
+
tests_count: number;
|
|
28
|
+
passed_count: number;
|
|
29
|
+
skipped_count: number;
|
|
30
|
+
failed_count: number;
|
|
31
|
+
tests: any;
|
|
32
|
+
} | {
|
|
33
|
+
status: any;
|
|
34
|
+
create_tests: boolean;
|
|
35
|
+
tests_count: number;
|
|
36
|
+
passed_count: number;
|
|
37
|
+
failed_count: number;
|
|
38
|
+
skipped_count: number;
|
|
39
|
+
tests: any[];
|
|
40
|
+
};
|
|
27
41
|
processJUnit(jsonSuite: any): {
|
|
28
42
|
create_tests: boolean;
|
|
29
43
|
duration: number;
|
|
@@ -35,14 +49,15 @@ declare class XmlReader {
|
|
|
35
49
|
tests: any[];
|
|
36
50
|
tests_count: number;
|
|
37
51
|
};
|
|
38
|
-
processNUnit(jsonSuite: any):
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
processNUnit(jsonSuite: any): {
|
|
53
|
+
status: any;
|
|
54
|
+
create_tests: boolean;
|
|
55
|
+
tests_count: number;
|
|
56
|
+
passed_count: number;
|
|
57
|
+
failed_count: number;
|
|
58
|
+
skipped_count: number;
|
|
59
|
+
tests: any[];
|
|
60
|
+
};
|
|
46
61
|
processTRX(jsonSuite: any): {
|
|
47
62
|
status: string;
|
|
48
63
|
create_tests: boolean;
|
|
@@ -52,27 +67,6 @@ declare class XmlReader {
|
|
|
52
67
|
failed_count: number;
|
|
53
68
|
tests: any;
|
|
54
69
|
};
|
|
55
|
-
_parseTRXTestDefinition(td: any): {
|
|
56
|
-
title: any;
|
|
57
|
-
example: any;
|
|
58
|
-
file: string;
|
|
59
|
-
description: any;
|
|
60
|
-
suite_title: any;
|
|
61
|
-
id: any;
|
|
62
|
-
};
|
|
63
|
-
_parseTRXTestResult(td: any, tests: any): {
|
|
64
|
-
suite_title: any;
|
|
65
|
-
title: any;
|
|
66
|
-
file: any;
|
|
67
|
-
description: any;
|
|
68
|
-
code: any;
|
|
69
|
-
run_time: number;
|
|
70
|
-
stack: any;
|
|
71
|
-
files: any;
|
|
72
|
-
create: boolean;
|
|
73
|
-
overwrite: boolean;
|
|
74
|
-
};
|
|
75
|
-
_mapTRXStatus(outcome: any): string;
|
|
76
70
|
processXUnit(assemblies: any): {
|
|
77
71
|
status: string;
|
|
78
72
|
create_tests: boolean;
|