blastproof 0.4.0 → 0.5.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/README.md +2 -2
- package/dist/cli.js +26 -4
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -107,9 +107,9 @@ jobs:
|
|
|
107
107
|
|
|
108
108
|
- run: npm start & # however your app boots
|
|
109
109
|
|
|
110
|
-
- uses: hamc/blastproof@v0.
|
|
110
|
+
- uses: hamc/blastproof@v0.5.0
|
|
111
111
|
with:
|
|
112
|
-
version: '0.
|
|
112
|
+
version: '0.5.0' # pin both when this gates merges
|
|
113
113
|
api-key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
114
114
|
base: ${{ github.event.pull_request.base.ref }}
|
|
115
115
|
min-score: '80'
|
package/dist/cli.js
CHANGED
|
@@ -256,7 +256,7 @@ function estimateMaxModelCalls(tests, maxIterationsPerStep, maxRetriesPerStep) {
|
|
|
256
256
|
(sum, test) => sum + (test.setup?.length ?? 0) + test.steps.length,
|
|
257
257
|
0
|
|
258
258
|
);
|
|
259
|
-
return totalSteps * (maxIterationsPerStep + maxRetriesPerStep);
|
|
259
|
+
return totalSteps * (maxIterationsPerStep + maxRetriesPerStep + Math.min(maxIterationsPerStep, maxRetriesPerStep));
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
// src/runner/env.ts
|
|
@@ -439,6 +439,19 @@ async function performAction(page, action, ctx) {
|
|
|
439
439
|
|
|
440
440
|
// src/runner/executor.ts
|
|
441
441
|
var DEFAULT_MAX_ITERATIONS_PER_STEP = 15;
|
|
442
|
+
var SETTLE_TIMEOUT_MS = 2e3;
|
|
443
|
+
async function waitForSettled(page) {
|
|
444
|
+
const deadline = Date.now() + SETTLE_TIMEOUT_MS;
|
|
445
|
+
const urlBefore = page.url();
|
|
446
|
+
await page.waitForLoadState("networkidle", { timeout: SETTLE_TIMEOUT_MS }).catch(() => {
|
|
447
|
+
});
|
|
448
|
+
if (page.url() === urlBefore) return;
|
|
449
|
+
const remaining = deadline - Date.now();
|
|
450
|
+
if (remaining > 0) {
|
|
451
|
+
await page.waitForLoadState("networkidle", { timeout: remaining }).catch(() => {
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
}
|
|
442
455
|
async function defaultSnapshot(page, maxLines) {
|
|
443
456
|
const { captureSnapshot } = await import("./snapshot-CAIB2OHX.js");
|
|
444
457
|
return captureSnapshot(page, { maxLines });
|
|
@@ -496,6 +509,7 @@ async function executeTest(page, test, options) {
|
|
|
496
509
|
if (iterations >= maxIterationsPerStep) {
|
|
497
510
|
throw new StepFailure(`step exceeded ${maxIterationsPerStep} actions without completing`);
|
|
498
511
|
}
|
|
512
|
+
await waitForSettled(page);
|
|
499
513
|
const snap = await takeSnapshot(page);
|
|
500
514
|
let action;
|
|
501
515
|
try {
|
|
@@ -527,7 +541,12 @@ async function executeTest(page, test, options) {
|
|
|
527
541
|
}
|
|
528
542
|
if (action.action === "assert") {
|
|
529
543
|
const expectation = action.expectation ?? action.reasoning;
|
|
530
|
-
|
|
544
|
+
let judgment = await brain.judge(mask(expectation), mask(snap));
|
|
545
|
+
if (!judgment.pass) {
|
|
546
|
+
await waitForSettled(page);
|
|
547
|
+
const freshSnap = await takeSnapshot(page);
|
|
548
|
+
judgment = await brain.judge(mask(expectation), mask(freshSnap));
|
|
549
|
+
}
|
|
531
550
|
const result = judgment.pass ? `ok: assertion passed: ${judgment.reason}` : `assertion failed: ${judgment.reason}`;
|
|
532
551
|
emitAction(index, action, result);
|
|
533
552
|
if (judgment.pass) {
|
|
@@ -1033,6 +1052,7 @@ Rules:
|
|
|
1033
1052
|
- Return "done" when the current step's outcome holds \u2014 including when it already held before you acted, or was achieved by your previous action. "Already true" is done, never failure. Do not return "done" for work belonging to later steps.
|
|
1034
1053
|
- Return "fail" only when the step's outcome cannot be reached: the element is still absent after retries, the page cannot support the step, or an error blocks progress. Never return "fail" because the work appears to have been done already.
|
|
1035
1054
|
- If your previous action errored, re-read the fresh snapshot and choose an alternative element or approach. Do not repeat the exact same failing action.
|
|
1055
|
+
- \`***\` in a snapshot is a redacted secret \u2014 a password, token or key deliberately withheld from you. Seeing it is expected and is not a problem. A field showing \`***\` after you filled it from an {{env.VAR}} placeholder means the fill worked; treat that as success and move on. Never retry a fill because its value is redacted, and never report failure because a value was withheld.
|
|
1036
1056
|
- Keep reasoning to one short sentence.`;
|
|
1037
1057
|
}
|
|
1038
1058
|
function agentUserPrompt(input) {
|
|
@@ -1053,7 +1073,9 @@ function agentUserPrompt(input) {
|
|
|
1053
1073
|
return parts.join("\n");
|
|
1054
1074
|
}
|
|
1055
1075
|
function assertSystemPrompt() {
|
|
1056
|
-
return `You are a QA judge. You receive a page accessibility snapshot and an expectation. Decide whether the snapshot satisfies the expectation. Be strict: only pass when the expectation is clearly met by the snapshot content. Answer with pass=true/false and a one-sentence reason
|
|
1076
|
+
return `You are a QA judge. You receive a page accessibility snapshot and an expectation. Decide whether the snapshot satisfies the expectation. Be strict: only pass when the expectation is clearly met by the snapshot content. Answer with pass=true/false and a one-sentence reason.
|
|
1077
|
+
|
|
1078
|
+
\`***\` marks a secret deliberately withheld from you \u2014 a password, token or key. Seeing it is expected. A field holding \`***\` is filled, not empty, so do not fail an expectation on the grounds that a value was redacted. This applies only to the redaction itself: everything else the expectation asks for must still be visibly satisfied by the snapshot, and an expectation you genuinely cannot check against what you were shown still fails.`;
|
|
1057
1079
|
}
|
|
1058
1080
|
function assertUserPrompt(expectation, snapshot) {
|
|
1059
1081
|
return [
|
|
@@ -2534,7 +2556,7 @@ function parsePositiveNumber(flag) {
|
|
|
2534
2556
|
};
|
|
2535
2557
|
}
|
|
2536
2558
|
var program = new Command();
|
|
2537
|
-
program.name("blastproof").description("Open-source AI testing agent: plain-English YAML tests executed agentically on a real browser.").version("0.
|
|
2559
|
+
program.name("blastproof").description("Open-source AI testing agent: plain-English YAML tests executed agentically on a real browser.").version("0.5.0");
|
|
2538
2560
|
program.command("init").description("Scaffold .blastproof/ (config, tests, sample tests) in the current directory").action(async () => {
|
|
2539
2561
|
try {
|
|
2540
2562
|
const result = await initProject(process.cwd());
|