@qawolf/cli 1.13.0 → 1.14.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.
Files changed (2) hide show
  1. package/dist/cli.js +53 -18
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -326186,6 +326186,7 @@ var interactiveRunnerMessages = {
326186
326186
  };
326187
326187
  // src/core/messages/runner.ts
326188
326188
  var maxListedNames = 5;
326189
+ var allowNoMatchHint = "Pass --allow-no-match to exit 0 instead.";
326189
326190
  function listNames(names) {
326190
326191
  const shown = names.slice(0, maxListedNames).join(", ");
326191
326192
  const rest = names.length - maxListedNames;
@@ -326195,6 +326196,10 @@ var runnerMessages = {
326195
326196
  playwrightLoadFailed: (envDir, detail) => packageLoadFailed("Playwright", envDir, detail),
326196
326197
  androidWorkersUnsupported: "Android flows are not yet supported with --workers > 1; rerun Android flows with --workers 1.",
326197
326198
  noFlowsMatched: "No flows matched.",
326199
+ noFlowsMatchedPattern: (pattern) => pattern === undefined ? `No flows found. ${allowNoMatchHint}` : `No flows matched '${pattern}'. ${allowNoMatchHint}`,
326200
+ noFlowsMatchedInEnv: (env, pattern) => pattern === undefined ? `No flows found in env '${env}'. ${allowNoMatchHint}` : `No flows matched '${pattern}' in env '${env}'. ${allowNoMatchHint}`,
326201
+ noTargetedFlows: `No matched flow declares a target. ${allowNoMatchHint}`,
326202
+ noRunnableFlows: `No matched flow has a target the CLI can run locally. ${allowNoMatchHint}`,
326198
326203
  androidBootFailed: "Android boot failed",
326199
326204
  preparingEnvironment: "Preparing environment",
326200
326205
  environmentReady: "Environment ready",
@@ -341006,7 +341011,10 @@ var inlineReasonMaxLength = 200;
341006
341011
  function describeIdentityError(err) {
341007
341012
  if (err.kind === "http") {
341008
341013
  if (err.status === 401 || err.status === 403) {
341009
- return { error: m.identity.invalidOrUnauthorized };
341014
+ return {
341015
+ error: m.identity.invalidOrUnauthorized,
341016
+ ...err.status === 401 ? { exitCode: exitCodes.auth } : {}
341017
+ };
341010
341018
  }
341011
341019
  return {
341012
341020
  error: m.identity.couldNotVerify(parseErrorBody(err.body, inlineReasonMaxLength), err.status)
@@ -341025,7 +341033,11 @@ function describeRequestError(err, baseUrl, noun) {
341025
341033
  const reason = parseErrorBody(err.body);
341026
341034
  const body = reason ? { errorBody: reason } : {};
341027
341035
  if (err.status === 401)
341028
- return { error: m.request.rejected401(noun), ...body };
341036
+ return {
341037
+ error: m.request.rejected401(noun),
341038
+ exitCode: exitCodes.auth,
341039
+ ...body
341040
+ };
341029
341041
  if (err.status === 403)
341030
341042
  return { error: m.request.rejected403(noun), ...body };
341031
341043
  if (err.status === 404)
@@ -341074,7 +341086,11 @@ var sleep = (ms) => setTimeout2(ms);
341074
341086
 
341075
341087
  // src/shell/platform/requestWithRetry.ts
341076
341088
  function failureFields(failure) {
341077
- return failure.errorBody ? { error: failure.error, errorBody: failure.errorBody } : { error: failure.error };
341089
+ return {
341090
+ error: failure.error,
341091
+ ...failure.errorBody ? { errorBody: failure.errorBody } : {},
341092
+ ...failure.exitCode === undefined ? {} : { exitCode: failure.exitCode }
341093
+ };
341078
341094
  }
341079
341095
  async function requestWithRetry(args) {
341080
341096
  const sleep2 = args.sleep ?? sleep;
@@ -345820,7 +345836,7 @@ function startUpdateCheck(deps) {
345820
345836
  // package.json
345821
345837
  var package_default = {
345822
345838
  name: "@qawolf/cli",
345823
- version: "1.13.0",
345839
+ version: "1.14.0",
345824
345840
  description: "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
345825
345841
  keywords: [
345826
345842
  "automation",
@@ -346114,7 +346130,7 @@ async function handleWhoami(ctx, deps = {}) {
346114
346130
  } else {
346115
346131
  ctx.ui.output({ authenticated: false, source: undefined }, authMessages.notAuthenticated);
346116
346132
  }
346117
- return { error: "not authenticated" };
346133
+ return { error: "not authenticated", exitCode: exitCodes.auth };
346118
346134
  }
346119
346135
  const platformClient = (deps.createPlatform ?? createPlatformClient)(resolved.key, {
346120
346136
  baseUrl: ctx.apiBaseUrl,
@@ -346134,7 +346150,10 @@ async function handleWhoami(ctx, deps = {}) {
346134
346150
  valid: false
346135
346151
  }, authMessages.whoami.authFailed(resolved.source, identity.error));
346136
346152
  }
346137
- return { error: "invalid key" };
346153
+ return {
346154
+ error: "invalid key",
346155
+ ...identity.exitCode === undefined ? {} : { exitCode: identity.exitCode }
346156
+ };
346138
346157
  }
346139
346158
  const { value } = identity;
346140
346159
  if ("user" in value) {
@@ -352872,6 +352891,16 @@ async function executeFlows(args) {
352872
352891
  }
352873
352892
  }
352874
352893
 
352894
+ // src/domains/runner/noMatch.ts
352895
+ function noMatchResult(ctx, args) {
352896
+ if (!args.allowNoMatch) {
352897
+ return { error: args.error, exitCode: exitCodes.invalidArgs };
352898
+ }
352899
+ if (args.notice !== undefined)
352900
+ ctx.ui.info(args.notice);
352901
+ return;
352902
+ }
352903
+
352875
352904
  // src/domains/runner/run.ts
352876
352905
  async function flowsRun(ctx, files, flags, deps) {
352877
352906
  const flows = [];
@@ -352907,10 +352936,12 @@ async function flowsRun(ctx, files, flags, deps) {
352907
352936
  }
352908
352937
  flows.sort((a2, b3) => a2.file.localeCompare(b3.file));
352909
352938
  if (flows.length === 0) {
352910
- if (skippedByType.size === 0) {
352911
- ctx.ui.info(runnerMessages.noFlowsMatched);
352912
- }
352913
- return;
352939
+ const skipped = skippedByType.size > 0;
352940
+ return noMatchResult(ctx, {
352941
+ allowNoMatch: flags.allowNoMatch,
352942
+ error: skipped ? runnerMessages.noRunnableFlows : runnerMessages.noTargetedFlows,
352943
+ notice: skipped ? undefined : runnerMessages.noFlowsMatched
352944
+ });
352914
352945
  }
352915
352946
  const webFlows = flows.filter((f3) => f3.kind === "web");
352916
352947
  const browsers = [
@@ -355280,8 +355311,11 @@ async function handleFlowsRun(ctx, pattern, flags, deps) {
355280
355311
  const expandedFiles = await resolvedDeps.expandPatterns(buildPatternArgs(pattern), cwd, ctx.log("flows"));
355281
355312
  ctx.log("flows").debug(`discovered ${pluralize(expandedFiles.length, "flow")}`);
355282
355313
  if (expandedFiles.length === 0) {
355283
- ctx.ui.info(runnerMessages.noFlowsMatched);
355284
- return;
355314
+ return noMatchResult(ctx, {
355315
+ allowNoMatch: flags.allowNoMatch,
355316
+ error: runnerMessages.noFlowsMatchedPattern(pattern),
355317
+ notice: runnerMessages.noFlowsMatched
355318
+ });
355285
355319
  }
355286
355320
  return runStagedFlows({
355287
355321
  ctx,
@@ -355321,10 +355355,11 @@ async function handleHybridFlowsRun(ctx, pattern, flags, deps) {
355321
355355
  return pullResult;
355322
355356
  files = await globFlows();
355323
355357
  if (files.length === 0) {
355324
- return {
355325
- error: pattern !== undefined ? `No flows matched '${pattern}' in env '${flags.env}'` : `No flows found in env '${flags.env}'`,
355326
- exitCode: 2
355327
- };
355358
+ return noMatchResult(ctx, {
355359
+ allowNoMatch: flags.allowNoMatch,
355360
+ error: runnerMessages.noFlowsMatchedInEnv(flags.env, pattern),
355361
+ notice: runnerMessages.noFlowsMatched
355362
+ });
355328
355363
  }
355329
355364
  }
355330
355365
  return runStagedFlows({ ctx, files, flags, envDir, deps: resolvedDeps });
@@ -355348,7 +355383,7 @@ Examples:
355348
355383
  function registerFlowsRunCommand(flows, signals) {
355349
355384
  declareCommandKind(flows.command("run [pattern]"), "local", {
355350
355385
  kindNote: "read with --env"
355351
- }).description("Run flows matching [pattern], or every flow when omitted; with --env, pull missing flows from that QA Wolf environment").option("--retries <n>", "Retry each failing flow up to this many times", parseInteger("--retries", { min: 0 }), 0).option("--bail", "Stop the run after the first failure", false).option("--workers <n>", "Parallel worker count for web flows", parseInteger("--workers", { min: 1 }), 1).option("--timeout <ms>", "Default timeout for actions and assertions, in milliseconds", parseInteger("--timeout", { min: 0 }), 30000).option("--video <mode>", "Record video: on | off | retain-on-failure", parseEnum("--video", videoModes), videoDefault).option("--trace <mode>", "Record Playwright trace: on | off | retain-on-failure", parseEnum("--trace", traceModes), traceDefault).option("--har <mode>", "Record HAR network log: on | off | retain-on-failure", parseEnum("--har", harModes), harDefault).option("--har-content <mode>", "HAR response bodies: omit | full (full uses more memory)", parseEnum("--har-content", harContentModes), harContentDefault).option("--output-dir <path>", "Directory for run artifacts (videos, traces, HAR)", defaultOutputDir).option("--junit [path]", "Write a JUnit XML report (default: <output-dir>/junit-report.xml)").option("--headed", "Show the browser window instead of headless", false).option("--env <env>", "Pull and run a flow from this environment (UUID or slug) if not cached locally").option("--deps <dir>", "Use this prepared dependency directory instead of auto-installing the runtime; or set QAWOLF_RUNTIME_DIR to relocate the managed runtime").option("--no-browser-deps", "Skip installing OS-level browser dependencies (Linux --with-deps, which needs root); requires the system libraries to already be present").addHelpText("after", runExamples).action((pattern, opts, command) => {
355386
+ }).description("Run flows matching [pattern], or every flow when omitted; with --env, pull missing flows from that QA Wolf environment").option("--retries <n>", "Retry each failing flow up to this many times", parseInteger("--retries", { min: 0 }), 0).option("--bail", "Stop the run after the first failure", false).option("--workers <n>", "Parallel worker count for web flows", parseInteger("--workers", { min: 1 }), 1).option("--timeout <ms>", "Default timeout for actions and assertions, in milliseconds", parseInteger("--timeout", { min: 0 }), 30000).option("--video <mode>", "Record video: on | off | retain-on-failure", parseEnum("--video", videoModes), videoDefault).option("--trace <mode>", "Record Playwright trace: on | off | retain-on-failure", parseEnum("--trace", traceModes), traceDefault).option("--har <mode>", "Record HAR network log: on | off | retain-on-failure", parseEnum("--har", harModes), harDefault).option("--har-content <mode>", "HAR response bodies: omit | full (full uses more memory)", parseEnum("--har-content", harContentModes), harContentDefault).option("--output-dir <path>", "Directory for run artifacts (videos, traces, HAR)", defaultOutputDir).option("--junit [path]", "Write a JUnit XML report (default: <output-dir>/junit-report.xml)").option("--headed", "Show the browser window instead of headless", false).option("--env <env>", "Pull and run a flow from this environment (UUID or slug) if not cached locally").option("--deps <dir>", "Use this prepared dependency directory instead of auto-installing the runtime; or set QAWOLF_RUNTIME_DIR to relocate the managed runtime").option("--allow-no-match", "Exit 0 instead of 2 when the pattern selects no runnable flow", false).option("--no-browser-deps", "Skip installing OS-level browser dependencies (Linux --with-deps, which needs root); requires the system libraries to already be present").addHelpText("after", runExamples).action((pattern, opts, command) => {
355352
355387
  if (opts.env !== undefined) {
355353
355388
  return withResolvedEnv(signals, {
355354
355389
  explicit: opts.env,
@@ -358159,4 +358194,4 @@ createProgram({ signals }).parseAsync().catch(() => {
358159
358194
  process.exitCode = 1;
358160
358195
  }).finally(() => flushAndExit(typeof process.exitCode === "number" ? process.exitCode : 0));
358161
358196
 
358162
- //# debugId=23E147B93341D71864756E2164756E21
358197
+ //# debugId=9D7349D928400D0E64756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qawolf/cli",
3
- "version": "1.13.0",
3
+ "version": "1.14.0",
4
4
  "description": "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
5
5
  "keywords": [
6
6
  "automation",