@testomatio/reporter 2.3.5-beta-6-xml-import → 2.3.5
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/junit-adapter/csharp.d.ts +1 -0
- package/lib/junit-adapter/csharp.js +7 -36
- package/lib/pipe/debug.js +1 -1
- package/lib/pipe/testomatio.js +14 -18
- package/lib/utils/utils.js +4 -33
- package/lib/xmlReader.d.ts +0 -9
- package/lib/xmlReader.js +11 -357
- package/package.json +1 -1
- package/src/junit-adapter/csharp.js +6 -40
- package/src/pipe/debug.js +3 -2
- package/src/pipe/testomatio.js +80 -74
- package/src/utils/utils.js +3 -33
- package/src/xmlReader.js +10 -409
package/src/pipe/testomatio.js
CHANGED
|
@@ -20,7 +20,7 @@ if (process.env.TESTOMATIO_RUN) process.env.runId = process.env.TESTOMATIO_RUN;
|
|
|
20
20
|
class TestomatioPipe {
|
|
21
21
|
constructor(params, store) {
|
|
22
22
|
this.batch = {
|
|
23
|
-
isEnabled: params?.isBatchEnabled ??
|
|
23
|
+
isEnabled: params?.isBatchEnabled ?? !process.env.TESTOMATIO_DISABLE_BATCH_UPLOAD ?? true,
|
|
24
24
|
intervalFunction: null, // will be created in createRun by setInterval function
|
|
25
25
|
intervalTime: 5000, // how often tests are sent
|
|
26
26
|
tests: [], // array of tests in batch
|
|
@@ -60,8 +60,8 @@ class TestomatioPipe {
|
|
|
60
60
|
retryConfig: {
|
|
61
61
|
retry: REPORTER_REQUEST_RETRIES.retriesPerRequest,
|
|
62
62
|
retryDelay: REPORTER_REQUEST_RETRIES.retryTimeout,
|
|
63
|
-
httpMethodsToRetry: ['GET',
|
|
64
|
-
shouldRetry: error => {
|
|
63
|
+
httpMethodsToRetry: ['GET','PUT','HEAD','OPTIONS','DELETE','POST'],
|
|
64
|
+
shouldRetry: (error) => {
|
|
65
65
|
if (!error.response) return false;
|
|
66
66
|
switch (error.response?.status) {
|
|
67
67
|
case 400: // Bad request (probably wrong API key)
|
|
@@ -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
|
|
|
80
80
|
this.isEnabled = true;
|
|
@@ -104,6 +104,7 @@ class TestomatioPipe {
|
|
|
104
104
|
// add test ID + run ID
|
|
105
105
|
if (data.rid) data.rid = `${this.runId}-${data.rid}`;
|
|
106
106
|
|
|
107
|
+
|
|
107
108
|
if (!process.env.TESTOMATIO_STACK_PASSED && data.status === STATUS.PASSED) {
|
|
108
109
|
data.stack = null;
|
|
109
110
|
}
|
|
@@ -119,6 +120,7 @@ class TestomatioPipe {
|
|
|
119
120
|
return data;
|
|
120
121
|
}
|
|
121
122
|
|
|
123
|
+
|
|
122
124
|
/**
|
|
123
125
|
* Asynchronously prepares and retrieves the Testomat.io test grepList based on the provided options.
|
|
124
126
|
* @param {Object} opts - The options for preparing the test grepList.
|
|
@@ -213,7 +215,7 @@ class TestomatioPipe {
|
|
|
213
215
|
method: 'PUT',
|
|
214
216
|
url: `/api/reporter/${this.runId}`,
|
|
215
217
|
data: runParams,
|
|
216
|
-
responseType: 'json'
|
|
218
|
+
responseType: 'json'
|
|
217
219
|
});
|
|
218
220
|
if (resp.data.artifacts) setS3Credentials(resp.data.artifacts);
|
|
219
221
|
return;
|
|
@@ -226,7 +228,7 @@ class TestomatioPipe {
|
|
|
226
228
|
url: '/api/reporter',
|
|
227
229
|
data: runParams,
|
|
228
230
|
maxContentLength: Infinity,
|
|
229
|
-
responseType: 'json'
|
|
231
|
+
responseType: 'json'
|
|
230
232
|
});
|
|
231
233
|
|
|
232
234
|
this.runId = resp.data.uid;
|
|
@@ -285,44 +287,44 @@ class TestomatioPipe {
|
|
|
285
287
|
|
|
286
288
|
debug('Adding test', json);
|
|
287
289
|
|
|
288
|
-
return this.client
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
.
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (err.response.status >= 400) {
|
|
303
|
-
const responseData = err.response.data || { message: '' };
|
|
304
|
-
console.log(
|
|
305
|
-
APP_PREFIX,
|
|
306
|
-
pc.yellow(`Warning: ${responseData.message} (${err.response.status})`),
|
|
307
|
-
pc.gray(data?.title || ''),
|
|
308
|
-
);
|
|
309
|
-
if (err.response?.data?.message?.includes('could not be matched')) {
|
|
310
|
-
this.hasUnmatchedTests = true;
|
|
311
|
-
}
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
290
|
+
return this.client.request({
|
|
291
|
+
method: 'POST',
|
|
292
|
+
url: `/api/reporter/${this.runId}/testrun`,
|
|
293
|
+
data: json,
|
|
294
|
+
headers: {
|
|
295
|
+
'Content-Type': 'application/json',
|
|
296
|
+
},
|
|
297
|
+
maxContentLength: Infinity
|
|
298
|
+
}).catch(err => {
|
|
299
|
+
this.requestFailures++;
|
|
300
|
+
this.notReportedTestsCount++;
|
|
301
|
+
if (err.response) {
|
|
302
|
+
if (err.response.status >= 400) {
|
|
303
|
+
const responseData = err.response.data || { message: '' };
|
|
314
304
|
console.log(
|
|
315
305
|
APP_PREFIX,
|
|
316
|
-
pc.yellow(`Warning: ${
|
|
317
|
-
|
|
306
|
+
pc.yellow(`Warning: ${responseData.message} (${err.response.status})`),
|
|
307
|
+
pc.gray(data?.title || ''),
|
|
318
308
|
);
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
309
|
+
if (err.response?.data?.message?.includes('could not be matched')) {
|
|
310
|
+
this.hasUnmatchedTests = true;
|
|
311
|
+
}
|
|
312
|
+
return;
|
|
322
313
|
}
|
|
323
|
-
|
|
314
|
+
console.log(
|
|
315
|
+
APP_PREFIX,
|
|
316
|
+
pc.yellow(`Warning: ${data?.title || ''} (${err.response?.status})`),
|
|
317
|
+
`Report couldn't be processed: ${err?.response?.data?.message}`,
|
|
318
|
+
);
|
|
319
|
+
printCreateIssue(err);
|
|
320
|
+
} else {
|
|
321
|
+
console.log(APP_PREFIX, pc.blue(data?.title || ''), "Report couldn't be processed", err);
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
324
|
};
|
|
325
325
|
|
|
326
|
+
|
|
327
|
+
|
|
326
328
|
/**
|
|
327
329
|
* Uploads tests as a batch (multiple tests at once). Intended to be used with a setInterval
|
|
328
330
|
*/
|
|
@@ -347,42 +349,43 @@ class TestomatioPipe {
|
|
|
347
349
|
const testsToSend = this.batch.tests.splice(0);
|
|
348
350
|
debug('📨 Batch upload', testsToSend.length, 'tests');
|
|
349
351
|
|
|
350
|
-
return this.client
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
if (err.response.status >= 400) {
|
|
369
|
-
const responseData = err.response.data || { message: '' };
|
|
370
|
-
console.log(APP_PREFIX, pc.yellow(`Warning: ${responseData.message} (${err.response.status})`));
|
|
371
|
-
if (err.response?.data?.message?.includes('could not be matched')) {
|
|
372
|
-
this.hasUnmatchedTests = true;
|
|
373
|
-
}
|
|
374
|
-
return;
|
|
375
|
-
}
|
|
352
|
+
return this.client.request({
|
|
353
|
+
method: 'POST',
|
|
354
|
+
url: `/api/reporter/${this.runId}/testrun`,
|
|
355
|
+
data: {
|
|
356
|
+
api_key: this.apiKey,
|
|
357
|
+
tests: testsToSend,
|
|
358
|
+
batch_index: this.batch.batchIndex
|
|
359
|
+
},
|
|
360
|
+
headers: {
|
|
361
|
+
'Content-Type': 'application/json',
|
|
362
|
+
},
|
|
363
|
+
maxContentLength: Infinity
|
|
364
|
+
}).catch(err => {
|
|
365
|
+
this.requestFailures++;
|
|
366
|
+
this.notReportedTestsCount += testsToSend.length;
|
|
367
|
+
if (err.response) {
|
|
368
|
+
if (err.response.status >= 400) {
|
|
369
|
+
const responseData = err.response.data || { message: '' };
|
|
376
370
|
console.log(
|
|
377
371
|
APP_PREFIX,
|
|
378
|
-
pc.yellow(`Warning: (${err.response
|
|
379
|
-
`Report couldn't be processed: ${err?.response?.data?.message}`,
|
|
372
|
+
pc.yellow(`Warning: ${responseData.message} (${err.response.status})`),
|
|
380
373
|
);
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
374
|
+
if (err.response?.data?.message?.includes('could not be matched')) {
|
|
375
|
+
this.hasUnmatchedTests = true;
|
|
376
|
+
}
|
|
377
|
+
return;
|
|
384
378
|
}
|
|
385
|
-
|
|
379
|
+
console.log(
|
|
380
|
+
APP_PREFIX,
|
|
381
|
+
pc.yellow(`Warning: (${err.response?.status})`),
|
|
382
|
+
`Report couldn't be processed: ${err?.response?.data?.message}`,
|
|
383
|
+
);
|
|
384
|
+
printCreateIssue(err);
|
|
385
|
+
} else {
|
|
386
|
+
console.log(APP_PREFIX, "Report couldn't be processed", err);
|
|
387
|
+
}
|
|
388
|
+
});
|
|
386
389
|
};
|
|
387
390
|
|
|
388
391
|
/**
|
|
@@ -405,9 +408,9 @@ class TestomatioPipe {
|
|
|
405
408
|
else this.batch.tests.push(data);
|
|
406
409
|
|
|
407
410
|
// if test is added after run which is already finished
|
|
408
|
-
|
|
411
|
+
if (!this.batch.intervalFunction) uploading = this.#batchUpload();
|
|
409
412
|
|
|
410
|
-
|
|
413
|
+
// return promise to be able to wait for it
|
|
411
414
|
return uploading;
|
|
412
415
|
}
|
|
413
416
|
|
|
@@ -456,7 +459,7 @@ class TestomatioPipe {
|
|
|
456
459
|
status_event,
|
|
457
460
|
detach: params.detach,
|
|
458
461
|
tests: params.tests,
|
|
459
|
-
}
|
|
462
|
+
}
|
|
460
463
|
});
|
|
461
464
|
|
|
462
465
|
console.log(APP_PREFIX, '✅ Testrun finished');
|
|
@@ -524,6 +527,9 @@ function printCreateIssue(err) {
|
|
|
524
527
|
console.log({ body: body?.replace(/"(tstmt_[^"]+)"/g, 'tstmt_*'), url, baseURL, method, time });
|
|
525
528
|
console.log('```');
|
|
526
529
|
});
|
|
530
|
+
|
|
527
531
|
}
|
|
528
532
|
|
|
533
|
+
|
|
534
|
+
|
|
529
535
|
export default TestomatioPipe;
|
package/src/utils/utils.js
CHANGED
|
@@ -139,8 +139,6 @@ export const TEST_ID_REGEX = /@T([\w\d]{8})/;
|
|
|
139
139
|
export const SUITE_ID_REGEX = /@S([\w\d]{8})/;
|
|
140
140
|
|
|
141
141
|
const fetchIdFromCode = (code, opts = {}) => {
|
|
142
|
-
if (!code) return null;
|
|
143
|
-
|
|
144
142
|
const comments = code
|
|
145
143
|
.split('\n')
|
|
146
144
|
.map(l => l.trim())
|
|
@@ -182,32 +180,8 @@ const fetchSourceCode = (contents, opts = {}) => {
|
|
|
182
180
|
if (lineIndex === -1) lineIndex = lines.findIndex(l => l.includes(`public void ${title}`));
|
|
183
181
|
if (lineIndex === -1) lineIndex = lines.findIndex(l => l.includes(`${title}(`));
|
|
184
182
|
} else if (opts.lang === 'csharp') {
|
|
185
|
-
|
|
186
|
-
lineIndex = lines.findIndex(l => l.includes(
|
|
187
|
-
|
|
188
|
-
if (lineIndex === -1) {
|
|
189
|
-
lineIndex = lines.findIndex(l => l.includes(`public async Task ${title}(`));
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (lineIndex === -1) {
|
|
193
|
-
lineIndex = lines.findIndex(l => l.includes(`${title}(`));
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Look for TestCase or Test attributes above the method
|
|
197
|
-
if (lineIndex === -1) {
|
|
198
|
-
const testAttributeIndex = lines.findIndex((l, index) => {
|
|
199
|
-
if (l.includes('[TestCase') || l.includes('[Test')) {
|
|
200
|
-
// Check next few lines for the method
|
|
201
|
-
const nextLines = lines.slice(index, Math.min(lines.length, index + 5));
|
|
202
|
-
const hasMethod = nextLines.some(nextLine => nextLine.includes(`${title}(`));
|
|
203
|
-
return hasMethod;
|
|
204
|
-
}
|
|
205
|
-
return false;
|
|
206
|
-
});
|
|
207
|
-
if (testAttributeIndex !== -1) {
|
|
208
|
-
lineIndex = testAttributeIndex;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
183
|
+
if (lineIndex === -1) lineIndex = lines.findIndex(l => l.includes(`public void ${title}`));
|
|
184
|
+
if (lineIndex === -1) lineIndex = lines.findIndex(l => l.includes(`${title}(`));
|
|
211
185
|
} else {
|
|
212
186
|
lineIndex = lines.findIndex(l => l.includes(title));
|
|
213
187
|
}
|
|
@@ -217,7 +191,7 @@ const fetchSourceCode = (contents, opts = {}) => {
|
|
|
217
191
|
lineIndex -= opts.prepend;
|
|
218
192
|
}
|
|
219
193
|
|
|
220
|
-
if (lineIndex
|
|
194
|
+
if (lineIndex) {
|
|
221
195
|
const result = [];
|
|
222
196
|
for (let i = lineIndex; i < lineIndex + limit; i++) {
|
|
223
197
|
if (lines[i] === undefined) continue;
|
|
@@ -242,10 +216,6 @@ const fetchSourceCode = (contents, opts = {}) => {
|
|
|
242
216
|
if (opts.lang === 'java' && lines[i].trim().match(/^@\w+/)) break;
|
|
243
217
|
if (opts.lang === 'java' && lines[i].includes(' public void ')) break;
|
|
244
218
|
if (opts.lang === 'java' && lines[i].includes(' class ')) break;
|
|
245
|
-
if (opts.lang === 'csharp' && lines[i].trim().match(/^\[Test/)) break;
|
|
246
|
-
if (opts.lang === 'csharp' && lines[i].includes(' public void ')) break;
|
|
247
|
-
if (opts.lang === 'csharp' && lines[i].includes(' public async Task ')) break;
|
|
248
|
-
if (opts.lang === 'csharp' && lines[i].includes(' class ') && lines[i].includes('public')) break;
|
|
249
219
|
}
|
|
250
220
|
result.push(lines[i]);
|
|
251
221
|
}
|