@qawolf/cli 1.28.0 → 1.29.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/dist/cli.js CHANGED
@@ -21213,7 +21213,7 @@ function startUpdateCheck(deps) {
21213
21213
  // package.json
21214
21214
  var package_default = {
21215
21215
  name: "@qawolf/cli",
21216
- version: "1.28.0",
21216
+ version: "1.29.0",
21217
21217
  description: "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
21218
21218
  keywords: [
21219
21219
  "automation",
@@ -33913,27 +33913,50 @@ async function handleRunnerInspect(ctx, options, deps) {
33913
33913
  }
33914
33914
 
33915
33915
  // src/core/interactiveRunner/inspectMobileRequest.ts
33916
+ var blankInspectMobileFlags = {
33917
+ context: undefined,
33918
+ partial: undefined,
33919
+ selector: undefined,
33920
+ strategy: undefined,
33921
+ text: undefined,
33922
+ x: undefined,
33923
+ y: undefined
33924
+ };
33916
33925
  function toNumber(value) {
33917
33926
  return value.trim() === "" ? Number.NaN : Number(value);
33918
33927
  }
33919
- function buildInspectMobileRequest(what, flags) {
33920
- if (flags.by === "point" && (flags.text !== undefined || flags.partial !== undefined)) {
33921
- return {
33922
- error: "--by point matches by pixel, so --text/--partial would be ignored rather than searching by text. Pass --by text instead, or drop --text/--partial.",
33923
- ok: false
33924
- };
33928
+ var groupsOf = (flags) => ({
33929
+ point: flags.x !== undefined || flags.y !== undefined,
33930
+ selector: flags.selector !== undefined || flags.strategy !== undefined,
33931
+ text: flags.text !== undefined || flags.partial !== undefined
33932
+ });
33933
+ function describeGroup(group) {
33934
+ switch (group) {
33935
+ case "point":
33936
+ return "--x/--y";
33937
+ case "selector":
33938
+ return "--selector/--strategy";
33939
+ case "text":
33940
+ return "--text/--partial";
33925
33941
  }
33926
- if (flags.by === "text" && (flags.x !== undefined || flags.y !== undefined)) {
33942
+ }
33943
+ function buildInspectMobileRequest(what, flags) {
33944
+ const groups = groupsOf(flags);
33945
+ const present = ["point", "text", "selector"].filter((group) => groups[group]);
33946
+ if (present.length > 1) {
33927
33947
  return {
33928
- error: "--by text matches by text, so --x/--y would be ignored rather than matching a point. Pass --by point instead, or drop --x/--y.",
33948
+ error: `${describeGroup(present[0])} and ${describeGroup(present[1])} were both passed, but elements are found by a point, by text, or by a selector — never more than one at once. Drop all but one of them.`,
33929
33949
  ok: false
33930
33950
  };
33931
33951
  }
33952
+ const by = present[0];
33932
33953
  const candidate = {
33933
33954
  what,
33934
- ...flags.by === undefined ? {} : { by: flags.by },
33955
+ ...by === undefined ? {} : { by },
33935
33956
  ...flags.context === undefined ? {} : { context: flags.context },
33936
33957
  ...flags.partial === undefined ? {} : { partial: flags.partial },
33958
+ ...flags.selector === undefined ? {} : { selector: flags.selector },
33959
+ ...flags.strategy === undefined ? {} : { strategy: flags.strategy },
33937
33960
  ...flags.text === undefined ? {} : { text: flags.text },
33938
33961
  ...flags.x === undefined ? {} : { x: toNumber(flags.x) },
33939
33962
  ...flags.y === undefined ? {} : { y: toNumber(flags.y) }
@@ -34041,46 +34064,26 @@ async function handleRunnerInspectMobile(ctx, options, deps) {
34041
34064
  // src/commands/runner/inspectMobile.register.ts
34042
34065
  function registerRunnerInspectMobileCommands(inspect, signals) {
34043
34066
  declareCommandKind(inspect.command("session"), "read").description("Print the Appium session's status: ready, or why not").option("--runner <id>", runnerFlagDescription).action((opts, command) => withAuthContext(signals, (ctx) => handleRunnerInspectMobile(ctx, {
34044
- flags: {
34045
- by: undefined,
34046
- context: undefined,
34047
- partial: undefined,
34048
- text: undefined,
34049
- x: undefined,
34050
- y: undefined
34051
- },
34067
+ flags: blankInspectMobileFlags,
34052
34068
  runner: opts.runner,
34053
34069
  what: "session"
34054
34070
  }, runnerDeps(ctx)))(opts, command));
34055
34071
  declareCommandKind(inspect.command("contexts"), "read").description("List the WebView contexts available, and which is current").option("--runner <id>", runnerFlagDescription).action((opts, command) => withAuthContext(signals, (ctx) => handleRunnerInspectMobile(ctx, {
34056
- flags: {
34057
- by: undefined,
34058
- context: undefined,
34059
- partial: undefined,
34060
- text: undefined,
34061
- x: undefined,
34062
- y: undefined
34063
- },
34072
+ flags: blankInspectMobileFlags,
34064
34073
  runner: opts.runner,
34065
34074
  what: "contexts"
34066
34075
  }, runnerDeps(ctx)))(opts, command));
34067
34076
  declareCommandKind(inspect.command("page-source"), "read").description("Print the current context's page source, as a tree").option("--context <name>", "Read this context instead of the current one").option("--runner <id>", runnerFlagDescription).action((opts, command) => withAuthContext(signals, (ctx) => handleRunnerInspectMobile(ctx, {
34068
- flags: {
34069
- by: undefined,
34070
- context: opts.context,
34071
- partial: undefined,
34072
- text: undefined,
34073
- x: undefined,
34074
- y: undefined
34075
- },
34077
+ flags: { ...blankInspectMobileFlags, context: opts.context },
34076
34078
  runner: opts.runner,
34077
34079
  what: "page"
34078
34080
  }, runnerDeps(ctx)))(opts, command));
34079
- declareCommandKind(inspect.command("elements"), "read").description("Find elements at a screen point, or elements carrying some text").requiredOption("--by <by>", "point or text").option("--context <name>", "Read this context instead of the current one").option("--partial", "text: match text containing this, rather than exactly this").option("--runner <id>", runnerFlagDescription).option("--text <text>", "text: the text to match").option("--x <pixels>", "point: whole pixels on the device's own screen").option("--y <pixels>", "point: whole pixels on the device's own screen").action((opts, command) => withAuthContext(signals, (ctx) => handleRunnerInspectMobile(ctx, {
34081
+ declareCommandKind(inspect.command("elements"), "read").description("Find elements at a screen point, carrying some text, or matching a selector").option("--context <name>", "Read this context instead of the current one").option("--partial", "text: match text containing this, rather than exactly this").option("--runner <id>", runnerFlagDescription).option("--selector <selector>", "Resolved the same way a screen object's own selector is").option("--strategy <strategy>", "selector: xpath, ios-predicate, or shadow (defaults to xpath)").option("--text <text>", "text: the text to match").option("--x <pixels>", "point: whole pixels on the device's own screen").option("--y <pixels>", "point: whole pixels on the device's own screen").action((opts, command) => withAuthContext(signals, (ctx) => handleRunnerInspectMobile(ctx, {
34080
34082
  flags: {
34081
- by: opts.by,
34082
34083
  context: opts.context,
34083
34084
  partial: opts.partial,
34085
+ selector: opts.selector,
34086
+ strategy: opts.strategy,
34084
34087
  text: opts.text,
34085
34088
  x: opts.x,
34086
34089
  y: opts.y
@@ -34099,8 +34102,9 @@ Examples:
34099
34102
  $ qawolf runner inspect session
34100
34103
  $ qawolf runner inspect contexts
34101
34104
  $ qawolf runner inspect page-source --context WEBVIEW_1
34102
- $ qawolf runner inspect elements --by point --x 200 --y 400
34103
- $ qawolf runner inspect elements --by text --text "Sign in" --partial`;
34105
+ $ qawolf runner inspect elements --x 200 --y 400
34106
+ $ qawolf runner inspect elements --text "Sign in" --partial
34107
+ $ qawolf runner inspect elements --selector "//android.widget.Button[@text='Sign in']"`;
34104
34108
  function registerRunnerInspectCommands(runner, signals) {
34105
34109
  const inspect = runner.command("inspect").description("Read one thing off a runner's live page (browser) or Appium session (mobile)").addHelpText("after", inspectExamples);
34106
34110
  declareCommandKind(inspect.command("element-html"), "read").description("Print the HTML of the first element a selector matches").requiredOption("--selector <selector>", "Playwright selector to inspect").option("--runner <id>", runnerFlagDescription).action((opts, command) => withAuthContext(signals, (ctx) => handleRunnerInspect(ctx, {
@@ -35438,4 +35442,4 @@ createProgram({ signals }).parseAsync().catch(() => {
35438
35442
  process.exitCode = 1;
35439
35443
  }).finally(() => exitWhenIdle(typeof process.exitCode === "number" ? process.exitCode : 0));
35440
35444
 
35441
- //# debugId=AAB38BDE68A61B2564756E2164756E21
35445
+ //# debugId=424C032AEE2722C964756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qawolf/cli",
3
- "version": "1.28.0",
3
+ "version": "1.29.0",
4
4
  "description": "Run and manage QA Wolf flows from the terminal, CI, or an AI agent",
5
5
  "keywords": [
6
6
  "automation",
@@ -179,7 +179,7 @@ that `url`; never guess a route and never send a repository link in its place.
179
179
  | `qawolf runner import-package` | write | Install a package into a runner's live run, so a snippet or a selection can import it |
180
180
  | `qawolf runner inspect contexts` | read | List the WebView contexts available, and which is current |
181
181
  | `qawolf runner inspect element-html` | read | Print the HTML of the first element a selector matches |
182
- | `qawolf runner inspect elements` | read | Find elements at a screen point, or elements carrying some text |
182
+ | `qawolf runner inspect elements` | read | Find elements at a screen point, carrying some text, or matching a selector |
183
183
  | `qawolf runner inspect page-html` | read | Print the page's HTML, simplified for a model to read |
184
184
  | `qawolf runner inspect page-source` | read | Print the current context's page source, as a tree |
185
185
  | `qawolf runner inspect session` | read | Print the Appium session's status: ready, or why not |
@@ -232,8 +232,10 @@ qawolf runner inspect session
232
232
  qawolf runner inspect contexts
233
233
  qawolf runner inspect page-source
234
234
  qawolf runner inspect page-source --context WEBVIEW_1 # a specific context, not the current one
235
- qawolf runner inspect elements --by point --x 240 --y 480
236
- qawolf runner inspect elements --by text --text "Sign in" --partial
235
+ qawolf runner inspect elements --x 240 --y 480
236
+ qawolf runner inspect elements --text "Sign in" --partial
237
+ qawolf runner inspect elements --selector "//android.widget.Button[@text='Sign in']"
238
+ qawolf runner inspect elements --selector "@label == 'Sign in'" --strategy ios-predicate
237
239
  ```
238
240
 
239
241
  `session` prints one summary line — ready, or why not — because that line is
@@ -253,15 +255,21 @@ runner yet — run a flow that opens one, then inspect again; `screen-not-ready`
253
255
  exits `4` and means the session exists but did not answer this instant, or more
254
256
  than one is somehow live — retry once, and relaunch the runner if it persists.
255
257
 
256
- `elements` takes one of two ways to search, chosen with `--by`: `point` needs
257
- whole-pixel `--x`/`--y` on the device's own screen, the same coordinates a
258
- screenshot is measured in; `text` needs `--text` and matches it exactly unless
259
- `--partial` is passed. The two do not mix — `--by point` with `--text` set, or
260
- `--by text` with `--x`/`--y` set, is refused before a runner is addressed
261
- rather than silently searching by the one it picked, since the schema itself
262
- just strips whichever field the chosen `by` does not define. `--context` on
263
- `page-source` or `elements` reads a context other than the current one —
264
- useful once `contexts` has told you which are available.
258
+ `elements` takes one of three ways to search: whole-pixel `--x`/`--y` on the
259
+ device's own screen, the same coordinates a screenshot is measured in;
260
+ `--text`, which matches exactly unless `--partial` is passed; or `--selector`,
261
+ resolved the same way a screen object's own selector is, with `--strategy`
262
+ naming how (`xpath`, `ios-predicate` or `shadow`; defaults to `xpath`). Prefer
263
+ `--selector` when checking a selector you are about to write: it answers what
264
+ that exact string resolves to, where `--text`/`--x`/`--y` only approximate it.
265
+ The three do not mix — passing flags from more than one at once is refused
266
+ before a runner is addressed rather than silently searching by whichever one
267
+ it picked. An unparseable selector answers `invalid-selector`, exit `2`,
268
+ distinctly from a selector that parsed fine but matched nothing, which answers
269
+ an empty `matches` list, exit `0` — the same distinction `highlight-selector`
270
+ draws on a browser runner. `--context` on `page-source` or `elements` reads a
271
+ context other than the current one — useful once `contexts` has told you which
272
+ are available.
265
273
 
266
274
  A browser runner answers `runner-is-not-mobile` to all four, exit `2`, since
267
275
  retrying never helps: launch with `--name android` or `--name ios` instead.