@testomatio/reporter 2.3.7-beta.1-xml-import → 2.3.7-beta.100
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/lib/adapter/codecept.js +22 -2
- package/lib/bin/cli.js +13 -3
- package/lib/bin/reportXml.js +1 -4
- package/lib/bin/startTest.js +3 -3
- package/lib/bin/uploadArtifacts.js +0 -0
- package/lib/client.d.ts +1 -1
- package/lib/client.js +32 -23
- 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.d.ts +2 -1
- package/lib/pipe/testomatio.js +17 -21
- package/lib/reporter.d.ts +19 -9
- package/lib/reporter.js +40 -5
- package/lib/template/testomatio.hbs +1366 -1026
- package/lib/uploader.js +0 -4
- package/lib/utils/utils.d.ts +1 -0
- package/lib/utils/utils.js +23 -35
- package/lib/xmlReader.d.ts +26 -11
- package/lib/xmlReader.js +1 -50
- package/package.json +8 -4
- package/src/adapter/codecept.js +27 -3
- package/src/bin/cli.js +1 -1
- package/src/bin/reportXml.js +1 -1
- package/src/bin/startTest.js +5 -5
- package/src/client.js +55 -27
- package/src/junit-adapter/csharp.js +11 -6
- package/src/junit-adapter/nunit-parser.js +83 -12
- package/src/pipe/debug.js +3 -2
- package/src/pipe/testomatio.js +81 -77
- package/src/reporter.js +7 -4
- package/src/template/testomatio.hbs +1366 -1026
- package/src/utils/utils.js +205 -32
- package/src/xmlReader.js +70 -45
- package/types/types.d.ts +364 -0
- package/types/vitest.types.d.ts +93 -0
- package/lib/junit-adapter/nunit-parser.d.ts +0 -82
- package/lib/junit-adapter/nunit-parser.js +0 -357
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import createDebugMessages from 'debug';
|
|
2
2
|
import { STATUS } from '../constants.js';
|
|
3
|
+
import { fetchFilesFromStackTrace } from '../utils/utils.js';
|
|
3
4
|
|
|
4
5
|
const debug = createDebugMessages('@testomatio/reporter:nunit-parser');
|
|
5
6
|
|
|
@@ -85,7 +86,8 @@ export class NUnitXmlParser {
|
|
|
85
86
|
case 'TestSuite':
|
|
86
87
|
// Namespace/grouping level - add to path but don't create test
|
|
87
88
|
debug(`Processing TestSuite level - adding '${suiteName}' to path`);
|
|
88
|
-
|
|
89
|
+
// Avoid adding duplicate suite names to the path
|
|
90
|
+
const newPath = parentPath[parentPath.length - 1] === suiteName ? [...parentPath] : [...parentPath, suiteName];
|
|
89
91
|
this.processChildren(testSuite, newPath);
|
|
90
92
|
break;
|
|
91
93
|
|
|
@@ -96,6 +98,13 @@ export class NUnitXmlParser {
|
|
|
96
98
|
this.processChildren(testSuite, testFixturePath);
|
|
97
99
|
break;
|
|
98
100
|
|
|
101
|
+
case 'ParameterizedMethod':
|
|
102
|
+
// Parameterized method level - process test cases directly
|
|
103
|
+
debug(`Processing ParameterizedMethod level - method '${suiteName}'`);
|
|
104
|
+
// Don't add to path, just process children directly
|
|
105
|
+
this.processChildren(testSuite, parentPath);
|
|
106
|
+
break;
|
|
107
|
+
|
|
99
108
|
default:
|
|
100
109
|
debug(`Unknown test-suite type: ${suiteType}, treating as TestSuite`);
|
|
101
110
|
const unknownPath = [...parentPath, suiteName];
|
|
@@ -110,15 +119,15 @@ export class NUnitXmlParser {
|
|
|
110
119
|
* @param {Array} currentPath - Current path in hierarchy
|
|
111
120
|
*/
|
|
112
121
|
processChildren(testSuite, currentPath) {
|
|
122
|
+
// Process test-cases first (to maintain order)
|
|
123
|
+
if (testSuite['test-case']) {
|
|
124
|
+
this.parseTestCases(testSuite['test-case'], currentPath, testSuite);
|
|
125
|
+
}
|
|
126
|
+
|
|
113
127
|
// Process nested test-suites
|
|
114
128
|
if (testSuite['test-suite']) {
|
|
115
129
|
this.parseTestSuite(testSuite['test-suite'], currentPath);
|
|
116
130
|
}
|
|
117
|
-
|
|
118
|
-
// Process test-cases
|
|
119
|
-
if (testSuite['test-case']) {
|
|
120
|
-
this.parseTestCases(testSuite['test-case'], currentPath, testSuite);
|
|
121
|
-
}
|
|
122
131
|
}
|
|
123
132
|
|
|
124
133
|
/**
|
|
@@ -156,12 +165,26 @@ export class NUnitXmlParser {
|
|
|
156
165
|
return null;
|
|
157
166
|
}
|
|
158
167
|
|
|
159
|
-
|
|
168
|
+
// Use Description from properties if available (for SpecFlow tests), otherwise use name
|
|
169
|
+
let testName = testCase.name;
|
|
170
|
+
if (testCase.properties && testCase.properties.property) {
|
|
171
|
+
const properties = Array.isArray(testCase.properties.property)
|
|
172
|
+
? testCase.properties.property
|
|
173
|
+
: [testCase.properties.property];
|
|
174
|
+
|
|
175
|
+
const descriptionProperty = properties.find(p => p.name === 'Description');
|
|
176
|
+
if (descriptionProperty && descriptionProperty.value) {
|
|
177
|
+
// Clean up SpecFlow description format: [C211256] Allow mobile print behavior -> Allow mobile print behavior
|
|
178
|
+
testName = descriptionProperty.value.replace(/^\[[^\]]+\]\s*/, '');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
160
182
|
const fullName = testCase.fullname;
|
|
161
183
|
const methodName = testCase.methodname || this.extractMethodName(testName);
|
|
162
184
|
const className = testCase.classname || parentSuite?.name;
|
|
163
185
|
|
|
164
186
|
debug(`Parsing test case: ${testName}`);
|
|
187
|
+
debug(`Test case structure:`, JSON.stringify(testCase, null, 2));
|
|
165
188
|
|
|
166
189
|
// Extract parameters if this is a parameterized test
|
|
167
190
|
const { baseMethodName, parameters, isParameterized } = this.extractParameters(testName);
|
|
@@ -192,17 +215,31 @@ export class NUnitXmlParser {
|
|
|
192
215
|
let message = '';
|
|
193
216
|
let stack = '';
|
|
194
217
|
|
|
218
|
+
const files = [];
|
|
219
|
+
|
|
195
220
|
if (testCase.failure) {
|
|
196
221
|
message = testCase.failure.message || '';
|
|
197
222
|
stack = testCase.failure['stack-trace'] || testCase.failure['#text'] || '';
|
|
198
223
|
}
|
|
199
224
|
|
|
200
|
-
if (testCase.output
|
|
201
|
-
|
|
225
|
+
if (testCase.output) {
|
|
226
|
+
const outputText = typeof testCase.output === 'string' ? testCase.output : testCase.output['#text'];
|
|
227
|
+
const stackFiles = fetchFilesFromStackTrace(outputText);
|
|
228
|
+
files.push(...stackFiles);
|
|
229
|
+
|
|
230
|
+
if (outputText) {
|
|
231
|
+
debug(`Found output in test case: ${outputText.substring(0, 100)}...`);
|
|
232
|
+
stack = `${stack}\n\n${outputText}`.trim();
|
|
233
|
+
} else {
|
|
234
|
+
debug('No output text found in test case');
|
|
235
|
+
}
|
|
236
|
+
} else {
|
|
237
|
+
debug('No output found in test case');
|
|
202
238
|
}
|
|
203
239
|
|
|
204
|
-
// Extract test ID from properties
|
|
240
|
+
// Extract test ID and tags from properties
|
|
205
241
|
let testId = null;
|
|
242
|
+
let tags = [];
|
|
206
243
|
if (testCase.properties && testCase.properties.property) {
|
|
207
244
|
const properties = Array.isArray(testCase.properties.property)
|
|
208
245
|
? testCase.properties.property
|
|
@@ -215,28 +252,62 @@ export class NUnitXmlParser {
|
|
|
215
252
|
if (testId.startsWith('@')) testId = testId.slice(1);
|
|
216
253
|
if (testId.startsWith('T')) testId = testId.slice(1);
|
|
217
254
|
}
|
|
255
|
+
|
|
256
|
+
// Extract Category properties as tags
|
|
257
|
+
const categoryProperties = properties.filter(p => p.name === 'Category');
|
|
258
|
+
tags = categoryProperties.map(p => p.value);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// If no test ID found in properties, try to extract from output
|
|
262
|
+
if (!testId && testCase.output) {
|
|
263
|
+
const outputText = typeof testCase.output === 'string' ? testCase.output : testCase.output['#text'];
|
|
264
|
+
if (outputText) {
|
|
265
|
+
debug(`Looking for test ID in output: ${outputText.substring(0, 200)}...`);
|
|
266
|
+
const idMatch = outputText.match(/\[ID\]\s+tid:\/\/@T([a-f0-9]{8})/i);
|
|
267
|
+
if (idMatch) {
|
|
268
|
+
testId = idMatch[1];
|
|
269
|
+
debug(`Found test ID in output: ${testId}`);
|
|
270
|
+
} else {
|
|
271
|
+
debug('No test ID found in output');
|
|
272
|
+
}
|
|
273
|
+
}
|
|
218
274
|
}
|
|
219
275
|
|
|
220
276
|
// Build file path from suite path and class name
|
|
221
277
|
const filePath = this.buildFilePath(suitePath, className, parentSuite);
|
|
222
278
|
|
|
279
|
+
// For parameterized tests, format example as expected by Testomatio API
|
|
280
|
+
// Convert array of parameters to object with numeric keys
|
|
281
|
+
let example = null;
|
|
282
|
+
if (isParameterized && parameters.length > 0) {
|
|
283
|
+
example = {};
|
|
284
|
+
parameters.forEach((param, index) => {
|
|
285
|
+
example[index] = param;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
223
289
|
return {
|
|
224
|
-
|
|
290
|
+
// For runs: use full test name with parameters (TestBooleanValue(true))
|
|
291
|
+
// For import: API will group by base name using the example field
|
|
292
|
+
title: testName, // Full name with parameters for run display
|
|
225
293
|
methodName: baseMethodName || methodName || testName,
|
|
226
294
|
fullName: fullName,
|
|
227
295
|
suitePath: suitePath,
|
|
228
296
|
suite_title: className || suitePath[suitePath.length - 1] || 'Unknown',
|
|
229
297
|
file: filePath,
|
|
298
|
+
files: files, // Array of files that will be attached
|
|
230
299
|
status: status,
|
|
231
300
|
message: message,
|
|
232
301
|
stack: stack,
|
|
233
302
|
run_time: parseFloat(testCase.duration || testCase.time || 0) * 1000,
|
|
234
303
|
test_id: testId,
|
|
304
|
+
tags: tags, // Array of category tags from properties
|
|
235
305
|
create: true,
|
|
236
306
|
retry: false,
|
|
237
307
|
// Parameterized test metadata
|
|
308
|
+
example: example, // Parameters as object for API grouping
|
|
238
309
|
isParameterized: isParameterized,
|
|
239
|
-
parameters: parameters,
|
|
310
|
+
parameters: parameters, // Keep original array for reference
|
|
240
311
|
baseMethodName: baseMethodName,
|
|
241
312
|
};
|
|
242
313
|
}
|
package/src/pipe/debug.js
CHANGED
|
@@ -15,7 +15,7 @@ export class DebugPipe {
|
|
|
15
15
|
this.isEnabled = !!process.env.TESTOMATIO_DEBUG || !!process.env.DEBUG;
|
|
16
16
|
if (this.isEnabled) {
|
|
17
17
|
this.batch = {
|
|
18
|
-
isEnabled: this.params.isBatchEnabled ??
|
|
18
|
+
isEnabled: this.params.isBatchEnabled ?? !process.env.TESTOMATIO_DISABLE_BATCH_UPLOAD ?? true,
|
|
19
19
|
intervalFunction: null,
|
|
20
20
|
intervalTime: 5000,
|
|
21
21
|
tests: [],
|
|
@@ -93,7 +93,8 @@ export class DebugPipe {
|
|
|
93
93
|
const logData = { action: 'addTest', testId: data };
|
|
94
94
|
if (this.store.runId) logData.runId = this.store.runId;
|
|
95
95
|
this.logToFile(logData);
|
|
96
|
-
}
|
|
96
|
+
}
|
|
97
|
+
else this.batch.tests.push(data);
|
|
97
98
|
|
|
98
99
|
if (!this.batch.intervalFunction) await this.batchUpload();
|
|
99
100
|
}
|
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,11 +459,9 @@ class TestomatioPipe {
|
|
|
456
459
|
status_event,
|
|
457
460
|
detach: params.detach,
|
|
458
461
|
tests: params.tests,
|
|
459
|
-
}
|
|
462
|
+
}
|
|
460
463
|
});
|
|
461
464
|
|
|
462
|
-
debug(APP_PREFIX, '✅ Testrun finished');
|
|
463
|
-
|
|
464
465
|
if (this.runUrl) {
|
|
465
466
|
console.log(APP_PREFIX, '📊 Report Saved. Report URL:', pc.magenta(this.runUrl));
|
|
466
467
|
}
|
|
@@ -471,7 +472,7 @@ class TestomatioPipe {
|
|
|
471
472
|
if (this.runUrl && this.proceed) {
|
|
472
473
|
const notFinishedMessage = pc.yellow(pc.bold('Run was not finished because of $TESTOMATIO_PROCEED'));
|
|
473
474
|
console.log(APP_PREFIX, `📊 ${notFinishedMessage}. Report URL: ${pc.magenta(this.runUrl)}`);
|
|
474
|
-
console.log(APP_PREFIX, `🛬 Run to finish it: TESTOMATIO_RUN=${this.runId} npx
|
|
475
|
+
console.log(APP_PREFIX, `🛬 Run to finish it: TESTOMATIO_RUN=${this.runId} npx @testomatio/reporter finish`);
|
|
475
476
|
}
|
|
476
477
|
|
|
477
478
|
if (this.hasUnmatchedTests) {
|
|
@@ -524,6 +525,9 @@ function printCreateIssue(err) {
|
|
|
524
525
|
console.log({ body: body?.replace(/"(tstmt_[^"]+)"/g, 'tstmt_*'), url, baseURL, method, time });
|
|
525
526
|
console.log('```');
|
|
526
527
|
});
|
|
528
|
+
|
|
527
529
|
}
|
|
528
530
|
|
|
531
|
+
|
|
532
|
+
|
|
529
533
|
export default TestomatioPipe;
|
package/src/reporter.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import Client from './client.js';
|
|
2
|
+
import * as TestomatioConstants from './constants.js';
|
|
3
3
|
import { services } from './services/index.js';
|
|
4
4
|
import reporterFunctions from './reporter-functions.js';
|
|
5
5
|
|
|
6
|
+
export { Client };
|
|
7
|
+
export const STATUS = TestomatioConstants.STATUS;
|
|
6
8
|
export const artifact = reporterFunctions.artifact;
|
|
7
9
|
export const log = reporterFunctions.log;
|
|
8
10
|
export const logger = services.logger;
|
|
@@ -35,6 +37,7 @@ export default {
|
|
|
35
37
|
linkTest: reporterFunctions.linkTest,
|
|
36
38
|
linkJira: reporterFunctions.linkJira,
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
TestomatioClient: Client,
|
|
41
|
+
STATUS,
|
|
42
|
+
|
|
40
43
|
};
|