@hasna/testers 0.0.56 → 0.0.57

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 CHANGED
@@ -39,9 +39,10 @@ testers workflow create "Projects CRUD" \
39
39
 
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
+ testers workflow fanout --project alumia --tag action-specific --workers 6 --batch-size 12 --batch 1 --url https://preview.example.com
42
43
  ```
43
44
 
44
- `--workers` is bounded to 1-12 concurrent sandboxes. 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.
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.
45
46
 
46
47
  ### Next.js Route and Action Inventory
47
48
 
@@ -63,7 +64,7 @@ testers inventory next /path/to/app \
63
64
  --sandbox-app-wait-url http://127.0.0.1:3000/health \
64
65
  --sandbox-env-optional OPENAI_API_KEY
65
66
 
66
- testers workflow fanout --project alumia --tag action-specific --workers 6 --url https://preview.example.com --dry-run
67
+ testers workflow fanout --project alumia --tag action-specific --workers 6 --batch-size 12 --batch 1 --url https://preview.example.com --dry-run
67
68
  ```
68
69
 
69
70
  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
@@ -60628,6 +60628,7 @@ var exports_workflow_fanout = {};
60628
60628
  __export(exports_workflow_fanout, {
60629
60629
  runWorkflowFanout: () => runWorkflowFanout,
60630
60630
  resolveWorkflowFanoutSelection: () => resolveWorkflowFanoutSelection,
60631
+ resolveWorkflowFanoutBatch: () => resolveWorkflowFanoutBatch,
60631
60632
  normalizeFanoutWorkerCount: () => normalizeFanoutWorkerCount,
60632
60633
  checkWorkflowFanoutReadiness: () => checkWorkflowFanoutReadiness
60633
60634
  });
@@ -60643,6 +60644,33 @@ function normalizeFanoutWorkerCount(value) {
60643
60644
  }
60644
60645
  return workers;
60645
60646
  }
