tewip-ai 0.70.9 → 0.70.11
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.
|
@@ -62,12 +62,25 @@ export function impliedLandmark(layerName) {
|
|
|
62
62
|
return null;
|
|
63
63
|
}
|
|
64
64
|
const PLACEHOLDER = /^(?:lorem ipsum|placeholder|label|text|body|paragraph|xxx+|\.\.\.|…)$/i;
|
|
65
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* Text worth checking for: real words a person would notice missing - **or a number**.
|
|
67
|
+
*
|
|
68
|
+
* This required two consecutive letters, which filters the noise it was written for (a lone glyph,
|
|
69
|
+
* an ellipsis, "Label") and also silently discarded every number in the design. Field-tested: a
|
|
70
|
+
* checkout frame specifying **£54.99** against a page serving **£59.99** produced a byte-identical
|
|
71
|
+
* report - "5 check(s) from the design, 3 met, 2 different" - because the price was never one of the
|
|
72
|
+
* five. A wrong price on a checkout screen is the drift a design review exists to catch, and it was
|
|
73
|
+
* the one kind that could not be seen.
|
|
74
|
+
*
|
|
75
|
+
* A run of two or more digits now counts, so a price, a total, a quantity or a rate becomes a check.
|
|
76
|
+
* A single character still does not, nor does punctuation on its own: `3`, `—` and `...` are noise,
|
|
77
|
+
* `£54.99` and `20%` are the design speaking.
|
|
78
|
+
*/
|
|
66
79
|
function meaningful(text) {
|
|
67
80
|
const t = text.trim();
|
|
68
81
|
if (t.length < 2 || t.length > 120)
|
|
69
82
|
return false;
|
|
70
|
-
if (!/[A-Za-z]{2}/.test(t))
|
|
83
|
+
if (!/[A-Za-z]{2}/.test(t) && !/\d{2}/.test(t))
|
|
71
84
|
return false;
|
|
72
85
|
return !PLACEHOLDER.test(t);
|
|
73
86
|
}
|
|
@@ -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)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tewip-ai",
|
|
3
|
-
"version": "0.70.
|
|
3
|
+
"version": "0.70.11",
|
|
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": [
|