tewip-ai 0.18.0 → 0.18.2
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/dist/engine/import/junit.js +26 -3
- package/package.json +1 -1
|
@@ -116,6 +116,9 @@ function junitCases(root, workspace) {
|
|
|
116
116
|
}
|
|
117
117
|
out.push({ testId, file: file || (testcase.attrs.classname ?? '').trim(), duration: Number.isFinite(seconds) ? Math.round(seconds * 1000) : 0, attempts });
|
|
118
118
|
};
|
|
119
|
+
// <testrun> is the root Eclipse's JUnit runner and Ant write; everything inside it is ordinary
|
|
120
|
+
// JUnit XML. A real report in that shape was rejected outright as "no test report Tewip can
|
|
121
|
+
// read", which is a poor answer to a file holding 36 perfectly readable results.
|
|
119
122
|
walk(root, root.name === 'testsuite' ? root : undefined);
|
|
120
123
|
// Attempts whose error the runner did not record borrow the final one's, when there is one.
|
|
121
124
|
for (const c of out) {
|
|
@@ -193,6 +196,26 @@ export function junitFiles(path) {
|
|
|
193
196
|
* Playwright; every test, passing or failing, is counted in the run summary so its history
|
|
194
197
|
* shows the passes too.
|
|
195
198
|
*/
|
|
199
|
+
/**
|
|
200
|
+
* A runner's own timestamp, when it is one a machine can read.
|
|
201
|
+
*
|
|
202
|
+
* Maven Surefire writes `timestamp="2025-03-05T11:53:11 IST"` - a timezone abbreviation with no
|
|
203
|
+
* offset, which is not a date any parser accepts. `new Date(...).toISOString()` then threw, and
|
|
204
|
+
* Tewip died on one of the most widely used test runners there is. This was found by reading real
|
|
205
|
+
* Surefire reports from public repositories; every fixture collected for this project had a clean
|
|
206
|
+
* timestamp. A report Tewip cannot date is still a report worth reading, so an unreadable one falls
|
|
207
|
+
* back to the time of import rather than stopping everything.
|
|
208
|
+
*/
|
|
209
|
+
function readTimestamp(raw) {
|
|
210
|
+
if (!raw)
|
|
211
|
+
return null;
|
|
212
|
+
const asIs = new Date(raw);
|
|
213
|
+
if (!Number.isNaN(asIs.getTime()))
|
|
214
|
+
return asIs.toISOString();
|
|
215
|
+
// Drop a trailing zone abbreviation (IST, CEST, PDT...) and read the rest as local time.
|
|
216
|
+
const withoutZone = new Date(raw.replace(/\s+[A-Z]{2,5}$/, ''));
|
|
217
|
+
return Number.isNaN(withoutZone.getTime()) ? null : withoutZone.toISOString();
|
|
218
|
+
}
|
|
196
219
|
export function importJunit(path, meta) {
|
|
197
220
|
const records = [];
|
|
198
221
|
const attempts = {};
|
|
@@ -229,7 +252,7 @@ export function importJunit(path, meta) {
|
|
|
229
252
|
if (start && (!startedAt || start < startedAt))
|
|
230
253
|
startedAt = start;
|
|
231
254
|
}
|
|
232
|
-
else if (root.name === 'testsuites' || root.name === 'testsuite') {
|
|
255
|
+
else if (root.name === 'testsuites' || root.name === 'testsuite' || root.name === 'testrun') {
|
|
233
256
|
cases = junitCases(root, meta.workspace);
|
|
234
257
|
const stamp = root.attrs.timestamp ?? root.children.find((c) => c.name === 'testsuite')?.attrs.timestamp;
|
|
235
258
|
if (stamp && (!startedAt || stamp < startedAt))
|
|
@@ -288,7 +311,7 @@ export function importJunit(path, meta) {
|
|
|
288
311
|
runId: meta.runId,
|
|
289
312
|
gitSha: meta.gitSha,
|
|
290
313
|
...(meta.branch ? { branch: meta.branch } : {}),
|
|
291
|
-
startedAt:
|
|
314
|
+
startedAt: readTimestamp(startedAt) ?? now,
|
|
292
315
|
finishedAt: now,
|
|
293
316
|
status: anyFailed ? 'failed' : 'passed',
|
|
294
317
|
attempts,
|
|
@@ -297,7 +320,7 @@ export function importJunit(path, meta) {
|
|
|
297
320
|
if (unread.length > 0) {
|
|
298
321
|
const list = unread.slice(0, 5).join(', ');
|
|
299
322
|
if (parsedFiles === 0) {
|
|
300
|
-
throw new Error(`no test report Tewip can read in ${path}: ${list}. It reads JUnit XML (<testsuites>/<testsuite>), NUnit 3 (<test-run>), .NET TRX (<TestRun>), ` +
|
|
323
|
+
throw new Error(`no test report Tewip can read in ${path}: ${list}. It reads JUnit XML (<testsuites>/<testsuite>/<testrun>), NUnit 3 (<test-run>), .NET TRX (<TestRun>), ` +
|
|
301
324
|
'Robot Framework output.xml (<robot>), JMeter .jtl (<testResults>) and a k6 summary (--summary-export). ' +
|
|
302
325
|
'Most runners can write JUnit XML; for TestNG use the Surefire report, and for NUnit use --result=x.xml.');
|
|
303
326
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tewip-ai",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.2",
|
|
4
4
|
"description": "Tewip finds why each failing test failed - real bug, flaky test, environment, test data or changed selector - for any stack, from the command line, CI, or your editor.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"test-failures",
|