@hasna/testers 0.0.54 → 0.0.55

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
@@ -57,12 +57,16 @@ testers inventory next /path/to/app \
57
57
  --action-workflow-grouping route \
58
58
  --sandbox-provider e2b \
59
59
  --sandbox-sync rsync \
60
+ --sandbox-app-source /path/to/app \
61
+ --sandbox-app-start-command "bun install && bun dev --hostname 0.0.0.0" \
62
+ --sandbox-app-url http://127.0.0.1:3000 \
63
+ --sandbox-app-wait-url http://127.0.0.1:3000/health \
60
64
  --sandbox-env-optional OPENAI_API_KEY
61
65
 
62
66
  testers workflow fanout --project alumia --tag next-action --workers 6 --url https://preview.example.com --dry-run
63
67
  ```
64
68
 
65
- Use `--action-workflow-grouping route` for route-specific workflows or `--action-workflow-grouping area-kind` for broader workflows such as commerce buttons or admin API methods.
69
+ Use `--action-workflow-grouping route` for route-specific workflows or `--action-workflow-grouping 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.
66
70
 
67
71
  ### Common Flags
68
72
 
package/dist/cli/index.js CHANGED
@@ -95551,7 +95551,7 @@ import chalk6 from "chalk";
95551
95551
  // package.json
