@hasna/testers 0.0.57 → 0.0.58
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 +3 -2
- package/dist/cli/index.js +105 -5
- package/dist/lib/workflow-fanout.d.ts +24 -0
- package/dist/lib/workflow-fanout.d.ts.map +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/server/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,9 +40,10 @@ testers workflow create "Projects CRUD" \
|
|
|
40
40
|
testers workflow fanout --project alumia --workers 6 --url https://preview.example.com
|
|
41
41
|
testers workflow fanout wf_abc,wf_def wf_xyz --workers 12 --url https://preview.example.com --json
|
|
42
42
|
testers workflow fanout --project alumia --tag action-specific --workers 6 --batch-size 12 --batch 1 --url https://preview.example.com
|
|
43
|
+
testers workflow fanout --project alumia --tag action-specific --workers 6 --batch-size 12 --all-batches --url https://preview.example.com
|
|
43
44
|
```
|
|
44
45
|
|
|
45
|
-
`--workers` is bounded to 1-12 concurrent sandboxes. Use `--batch-size` with a 1-based `--batch` to run large workflow corpora in deterministic waves, or `--offset` for a manual selected-workflow cursor. Fanout preflights provider credentials, required sandbox environment references, `rsync`, and app source directories before launching workers. Use `--dry-run` to inspect the remote commands, upload plans, and preflight checks without spawning sandboxes.
|
|
46
|
+
`--workers` is bounded to 1-12 concurrent sandboxes. Use `--batch-size` with a 1-based `--batch` to run large workflow corpora in deterministic waves, or `--all-batches` with optional `--from-batch` / `--to-batch` to run a staged range in one command. `--offset` is available for a manual selected-workflow cursor. Fanout preflights provider credentials, required sandbox environment references, `rsync`, and app source directories before launching workers. Use `--dry-run` to inspect the remote commands, upload plans, and preflight checks without spawning sandboxes.
|
|
46
47
|
|
|
47
48
|
### Next.js Route and Action Inventory
|
|
48
49
|
|
|
@@ -64,7 +65,7 @@ testers inventory next /path/to/app \
|
|
|
64
65
|
--sandbox-app-wait-url http://127.0.0.1:3000/health \
|
|
65
66
|
--sandbox-env-optional OPENAI_API_KEY
|
|
66
67
|
|
|
67
|
-
testers workflow fanout --project alumia --tag action-specific --workers 6 --batch-size 12 --batch 1 --url https://preview.example.com --dry-run
|
|
68
|
+
testers workflow fanout --project alumia --tag action-specific --workers 6 --batch-size 12 --all-batches --from-batch 1 --to-batch 3 --url https://preview.example.com --dry-run
|
|
68
69
|
```
|
|
69
70
|
|
|
70
71
|
Use `--action-workflow-grouping action` for one workflow per discovered action, `route` for route-specific workflows, or `area-kind` for broader workflows such as commerce buttons or admin API methods. Add the `--sandbox-app-*` flags when the sandbox should rsync, install, start, and test the app source instead of only testing an already-running URL.
|
package/dist/cli/index.js
CHANGED
|
@@ -60626,8 +60626,10 @@ var init_agents = __esm(() => {
|
|
|
60626
60626
|
// src/lib/workflow-fanout.ts
|
|
60627
60627
|
var exports_workflow_fanout = {};
|
|
60628
60628
|
__export(exports_workflow_fanout, {
|
|
60629
|
+
runWorkflowFanoutBatches: () => runWorkflowFanoutBatches,
|
|
60629
60630
|
runWorkflowFanout: () => runWorkflowFanout,
|
|
60630
60631
|
resolveWorkflowFanoutSelection: () => resolveWorkflowFanoutSelection,
|
|
60632
|
+
resolveWorkflowFanoutBatchRange: () => resolveWorkflowFanoutBatchRange,
|
|
60631
60633
|
resolveWorkflowFanoutBatch: () => resolveWorkflowFanoutBatch,
|
|
60632
60634
|
normalizeFanoutWorkerCount: () => normalizeFanoutWorkerCount,
|
|
60633
60635
|
checkWorkflowFanoutReadiness: () => checkWorkflowFanoutReadiness
|
|
@@ -60671,6 +60673,28 @@ function resolveWorkflowFanoutBatch(workflows, options = {}) {
|
|
|
60671
60673
|
}
|
|
60672
60674
|
};
|
|
60673
60675
|
}
|
|
60676
|
+
function resolveWorkflowFanoutBatchRange(matched, options) {
|
|
60677
|
+
const batchSize = normalizeOptionalPositiveInteger(options.batchSize, "workflow fanout batch size");
|
|
60678
|
+
if (batchSize === undefined) {
|
|
60679
|
+
throw new Error("workflow fanout batch range requires batch size");
|
|
60680
|
+
}
|
|
60681
|
+
if (matched < 1) {
|
|
60682
|
+
throw new Error("workflow fanout batch range requires at least one matched workflow");
|
|
60683
|
+
}
|
|
60684
|
+
const totalBatches = Math.ceil(matched / batchSize);
|
|
60685
|
+
const batchStart = normalizeOptionalPositiveInteger(options.batchStart, "workflow fanout start batch") ?? 1;
|
|
60686
|
+
const batchEnd = normalizeOptionalPositiveInteger(options.batchEnd, "workflow fanout end batch") ?? totalBatches;
|
|
60687
|
+
if (batchStart > batchEnd) {
|
|
60688
|
+
throw new Error("workflow fanout start batch must be less than or equal to end batch");
|
|
60689
|
+
}
|
|
60690
|
+
if (batchStart > totalBatches) {
|
|
60691
|
+
throw new Error(`workflow fanout start batch ${batchStart} exceeds total batches ${totalBatches}`);
|
|
60692
|
+
}
|
|
60693
|
+
if (batchEnd > totalBatches) {
|
|
60694
|
+
throw new Error(`workflow fanout end batch ${batchEnd} exceeds total batches ${totalBatches}`);
|
|
60695
|
+
}
|
|
60696
|
+
return { batchSize, batchStart, batchEnd, totalBatches };
|
|
60697
|
+
}
|
|
60674
60698
|
function resolveWorkflowFanoutSelection(options) {
|
|
60675
60699
|
const ids = splitWorkflowIds(options.workflowIds);
|
|
60676
60700
|
const workflows = ids.length > 0 ? ids.map((id) => {
|
|
@@ -60876,6 +60900,49 @@ async function runWorkflowFanout(options, dependencies = {}) {
|
|
|
60876
60900
|
preflight
|
|
60877
60901
|
};
|
|
60878
60902
|
}
|
|
60903
|
+
async function runWorkflowFanoutBatches(options, dependencies = {}) {
|
|
60904
|
+
if (options.batch !== undefined || options.offset !== undefined) {
|
|
60905
|
+
throw new Error("workflow fanout all-batches cannot be combined with batch or offset");
|
|
60906
|
+
}
|
|
60907
|
+
const workers = normalizeFanoutWorkerCount(options.workers);
|
|
60908
|
+
const matchedWorkflows = resolveWorkflowFanoutSelection(options);
|
|
60909
|
+
const { batchSize, batchStart, batchEnd, totalBatches } = resolveWorkflowFanoutBatchRange(matchedWorkflows.length, options);
|
|
60910
|
+
const batches = [];
|
|
60911
|
+
let stoppedEarly = false;
|
|
60912
|
+
for (let batch = batchStart;batch <= batchEnd; batch++) {
|
|
60913
|
+
const result = await runWorkflowFanout({
|
|
60914
|
+
...options,
|
|
60915
|
+
batchSize,
|
|
60916
|
+
batch,
|
|
60917
|
+
batchStart: undefined,
|
|
60918
|
+
batchEnd: undefined,
|
|
60919
|
+
offset: undefined
|
|
60920
|
+
}, dependencies);
|
|
60921
|
+
batches.push(result);
|
|
60922
|
+
if (result.status === "failed" && !options.continueOnFailure) {
|
|
60923
|
+
stoppedEarly = batch < batchEnd;
|
|
60924
|
+
break;
|
|
60925
|
+
}
|
|
60926
|
+
}
|
|
60927
|
+
const total = batches.reduce((sum, batch) => sum + batch.total, 0);
|
|
60928
|
+
const passed = batches.reduce((sum, batch) => sum + batch.passed, 0);
|
|
60929
|
+
const failed = batches.reduce((sum, batch) => sum + batch.failed, 0);
|
|
60930
|
+
const dryRun = options.dryRun === true;
|
|
60931
|
+
return {
|
|
60932
|
+
status: dryRun ? "dry-run" : failed > 0 || stoppedEarly ? "failed" : "passed",
|
|
60933
|
+
workers,
|
|
60934
|
+
matched: matchedWorkflows.length,
|
|
60935
|
+
batchSize,
|
|
60936
|
+
batchStart,
|
|
60937
|
+
batchEnd,
|
|
60938
|
+
totalBatches,
|
|
60939
|
+
stoppedEarly,
|
|
60940
|
+
total,
|
|
60941
|
+
passed,
|
|
60942
|
+
failed,
|
|
60943
|
+
batches
|
|
60944
|
+
};
|
|
60945
|
+
}
|
|
60879
60946
|
function groupWorkflowsByProvider(workflows) {
|
|
60880
60947
|
const byProvider = new Map;
|
|
60881
60948
|
for (const workflow of workflows) {
|
|
@@ -95624,7 +95691,7 @@ import chalk6 from "chalk";
|
|
|
95624
95691
|
// package.json
|
|
95625
95692
|
var package_default = {
|
|
95626
95693
|
name: "@hasna/testers",
|
|
95627
|
-
version: "0.0.
|
|
95694
|
+
version: "0.0.58",
|
|
95628
95695
|
description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
|
|
95629
95696
|
type: "module",
|
|
95630
95697
|
main: "dist/index.js",
|
|
@@ -102409,10 +102476,9 @@ workflowCmd.command("run <id>").description("Run a saved testing workflow").requ
|
|
|
102409
102476
|
workflowCmd.command("fanout [ids...]").description("Run multiple saved sandbox workflows concurrently").requiredOption("-u, --url <url>", "Target URL").option("--project <id>", "Project ID").option("--tag <tag>", "Workflow scenario tag filter (repeatable)", (val, acc) => {
|
|
102410
102477
|
acc.push(val);
|
|
102411
102478
|
return acc;
|
|
102412
|
-
}, []).option("--all", "Include disabled workflows when selecting by project/tag", false).option("--workers <n>", "Concurrent sandboxes, 1-12 (default: 6)", "6").option("--batch-size <n>", "Limit this run to a batch of selected workflows").option("--batch <n>", "1-based batch number to run with --batch-size").option("--offset <n>", "0-based selected-workflow offset for staged fanout").option("-m, --model <model>", "AI model").option("--headed", "Run headed", false).option("--parallel <n>", "Parallel browser workers inside each sandbox").option("--timeout <ms>", "Override workflow timeout").option("--dry-run", "Print resolved sandbox plans without spawning sandboxes", false).option("--json", "Output as JSON", false).action(async (ids, opts) => {
|
|
102479
|
+
}, []).option("--all", "Include disabled workflows when selecting by project/tag", false).option("--workers <n>", "Concurrent sandboxes, 1-12 (default: 6)", "6").option("--batch-size <n>", "Limit this run to a batch of selected workflows").option("--batch <n>", "1-based batch number to run with --batch-size").option("--offset <n>", "0-based selected-workflow offset for staged fanout").option("--all-batches", "Run all selected workflow batches sequentially with --batch-size", false).option("--from-batch <n>", "First batch to run when using --all-batches").option("--to-batch <n>", "Last batch to run when using --all-batches").option("--continue-on-failure", "Continue later batches after a failed batch", false).option("-m, --model <model>", "AI model").option("--headed", "Run headed", false).option("--parallel <n>", "Parallel browser workers inside each sandbox").option("--timeout <ms>", "Override workflow timeout").option("--dry-run", "Print resolved sandbox plans without spawning sandboxes", false).option("--json", "Output as JSON", false).action(async (ids, opts) => {
|
|
102413
102480
|
try {
|
|
102414
|
-
const
|
|
102415
|
-
const result = await runWorkflowFanout2({
|
|
102481
|
+
const fanoutOptions = {
|
|
102416
102482
|
workflowIds: ids,
|
|
102417
102483
|
projectId: opts.project ? resolveProject2(opts.project) : undefined,
|
|
102418
102484
|
tags: opts.tag,
|
|
@@ -102421,13 +102487,47 @@ workflowCmd.command("fanout [ids...]").description("Run multiple saved sandbox w
|
|
|
102421
102487
|
batchSize: opts.batchSize ? parseInt(opts.batchSize, 10) : undefined,
|
|
102422
102488
|
batch: opts.batch ? parseInt(opts.batch, 10) : undefined,
|
|
102423
102489
|
offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
|
|
102490
|
+
batchStart: opts.fromBatch ? parseInt(opts.fromBatch, 10) : undefined,
|
|
102491
|
+
batchEnd: opts.toBatch ? parseInt(opts.toBatch, 10) : undefined,
|
|
102492
|
+
continueOnFailure: opts.continueOnFailure,
|
|
102424
102493
|
url: opts.url,
|
|
102425
102494
|
model: opts.model,
|
|
102426
102495
|
headed: opts.headed,
|
|
102427
102496
|
parallel: opts.parallel ? parseInt(opts.parallel, 10) : undefined,
|
|
102428
102497
|
timeout: opts.timeout ? parseInt(opts.timeout, 10) : undefined,
|
|
102429
102498
|
dryRun: opts.dryRun
|
|
102430
|
-
}
|
|
102499
|
+
};
|
|
102500
|
+
const runAllBatches = opts.allBatches || opts.fromBatch !== undefined || opts.toBatch !== undefined;
|
|
102501
|
+
if (runAllBatches) {
|
|
102502
|
+
const { runWorkflowFanoutBatches: runWorkflowFanoutBatches2 } = await Promise.resolve().then(() => (init_workflow_fanout(), exports_workflow_fanout));
|
|
102503
|
+
const result2 = await runWorkflowFanoutBatches2(fanoutOptions);
|
|
102504
|
+
if (opts.json || opts.dryRun) {
|
|
102505
|
+
log(JSON.stringify(result2, null, 2));
|
|
102506
|
+
} else {
|
|
102507
|
+
const status = result2.status === "passed" ? chalk6.green("passed") : chalk6.red("failed");
|
|
102508
|
+
const stop = result2.stoppedEarly ? chalk6.yellow(" stopped early") : "";
|
|
102509
|
+
log(chalk6.bold(`Sandbox workflow fanout batches ${status}: ${result2.passed}/${result2.total} passed across ${result2.batches.length} batch(es)${stop}`));
|
|
102510
|
+
log(chalk6.dim(`Selected ${result2.matched} workflow(s), batch size ${result2.batchSize}, running batch ${result2.batchStart}-${result2.batchEnd}/${result2.totalBatches} with ${result2.workers} worker(s).`));
|
|
102511
|
+
for (const batch of result2.batches) {
|
|
102512
|
+
const batchStatus = batch.status === "passed" ? chalk6.green(batch.status) : batch.status === "dry-run" ? chalk6.yellow(batch.status) : chalk6.red(batch.status);
|
|
102513
|
+
const batchNumber = batch.selection.batch ?? "?";
|
|
102514
|
+
log(` ${batchStatus} batch ${batchNumber}/${batch.selection.totalBatches ?? result2.totalBatches}: ${batch.passed}/${batch.total} passed`);
|
|
102515
|
+
const failedItems = batch.items.filter((item) => item.status === "failed").slice(0, 5);
|
|
102516
|
+
for (const item of failedItems) {
|
|
102517
|
+
const error40 = item.error ? chalk6.dim(` ${item.error}`) : "";
|
|
102518
|
+
log(` ${chalk6.red("failed")} ${item.workflowName}${error40}`);
|
|
102519
|
+
}
|
|
102520
|
+
if (batch.items.filter((item) => item.status === "failed").length > failedItems.length) {
|
|
102521
|
+
log(chalk6.dim(` ... ${batch.items.filter((item) => item.status === "failed").length - failedItems.length} more failure(s)`));
|
|
102522
|
+
}
|
|
102523
|
+
}
|
|
102524
|
+
}
|
|
102525
|
+
if (result2.status === "failed")
|
|
102526
|
+
process.exit(1);
|
|
102527
|
+
return;
|
|
102528
|
+
}
|
|
102529
|
+
const { runWorkflowFanout: runWorkflowFanout2 } = await Promise.resolve().then(() => (init_workflow_fanout(), exports_workflow_fanout));
|
|
102530
|
+
const result = await runWorkflowFanout2(fanoutOptions);
|
|
102431
102531
|
if (opts.json || opts.dryRun) {
|
|
102432
102532
|
log(JSON.stringify(result, null, 2));
|
|
102433
102533
|
} else {
|
|
@@ -9,6 +9,9 @@ export interface WorkflowFanoutOptions extends WorkflowRunOptions {
|
|
|
9
9
|
batchSize?: number;
|
|
10
10
|
batch?: number;
|
|
11
11
|
offset?: number;
|
|
12
|
+
batchStart?: number;
|
|
13
|
+
batchEnd?: number;
|
|
14
|
+
continueOnFailure?: boolean;
|
|
12
15
|
}
|
|
13
16
|
export interface WorkflowFanoutItem {
|
|
14
17
|
workflowId: string;
|
|
@@ -32,6 +35,20 @@ export interface WorkflowFanoutResult {
|
|
|
32
35
|
items: WorkflowFanoutItem[];
|
|
33
36
|
preflight?: WorkflowFanoutPreflightResult;
|
|
34
37
|
}
|
|
38
|
+
export interface WorkflowFanoutBatchesResult {
|
|
39
|
+
status: "passed" | "failed" | "dry-run";
|
|
40
|
+
workers: number;
|
|
41
|
+
matched: number;
|
|
42
|
+
batchSize: number;
|
|
43
|
+
batchStart: number;
|
|
44
|
+
batchEnd: number;
|
|
45
|
+
totalBatches: number;
|
|
46
|
+
stoppedEarly: boolean;
|
|
47
|
+
total: number;
|
|
48
|
+
passed: number;
|
|
49
|
+
failed: number;
|
|
50
|
+
batches: WorkflowFanoutResult[];
|
|
51
|
+
}
|
|
35
52
|
export interface WorkflowFanoutDependencies extends WorkflowRunnerDependencies {
|
|
36
53
|
runTestingWorkflow?: typeof runTestingWorkflow;
|
|
37
54
|
preflight?: (workflows: TestingWorkflow[]) => WorkflowFanoutPreflightResult | Promise<WorkflowFanoutPreflightResult>;
|
|
@@ -71,8 +88,15 @@ export declare function resolveWorkflowFanoutBatch(workflows: TestingWorkflow[],
|
|
|
71
88
|
workflows: TestingWorkflow[];
|
|
72
89
|
selection: WorkflowFanoutSelection;
|
|
73
90
|
};
|
|
91
|
+
export declare function resolveWorkflowFanoutBatchRange(matched: number, options: Pick<WorkflowFanoutOptions, "batchSize" | "batchStart" | "batchEnd">): {
|
|
92
|
+
batchSize: number;
|
|
93
|
+
batchStart: number;
|
|
94
|
+
batchEnd: number;
|
|
95
|
+
totalBatches: number;
|
|
96
|
+
};
|
|
74
97
|
export declare function resolveWorkflowFanoutSelection(options: Pick<WorkflowFanoutOptions, "workflowIds" | "projectId" | "tags" | "includeDisabled">): TestingWorkflow[];
|
|
75
98
|
export declare function checkWorkflowFanoutReadiness(workflows: TestingWorkflow[], dependencies?: WorkflowFanoutPreflightDependencies): Promise<WorkflowFanoutPreflightResult>;
|
|
76
99
|
export declare function runWorkflowFanout(options: WorkflowFanoutOptions, dependencies?: WorkflowFanoutDependencies): Promise<WorkflowFanoutResult>;
|
|
100
|
+
export declare function runWorkflowFanoutBatches(options: WorkflowFanoutOptions, dependencies?: WorkflowFanoutDependencies): Promise<WorkflowFanoutBatchesResult>;
|
|
77
101
|
export {};
|
|
78
102
|
//# sourceMappingURL=workflow-fanout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-fanout.d.ts","sourceRoot":"","sources":["../../src/lib/workflow-fanout.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAEpH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB;IAC/D,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"workflow-fanout.d.ts","sourceRoot":"","sources":["../../src/lib/workflow-fanout.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -52,7 +52,7 @@ var package_default;
|
|
|
52
52
|
var init_package = __esm(() => {
|
|
53
53
|
package_default = {
|
|
54
54
|
name: "@hasna/testers",
|
|
55
|
-
version: "0.0.
|
|
55
|
+
version: "0.0.58",
|
|
56
56
|
description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
|
|
57
57
|
type: "module",
|
|
58
58
|
main: "dist/index.js",
|
package/dist/server/index.js
CHANGED
|
@@ -47090,7 +47090,7 @@ import { join as join14 } from "path";
|
|
|
47090
47090
|
// package.json
|
|
47091
47091
|
var package_default = {
|
|
47092
47092
|
name: "@hasna/testers",
|
|
47093
|
-
version: "0.0.
|
|
47093
|
+
version: "0.0.58",
|
|
47094
47094
|
description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
|
|
47095
47095
|
type: "module",
|
|
47096
47096
|
main: "dist/index.js",
|