@activate-core/test-forge 0.13.1 → 0.14.0
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/core/ai-generator.js +41 -0
- package/dist/core/doc-guidance.js +6 -0
- package/dist/core/reference.js +10 -0
- package/package.json +1 -1
- package/reporters/_shared.cjs +19 -3
|
@@ -105,6 +105,47 @@ export function buildPrompt(journey, map, testPath, focus, harnessPath, transpor
|
|
|
105
105
|
`guard is missing and produce a failing test that falsely brands the`,
|
|
106
106
|
`product as vulnerable.`,
|
|
107
107
|
``,
|
|
108
|
+
`PRIME DIRECTIVE — A FAILING TEST MUST MEAN A REAL PRODUCT DEFECT.`,
|
|
109
|
+
`Teams hold releases on what these tests report. A test that fails for`,
|
|
110
|
+
`any reason other than the product being wrong is worse than no test at`,
|
|
111
|
+
`all: it burns the team's trust, and the next real defect gets waved`,
|
|
112
|
+
`through as "probably the tool again". So a test may FAIL only when the`,
|
|
113
|
+
`product provably contradicts an expectation the journey document`,
|
|
114
|
+
`states EXPLICITLY. Apply these rules without exception:`,
|
|
115
|
+
`(1) EXPLICIT-ORACLE ONLY. Before writing an assertion, find the exact`,
|
|
116
|
+
` line in the journey document that fixes the expected outcome, and`,
|
|
117
|
+
` cite it in a short comment (e.g. "// oracle: §4 total = fee +`,
|
|
118
|
+
` shipping"). If the expectation is merely implied, inferred, or`,
|
|
119
|
+
` "good practice" — including a rule that sounds obviously right —`,
|
|
120
|
+
` it is NOT an oracle: write it ${pending} with a "// TODO:" note.`,
|
|
121
|
+
` An assertion you cannot trace to a stated requirement is a false`,
|
|
122
|
+
` positive waiting to happen. Anything under a "Suggested (not a`,
|
|
123
|
+
` requirement…)" heading is explicitly NOT an oracle — never assert`,
|
|
124
|
+
` it; make it ${pending} if you cover it at all.`,
|
|
125
|
+
`(2) INFRASTRUCTURE IS NEVER A PRODUCT DEFECT. If a precondition cannot`,
|
|
126
|
+
` be established — a dependency is unreachable, a required env var or`,
|
|
127
|
+
` credential is absent, seed/fixture data is missing, a second`,
|
|
128
|
+
` identity is unavailable, an external provider is down — SKIP the`,
|
|
129
|
+
` test with a one-line reason naming exactly what was missing. Never`,
|
|
130
|
+
` let a missing precondition reach an assertion and report as a bug.`,
|
|
131
|
+
` Guard such tests at the top: check the precondition, skip if unmet.`,
|
|
132
|
+
`(3) NO FLAKY TESTS. Every test must pass or fail for the same reason on`,
|
|
133
|
+
` every run, in any order. Do not depend on execution order, on data`,
|
|
134
|
+
` another test creates or mutates, on wall-clock timing, or on`,
|
|
135
|
+
` ambient totals that other tests change (assert on the rows YOU`,
|
|
136
|
+
` seeded, by id — never on a global count). Set up what you assert`,
|
|
137
|
+
` on, and assert only on that. Wait for a specific condition, never a`,
|
|
138
|
+
` fixed sleep.`,
|
|
139
|
+
`(4) NEVER ASSERT AN UNFIXED VALUE. Do not assert exact user-facing copy,`,
|
|
140
|
+
` incidental ordering, generated ids, timestamps, or counts the`,
|
|
141
|
+
` document does not fix. Assert the behaviour the document specifies,`,
|
|
142
|
+
` at the loosest form that still proves it.`,
|
|
143
|
+
`(5) A TIMEOUT IS NOT A BUG REPORT. If an action legitimately waits on`,
|
|
144
|
+
` something external, verify availability first and skip when absent.`,
|
|
145
|
+
` A test that times out tells the team nothing about the product.`,
|
|
146
|
+
`When rules conflict, prefer reporting LESS: a pending test costs a line`,
|
|
147
|
+
`in the report; a false failure costs the team a release.`,
|
|
148
|
+
``,
|
|
108
149
|
`GROUND EVERYTHING IN THE REAL SOURCE. You are running inside the`,
|
|
109
150
|
`project's repository and have read-only tools (Read, Grep, Glob, LS).`,
|
|
110
151
|
`BEFORE writing tests, look up the actual code for this journey — use`,
|
|
@@ -20,6 +20,12 @@ export const DEEP_DOC_GUIDANCE = [
|
|
|
20
20
|
` vague mentions;`,
|
|
21
21
|
`- concrete acceptance criteria per case (exactly what must hold).`,
|
|
22
22
|
`Aim for the depth of a spec a new engineer could implement from.`,
|
|
23
|
+
`Every acceptance criterion you write becomes an ORACLE — tests are`,
|
|
24
|
+
`generated from it, and a product that disagrees is reported to the team`,
|
|
25
|
+
`as a defect. So state a criterion ONLY where the source actually fixes`,
|
|
26
|
+
`the behaviour. Anything you merely believe SHOULD hold goes under a`,
|
|
27
|
+
`"Suggested (not a requirement — do not assert)" heading, never into the`,
|
|
28
|
+
`acceptance criteria: an invented requirement becomes a false bug report.`,
|
|
23
29
|
`Organise the body with numbered "## N. <Section>" headings, ONE`,
|
|
24
30
|
`concern per section, because each section later becomes its own`,
|
|
25
31
|
`focused test file — so the richer and better-separated the sections,`,
|
package/dist/core/reference.js
CHANGED
|
@@ -147,6 +147,16 @@ export function buildReferenceDiscoverPrompt(srcDir, docsDir, reference, journey
|
|
|
147
147
|
`Rules:`,
|
|
148
148
|
`- Base behavior on the reference and technical detail on real code;`,
|
|
149
149
|
` do not invent either with false confidence.`,
|
|
150
|
+
`- EVERY requirement you write becomes an ORACLE: tests will be`,
|
|
151
|
+
` generated from it, and a product that disagrees will be reported to`,
|
|
152
|
+
` the team as a defect. So write a requirement ONLY when the reference`,
|
|
153
|
+
` actually states it. Do NOT add hardening, validation, limits, or`,
|
|
154
|
+
` guards that the reference does not ask for, however sensible they`,
|
|
155
|
+
` seem — an invented requirement becomes a false bug report and costs`,
|
|
156
|
+
` the team a release.`,
|
|
157
|
+
`- When you believe something SHOULD hold but the reference does not say`,
|
|
158
|
+
` so, put it under a "Suggested (not a requirement — do not assert)"`,
|
|
159
|
+
` heading, never in Expected / Negative Cases / acceptance criteria.`,
|
|
150
160
|
`- Where the reference is silent on a needed detail, add a "# TODO:"`,
|
|
151
161
|
` line describing what the developer must verify.`,
|
|
152
162
|
`- Never include secrets — refer to env var names only.`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@activate-core/test-forge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "AI-powered QA automation. Scans a project, drafts journey docs, and generates seeded Jest/Playwright tests. Works in any project, with any AI CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/reporters/_shared.cjs
CHANGED
|
@@ -117,11 +117,27 @@ function resolveEnv() {
|
|
|
117
117
|
|
|
118
118
|
function sig(msg) {
|
|
119
119
|
const m = strip(msg || '').replace(/\n/g, ' ');
|
|
120
|
-
|
|
120
|
+
// Order matters, and each pattern has to be precise. A failing assertion
|
|
121
|
+
// carries plenty of incidental words — Playwright prints "Timeout: 5000ms"
|
|
122
|
+
// inside every expect() failure, and a status-code assertion legitimately
|
|
123
|
+
// mentions 403 — so loose patterns used to swallow most failures into
|
|
124
|
+
// "Timeout" / "IM auth" and made the whole triage useless.
|
|
125
|
+
|
|
126
|
+
// 1) A REAL timeout: the runner itself gave up, or the socket did.
|
|
127
|
+
if (/test timeout of \d+ ?ms exceeded|exceeded timeout of \d+ ?ms|timed out after \d+|ETIMEDOUT|ESOCKETTIMEDOUT|ECONNABORTED/i.test(m))
|
|
128
|
+
return 'Timeout';
|
|
129
|
+
|
|
130
|
+
// 2) An assertion that ran and disagreed — the common, useful case.
|
|
131
|
+
if (/expect\(.*\)|toBe\b|toEqual\b|toHaveCount\b|Received:|Expected:|expected the result to/i.test(m))
|
|
132
|
+
return 'Assertion mismatch';
|
|
133
|
+
|
|
134
|
+
// 3) Auth against the identity service — needs auth wording, not a bare 403.
|
|
135
|
+
if (/whoami|invalid_grant|refresh token|Unauthorized|Forbidden|invalid token|jwt (expired|malformed)/i.test(m))
|
|
136
|
+
return 'IM auth (403)';
|
|
137
|
+
|
|
121
138
|
if (/\$gt|\$exists|injection/i.test(m)) return 'NoSQL injection accepted';
|
|
122
|
-
if (/timeout|timed out|ETIMEDOUT/i.test(m)) return 'Timeout';
|
|
123
139
|
if (/\b500\b|Internal Server/i.test(m)) return 'Server 500';
|
|
124
|
-
if (/
|
|
140
|
+
if (/timeout|timed out/i.test(m)) return 'Timeout'; // looser fallback, last
|
|
125
141
|
return 'Uncategorised';
|
|
126
142
|
}
|
|
127
143
|
|