blastproof 0.16.0 → 0.17.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 -0
- package/dist/cli.js +11 -8
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,6 +77,8 @@ Three questions. The first one decides most cases.
|
|
|
77
77
|
|
|
78
78
|
**A hard requirement, not a preference.** blastproof finds elements the way a screen reader does — by role, by label, by visible text. That is what removes selectors and survives redesigns. The cost is that there is deliberately no CSS or XPath fallback, so anything the accessibility tree cannot describe cannot be driven at all.
|
|
79
79
|
|
|
80
|
+
The name is matched **exactly first**, then by substring if nothing matches exactly — so a control named `Add` is found even when `Add New` sits above it. When several controls answer to the same name, the first one on the page wins. Give each control an accessible name no other control on the page shares; a page that cannot offer one cannot be driven unambiguously, and no matching rule fixes that.
|
|
81
|
+
|
|
80
82
|
| works | cannot be driven |
|
|
81
83
|
| --- | --- |
|
|
82
84
|
| `<button>Add to cart</button>` | a `<div>` with a click handler |
|
package/dist/cli.js
CHANGED
|
@@ -424,13 +424,18 @@ function describeTarget(target) {
|
|
|
424
424
|
async function resolveTarget(page, target, resolveTimeoutMs = 2e3) {
|
|
425
425
|
const candidates = [];
|
|
426
426
|
if (target.role) {
|
|
427
|
+
if (target.name) {
|
|
428
|
+
candidates.push(page.getByRole(target.role, { name: target.name, exact: true }));
|
|
429
|
+
}
|
|
427
430
|
candidates.push(page.getByRole(target.role, target.name ? { name: target.name } : {}));
|
|
428
431
|
}
|
|
429
432
|
if (target.name) {
|
|
433
|
+
candidates.push(page.getByLabel(target.name, { exact: true }));
|
|
430
434
|
candidates.push(page.getByLabel(target.name));
|
|
431
435
|
}
|
|
432
436
|
const text = target.text ?? target.name;
|
|
433
437
|
if (text) {
|
|
438
|
+
candidates.push(page.getByText(text, { exact: true }));
|
|
434
439
|
candidates.push(page.getByText(text));
|
|
435
440
|
}
|
|
436
441
|
for (const candidate of candidates) {
|
|
@@ -2952,13 +2957,11 @@ async function planCommand(options) {
|
|
|
2952
2957
|
written.push(path10.relative(options.cwd, file));
|
|
2953
2958
|
console.log(` wrote ${path10.relative(options.cwd, file)}`);
|
|
2954
2959
|
} catch (error) {
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
}
|
|
2961
|
-
throw error;
|
|
2960
|
+
generated.pop();
|
|
2961
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
2962
|
+
failed.push({ route, reason });
|
|
2963
|
+
console.log(` X failed: ${reason}`);
|
|
2964
|
+
continue;
|
|
2962
2965
|
}
|
|
2963
2966
|
} else {
|
|
2964
2967
|
console.log(`
|
|
@@ -3079,7 +3082,7 @@ function parsePositiveNumber(flag) {
|
|
|
3079
3082
|
};
|
|
3080
3083
|
}
|
|
3081
3084
|
var program = new Command();
|
|
3082
|
-
program.name("blastproof").description("Open-source AI testing agent: plain-English YAML tests executed agentically on a real browser.").version("0.
|
|
3085
|
+
program.name("blastproof").description("Open-source AI testing agent: plain-English YAML tests executed agentically on a real browser.").version("0.17.0");
|
|
3083
3086
|
program.command("init").description("Scaffold .blastproof/ (config, tests, sample tests) in the current directory").action(async () => {
|
|
3084
3087
|
try {
|
|
3085
3088
|
const result = await initProject(process.cwd());
|