tewip-ai 0.70.10 → 0.70.12
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.
|
@@ -19,6 +19,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
19
19
|
import { existsSync, readFileSync, readdirSync, statSync, watch } from 'node:fs';
|
|
20
20
|
import { join, resolve } from 'node:path';
|
|
21
21
|
import { spawnSync } from 'node:child_process';
|
|
22
|
+
import { detectFrameworks } from '../quality/frameworks.js';
|
|
22
23
|
/** Where test runners in this project put their reports, in the order they are usually found. */
|
|
23
24
|
export const REPORT_PLACES = [
|
|
24
25
|
'blob-report',
|
|
@@ -103,6 +104,40 @@ const SKIP_DIR = /(?:^|[\\/])(?:node_modules|\.git|\.tewip|dist|build|target|cov
|
|
|
103
104
|
* Watches the project and explains failures as they appear. Returns when `once` is set; otherwise
|
|
104
105
|
* it runs until the person stops it, which is what a terminal beside your editor is for.
|
|
105
106
|
*/
|
|
107
|
+
/**
|
|
108
|
+
* What to change so the next run can be explained - named for the runner this project actually uses.
|
|
109
|
+
*
|
|
110
|
+
* The advice was a fixed list of three examples: pytest, jest, dotnet. Field-tested on a project
|
|
111
|
+
* using **`node --test`**, Node's own built-in runner, the suite failed with a perfectly clear
|
|
112
|
+
* assertion - `26 !== 25`, the test named, the line numbered - and the answer was a list that did
|
|
113
|
+
* not mention the runner failing in front of it. Telling somebody to configure jest when they are
|
|
114
|
+
* not using jest is the kind of advice that gets a tool closed.
|
|
115
|
+
*
|
|
116
|
+
* The frameworks this project has are already detectable, so the first line is the one command that
|
|
117
|
+
* will work here, and the examples stay underneath for anyone whose runner was not found.
|
|
118
|
+
*/
|
|
119
|
+
export function howToWriteAReport(root) {
|
|
120
|
+
const JUNIT = {
|
|
121
|
+
node: 'node --test --test-reporter=junit --test-reporter-destination=report.xml',
|
|
122
|
+
jest: 'npx jest --reporters=default --reporters=jest-junit',
|
|
123
|
+
vitest: 'npx vitest run --reporter=junit --outputFile=report.xml',
|
|
124
|
+
mocha: 'npx mocha --reporter mocha-junit-reporter',
|
|
125
|
+
pytest: 'pytest --junitxml=report.xml',
|
|
126
|
+
go: 'gotestsum --junitfile report.xml',
|
|
127
|
+
dotnet: 'dotnet test --logger trx',
|
|
128
|
+
maven: 'mvn test (Surefire already writes XML to target/surefire-reports)',
|
|
129
|
+
gradle: './gradlew test (already writes XML to build/test-results)',
|
|
130
|
+
playwright: 'npx playwright test --reporter=blob',
|
|
131
|
+
};
|
|
132
|
+
const here = detectFrameworks(root)
|
|
133
|
+
.map((f) => JUNIT[f.id])
|
|
134
|
+
.filter((line, i, all) => Boolean(line) && all.indexOf(line) === i);
|
|
135
|
+
const head = 'The tests failed but wrote no report Tewip can read.';
|
|
136
|
+
if (here.length === 0) {
|
|
137
|
+
return `${head} Make the runner write JUnit XML (for example: pytest --junitxml=report.xml, jest --reporters=jest-junit, dotnet test --logger trx).`;
|
|
138
|
+
}
|
|
139
|
+
return [`${head} For the runner${here.length === 1 ? '' : 's'} this project has, that is:`, ...here.map((line) => ` ${line}`)].join(String.fromCharCode(10));
|
|
140
|
+
}
|
|
106
141
|
export async function runWatch(cmd) {
|
|
107
142
|
const root = resolve(cmd.root);
|
|
108
143
|
const explain = cmd.explain ?? explainReport;
|
|
@@ -124,9 +159,7 @@ export async function runWatch(cmd) {
|
|
|
124
159
|
}
|
|
125
160
|
const found = cmd.report ? { path: resolve(root, cmd.report), at: Date.now() } : newestReport(root);
|
|
126
161
|
if (!found || !existsSync(found.path)) {
|
|
127
|
-
console.log(cmd.cmd
|
|
128
|
-
? 'The tests failed but wrote no report Tewip can read. Make the runner write JUnit XML (for example: pytest --junitxml=report.xml, jest --reporters=jest-junit, dotnet test --logger trx).'
|
|
129
|
-
: 'No test report here yet. Run your tests, or use --cmd "npm test" to let Tewip run them.');
|
|
162
|
+
console.log(cmd.cmd ? howToWriteAReport(root) : 'No test report here yet. Run your tests, or use --cmd "npm test" to let Tewip run them.');
|
|
130
163
|
return;
|
|
131
164
|
}
|
|
132
165
|
if (!cmd.cmd && found.at === seen)
|
|
@@ -43,10 +43,26 @@ export function digestView(allItems, allSummaries, dataset) {
|
|
|
43
43
|
counts.set(i.diagnosis.category, (counts.get(i.diagnosis.category) ?? 0) + 1);
|
|
44
44
|
return [...counts.entries()].sort((a, b) => b[1] - a[1])[0]?.[0];
|
|
45
45
|
};
|
|
46
|
+
// Was there an earlier half to compare the later one against?
|
|
47
|
+
//
|
|
48
|
+
// The window is split at the median run time, and `half()` puts anything not strictly before the
|
|
49
|
+
// median into the later half - so with a single run the **earlier half is empty by construction**,
|
|
50
|
+
// no row can ever appear, and the digest said:
|
|
51
|
+
//
|
|
52
|
+
// Comparing 2026-09-16 to 2026-09-16 with 2026-09-16 to 2026-09-16, over all 1 runs.
|
|
53
|
+
// No area got noticeably worse.
|
|
54
|
+
//
|
|
55
|
+
// A window compared against itself, reported as reassurance. "Nothing got worse" and "nothing
|
|
56
|
+
// could have been shown to get worse" are different statements, and a lead reading a weekly note
|
|
57
|
+
// has no way to tell them apart. Found by running `note` on a one-run history.
|
|
58
|
+
const earlier = summaries.filter((s) => half(s.startedAt) === 0).length;
|
|
59
|
+
const comparable = earlier > 0 && summaries.length - earlier > 0;
|
|
46
60
|
const markdown = [
|
|
47
61
|
'# Risk digest',
|
|
48
62
|
'',
|
|
49
|
-
|
|
63
|
+
comparable
|
|
64
|
+
? `Comparing ${period(0)} with ${period(1)}, over ${scope}. ${rows.length === 0 ? 'No area got noticeably worse.' : `${rows.length} area(s) got worse.`}`
|
|
65
|
+
: `**Nothing to compare yet.** ${summaries.length === 1 ? 'One run is kept here' : `${summaries.length} run(s) are kept here, all at the same moment`}, so there is no earlier period to measure a later one against - this is not a report that nothing got worse. Keep a few more runs and ask again.`,
|
|
50
66
|
'',
|
|
51
67
|
sourceNote(dataset),
|
|
52
68
|
'',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tewip-ai",
|
|
3
|
-
"version": "0.70.
|
|
3
|
+
"version": "0.70.12",
|
|
4
4
|
"mcpName": "io.github.hmamut39/tewip",
|
|
5
5
|
"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.",
|
|
6
6
|
"keywords": [
|