95552
95552
  var package_default = {
95553
95553
  name: "@hasna/testers",
95554
- version: "0.0.54",
95554
+ version: "0.0.55",
95555
95555
  description: "AI-powered QA testing CLI \u2014 spawns cheap AI agents to test web apps with headless browsers",
95556
95556
  type: "module",
95557
95557
  main: "dist/index.js",
@@ -101176,14 +101176,17 @@ Imported ${imported} scenarios from API spec:`));
101176
101176
  }
101177
101177
  });
101178
101178
  var inventoryCmd = program2.command("inventory").description("Discover source-derived app route/action inventories");
101179
- inventoryCmd.command("next [root]").description("Discover Next.js app routes and optionally import route coverage scenarios").option("--app-dir <path>", "Next.js app directory relative to root (default: packages/web/app or app)").option("--project <id>", "Project ID").option("--no-pages", "Do not include page.tsx/page.ts routes").option("--no-api", "Do not include route.ts/route.js API routes").option("--limit <n>", "Limit discovered routes").option("--create-scenarios", "Upsert source-derived route coverage scenarios", false).option("--create-action-scenarios", "Upsert one source-derived scenario per discovered page/API action", false).option("--create-workflows", "Upsert grouped workflows by area and route kind", false).option("--create-action-workflows", "Upsert action-focused workflows for discovered action scenarios", false).option("--action-workflow-grouping <mode>", "Action workflow grouping: route or area-kind", "route").option("--workflow-target <target>", "Workflow execution target: local or sandbox", "sandbox").option("--sandbox-provider <provider>", "Sandbox provider for created workflows", "e2b").option("--sandbox-cleanup <mode>", "Sandbox cleanup mode: delete, stop, or keep", "delete").option("--sandbox-sync <strategy>", "Sandbox upload sync strategy: rsync or archive", "rsync").option("--sandbox-env-optional <name>", "Optional sandbox env var; forwards host NAME only when set (repeatable)", (val, acc) => {
101179
+ inventoryCmd.command("next [root]").description("Discover Next.js app routes and optionally import route coverage scenarios").option("--app-dir <path>", "Next.js app directory relative to root (default: packages/web/app or app)").option("--project <id>", "Project ID").option("--no-pages", "Do not include page.tsx/page.ts routes").option("--no-api", "Do not include route.ts/route.js API routes").option("--limit <n>", "Limit discovered routes").option("--create-scenarios", "Upsert source-derived route coverage scenarios", false).option("--create-action-scenarios", "Upsert one source-derived scenario per discovered page/API action", false).option("--create-workflows", "Upsert grouped workflows by area and route kind", false).option("--create-action-workflows", "Upsert action-focused workflows for discovered action scenarios", false).option("--action-workflow-grouping <mode>", "Action workflow grouping: route or area-kind", "route").option("--workflow-target <target>", "Workflow execution target: local or sandbox", "sandbox").option("--sandbox-provider <provider>", "Sandbox provider for created workflows", "e2b").option("--sandbox-image <image>", "Sandbox image/template for created workflows").option("--sandbox-remote-dir <path>", "Remote working directory for sandbox runs").option("--sandbox-cleanup <mode>", "Sandbox cleanup mode: delete, stop, or keep", "delete").option("--sandbox-sync <strategy>", "Sandbox upload sync strategy: rsync or archive", "rsync").option("--sandbox-setup-command <command>", "Shell command to run before testers in the sandbox").option("--sandbox-package <spec>", "Package spec to execute in the sandbox", "@hasna/testers").option("--sandbox-env <assignment>", "Sandbox env var; KEY forwards host KEY, KEY=value stores value (repeatable)", (val, acc) => {
101180
101180
  acc.push(val);
101181
101181
  return acc;
101182
- }, []).option("--timeout <ms>", "Workflow timeout in milliseconds").option("--json", "Output as JSON", false).action(async (root, opts) => {
101182
+ }, []).option("--sandbox-env-optional <name>", "Optional sandbox env var; forwards host NAME only when set (repeatable)", (val, acc) => {
101183
+ acc.push(val);
101184
+ return acc;
101185
+ }, []).option("--sandbox-app-source <path>", "Local app source directory to upload into the sandbox").option("--sandbox-app-remote-dir <path>", "Remote app directory inside the sandbox (default: <sandbox-remote-dir>/app)").option("--sandbox-app-start-command <command>", "Shell command to start the app before testers runs").option("--sandbox-app-url <url>", "URL testers should target inside the sandbox after the app starts").option("--sandbox-app-wait-url <url>", "URL to poll before starting testers (defaults to --sandbox-app-url)").option("--sandbox-app-wait-timeout <ms>", "App readiness wait timeout in milliseconds").option("--timeout <ms>", "Workflow timeout in milliseconds").option("--json", "Output as JSON", false).action(async (root, opts) => {
101183
101186
  try {
101184
101187
  const { importNextRouteInventory: importNextRouteInventory2 } = await Promise.resolve().then(() => (init_next_route_inventory(), exports_next_route_inventory));
101185
101188
  const projectId = resolveProject2(opts.project) ?? undefined;
101186
- const env = parseSandboxEnv(undefined, opts.sandboxEnvOptional);
101189
+ const env = parseSandboxEnv(opts.sandboxEnv, opts.sandboxEnvOptional);
101187
101190
  if (!["route", "area-kind"].includes(opts.actionWorkflowGrouping)) {
101188
101191
  throw new Error("--action-workflow-grouping must be route or area-kind");
101189
101192
  }
@@ -101204,10 +101207,20 @@ inventoryCmd.command("next [root]").description("Discover Next.js app routes and
101204
101207
  workflowExecution: {
101205
101208
  target: opts.workflowTarget,
101206
101209
  provider: opts.workflowTarget === "sandbox" ? opts.sandboxProvider : undefined,
101210
+ sandboxImage: opts.sandboxImage,
101211
+ sandboxRemoteDir: opts.sandboxRemoteDir,
101207
101212
  sandboxCleanup: opts.sandboxCleanup,
101208
101213
  sandboxSyncStrategy: opts.sandboxSync,
101214
+ setupCommand: opts.sandboxSetupCommand,
101215
+ packageSpec: opts.sandboxPackage,
101209
101216
  timeoutMs: opts.timeout ? parseInt(opts.timeout, 10) : undefined,
101210
- env
101217
+ env,
101218
+ appSourceDir: opts.sandboxAppSource,
101219
+ appRemoteDir: opts.sandboxAppRemoteDir,
101220
+ appStartCommand: opts.sandboxAppStartCommand,
101221
+ appUrl: opts.sandboxAppUrl,
101222
+ appWaitUrl: opts.sandboxAppWaitUrl,
101223
+ appWaitTimeoutMs: opts.sandboxAppWaitTimeout ? parseInt(opts.sandboxAppWaitTimeout, 10) : undefined
101211
101224
  }
101212
101225
  });
101213
101226
  if (opts.json) {
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.54",
55
+ version: "0.0.55",
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.54",
47093
+ version: "0.0.55",
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.54",
3
+ "version": "0.0.55",
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",