60647
+ function resolveWorkflowFanoutBatch(workflows, options = {}) {
60648
+ const batchSize = normalizeOptionalPositiveInteger(options.batchSize, "workflow fanout batch size");
60649
+ const batch = normalizeOptionalPositiveInteger(options.batch, "workflow fanout batch");
60650
+ const offset = normalizeOptionalNonNegativeInteger(options.offset, "workflow fanout offset");
60651
+ if (batch !== undefined && offset !== undefined) {
60652
+ throw new Error("workflow fanout batch and offset cannot both be set");
60653
+ }
60654
+ if (batch !== undefined && batchSize === undefined) {
60655
+ throw new Error("workflow fanout batch requires batch size");
60656
+ }
60657
+ const resolvedOffset = batch !== undefined && batchSize !== undefined ? (batch - 1) * batchSize : offset ?? 0;
60658
+ const limit = batchSize;
60659
+ const selected = workflows.slice(resolvedOffset, limit === undefined ? undefined : resolvedOffset + limit);
60660
+ if (selected.length === 0) {
60661
+ throw new Error(`No testing workflows matched the fanout batch selection (matched ${workflows.length}, offset ${resolvedOffset})`);
60662
+ }
60663
+ return {
60664
+ workflows: selected,
60665
+ selection: {
60666
+ matched: workflows.length,
60667
+ offset: resolvedOffset,
60668
+ ...limit !== undefined ? { limit } : {},
60669
+ ...batch !== undefined ? { batch } : {},
60670
+ ...batchSize !== undefined ? { batchSize, totalBatches: Math.ceil(workflows.length / batchSize) } : {}
60671
+ }
60672
+ };
60673
+ }
60646
60674
  function resolveWorkflowFanoutSelection(options) {
60647
60675
  const ids = splitWorkflowIds(options.workflowIds);
60648
60676
  const workflows = ids.length > 0 ? ids.map((id) => {
@@ -60762,7 +60790,8 @@ async function mapWithConcurrency(items, limit, worker) {
60762
60790
  }
60763
60791
  async function runWorkflowFanout(options, dependencies = {}) {
60764
60792
  const workers = normalizeFanoutWorkerCount(options.workers);
60765
- const workflows = resolveWorkflowFanoutSelection(options);
60793
+ const matchedWorkflows = resolveWorkflowFanoutSelection(options);
60794
+ const { workflows, selection } = resolveWorkflowFanoutBatch(matchedWorkflows, options);
60766
60795
  const {
60767
60796
  runTestingWorkflow: runOne = runTestingWorkflow,
60768
60797
  preflight: preflightOverride,
@@ -60783,6 +60812,7 @@ async function runWorkflowFanout(options, dependencies = {}) {
60783
60812
  return {
60784
60813
  status: "failed",
60785
60814
  workers,
60815
+ selection,
60786
60816
  total: workflows.length,
60787
60817
  passed: 0,
60788
60818
  failed: workflows.length,
@@ -60838,6 +60868,7 @@ async function runWorkflowFanout(options, dependencies = {}) {
60838
60868
  return {
60839
60869
  status: dryRun ? "dry-run" : failed > 0 ? "failed" : "passed",
60840
60870
  workers,
60871
+ selection,
60841
60872
  total: items.length,
60842
60873
  passed,
60843
60874
  failed,
@@ -60871,6 +60902,24 @@ function defaultCommandExists(command) {
60871
60902
  const result = spawnSync2(command, ["--version"], { encoding: "utf8" });
60872
60903
  return !result.error && result.status === 0;
60873
60904
  }
60905
+ function normalizeOptionalPositiveInteger(value, label) {
60906
+ if (value === undefined)
60907
+ return;
60908
+ const normalized = Math.floor(value);
60909
+ if (!Number.isFinite(normalized) || normalized < 1) {
60910
+ throw new Error(`${label} must be a positive integer`);
60911
+ }
60912
+ return normalized;
60913
+ }
60914
+ function normalizeOptionalNonNegativeInteger(value, label) {
60915
+ if (value === undefined)
60916
+ return;
60917
+ const normalized = Math.floor(value);
60918
+ if (!Number.isFinite(normalized) || normalized < 0) {
60919
+ throw new Error(`${label} must be a non-negative integer`);
60920
+ }
60921
+ return normalized;
60922
+ }
60874
60923
  function collectMissingSandboxEnvRefs(workflows, env, credentialResolver) {
60875
60924
  const requiredMissing = [];
60876
60925
  const optionalMissing = [];
@@ -95575,7 +95624,7 @@ import chalk6 from "chalk";
95575
95624
  // package.json
95576
95625
  var package_default = {
95577
95626
  name: "@hasna/testers",
95578
- version: "0.0.56",
95627
+ version: "0.0.57",
95579
95628
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
95580
95629
  type: "module",
95581
95630
  main: "dist/index.js",
@@ -102360,7 +102409,7 @@ workflowCmd.command("run <id>").description("Run a saved testing workflow").requ
102360
102409
  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) => {
102361
102410
  acc.push(val);
102362
102411
  return acc;
102363
- }, []).option("--all", "Include disabled workflows when selecting by project/tag", false).option("--workers <n>", "Concurrent sandboxes, 1-12 (default: 6)", "6").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) => {
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) => {
102364
102413
  try {
102365
102414
  const { runWorkflowFanout: runWorkflowFanout2 } = await Promise.resolve().then(() => (init_workflow_fanout(), exports_workflow_fanout));
102366
102415
  const result = await runWorkflowFanout2({
@@ -102369,6 +102418,9 @@ workflowCmd.command("fanout [ids...]").description("Run multiple saved sandbox w
102369
102418
  tags: opts.tag,
102370
102419
  includeDisabled: opts.all,
102371
102420
  workers: opts.workers ? parseInt(opts.workers, 10) : undefined,
102421
+ batchSize: opts.batchSize ? parseInt(opts.batchSize, 10) : undefined,
102422
+ batch: opts.batch ? parseInt(opts.batch, 10) : undefined,
102423
+ offset: opts.offset ? parseInt(opts.offset, 10) : undefined,
102372
102424
  url: opts.url,
102373
102425
  model: opts.model,
102374
102426
  headed: opts.headed,
@@ -102392,6 +102444,10 @@ workflowCmd.command("fanout [ids...]").description("Run multiple saved sandbox w
102392
102444
  log(` ${chalk6.yellow("warning")} ${check2.message}`);
102393
102445
  }
102394
102446
  }
102447
+ if (result.selection.matched !== result.total) {
102448
+ const batch = result.selection.batch !== undefined && result.selection.totalBatches !== undefined ? ` batch ${result.selection.batch}/${result.selection.totalBatches}` : "";
102449
+ log(chalk6.dim(`Selected ${result.total}/${result.selection.matched} workflow(s) from offset ${result.selection.offset}${batch}.`));
102450
+ }
102395
102451
  const status = result.status === "passed" ? chalk6.green("passed") : chalk6.red("failed");
102396
102452
  log(chalk6.bold(`Sandbox workflow fanout ${status}: ${result.passed}/${result.total} passed with ${result.workers} worker(s)`));
102397
102453
  for (const item of result.items) {
@@ -6,6 +6,9 @@ export interface WorkflowFanoutOptions extends WorkflowRunOptions {
6
6
  tags?: string[];
7
7
  includeDisabled?: boolean;
8
8
  workers?: number;
9
+ batchSize?: number;
10
+ batch?: number;
11
+ offset?: number;
9
12
  }
10
13
  export interface WorkflowFanoutItem {
11
14
  workflowId: string;
@@ -22,6 +25,7 @@ export interface WorkflowFanoutItem {
22
25
  export interface WorkflowFanoutResult {
23
26
  status: "passed" | "failed" | "dry-run";
24
27
  workers: number;
28
+ selection: WorkflowFanoutSelection;
25
29
  total: number;
26
30
  passed: number;
27
31
  failed: number;
@@ -48,6 +52,14 @@ export interface WorkflowFanoutPreflightResult {
48
52
  ok: boolean;
49
53
  checks: WorkflowFanoutPreflightCheck[];
50
54
  }
55
+ export interface WorkflowFanoutSelection {
56
+ matched: number;
57
+ offset: number;
58
+ limit?: number;
59
+ batch?: number;
60
+ batchSize?: number;
61
+ totalBatches?: number;
62
+ }
51
63
  interface WorkflowFanoutPreflightDependencies {
52
64
  providerApiKeyResolver?: WorkflowFanoutDependencies["providerApiKeyResolver"];
53
65
  commandExists?: WorkflowFanoutDependencies["commandExists"];
@@ -55,6 +67,10 @@ interface WorkflowFanoutPreflightDependencies {
55
67
  env?: Record<string, string | undefined>;
56
68
  }
57
69
  export declare function normalizeFanoutWorkerCount(value: number | undefined): number;
70
+ export declare function resolveWorkflowFanoutBatch(workflows: TestingWorkflow[], options?: Pick<WorkflowFanoutOptions, "batchSize" | "batch" | "offset">): {
71
+ workflows: TestingWorkflow[];
72
+ selection: WorkflowFanoutSelection;
73
+ };
58
74
  export declare function resolveWorkflowFanoutSelection(options: Pick<WorkflowFanoutOptions, "workflowIds" | "projectId" | "tags" | "includeDisabled">): TestingWorkflow[];
59
75
  export declare function checkWorkflowFanoutReadiness(workflows: TestingWorkflow[], dependencies?: WorkflowFanoutPreflightDependencies): Promise<WorkflowFanoutPreflightResult>;
60
76
  export declare function runWorkflowFanout(options: WorkflowFanoutOptions, dependencies?: WorkflowFanoutDependencies): Promise<WorkflowFanoutResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-fanout.d.ts","sourceRoot":"","sources":["../../src/lib/workflow-fanout.ts"],"names":[],"mappings":"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"}
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.56",
55
+ version: "0.0.57",
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",
@@ -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.56",
47093
+ version: "0.0.57",
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",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/testers",
3
- "version": "0.0.56",
3
+ "version": "0.0.57",
4
4
  "description": "AI-powered QA testing CLI — spawns cheap AI agents to test web apps with headless browsers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",