@swmansion/argent 0.18.1-next.15 → 0.18.1-next.16

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-cmds.mjs CHANGED
@@ -9179,8 +9179,10 @@ function renderUnderStepLine(s, n2, text2) {
9179
9179
  function renderSummary(report, opts = {}) {
9180
9180
  const warnings = report.steps.filter((s) => s.warning).length;
9181
9181
  const warningsNote = warnings ? `, ${warnings} warning${warnings === 1 ? "" : "s"}` : "";
9182
- const where = opts.withDevice ? ` on ${report.device}` : "";
9183
- return `${report.ok ? "PASS" : "FAIL"}${where} \u2014 ${report.passed} passed, ${report.failed} failed, ${report.errored} errored, ${report.skipped} skipped${warningsNote}`;
9182
+ const where = opts.withDevice && report.device ? ` on ${report.device}` : "";
9183
+ const nothingCounted = report.ok && report.passed + report.failed + report.errored + report.skipped === 0;
9184
+ const note = nothingCounted ? " (no test steps)" : "";
9185
+ return `${report.ok ? "PASS" : "FAIL"}${where} \u2014 ${report.passed} passed, ${report.failed} failed, ${report.errored} errored, ${report.skipped} skipped${warningsNote}${note}`;
9184
9186
  }
9185
9187
  function renderArtifactLines(report) {
9186
9188
  const lines = [];
@@ -9248,7 +9250,7 @@ function exitAfterFlush(code, streams = [process.stdout, process.stderr]) {
9248
9250
  }
9249
9251
  function renderReport(report) {
9250
9252
  const lines = [];
9251
- lines.push(`Flow "${report.flow}" on ${report.device}`);
9253
+ lines.push(`Flow "${report.flow}"${report.device ? ` on ${report.device}` : ""}`);
9252
9254
  if (report.executionPrerequisite) {
9253
9255
  lines.push(` assumes: ${report.executionPrerequisite}`);
9254
9256
  }
@@ -19293,9 +19293,11 @@ async function flowRunToMcpContent(result, ctx) {
19293
19293
  }
19294
19294
  }
19295
19295
  if (result.ok !== void 0) {
19296
+ const counted = (result.passed ?? 0) + (result.failed ?? 0) + (result.errored ?? 0) + (result.skipped ?? 0);
19297
+ const note = result.ok && counted === 0 ? " (no test steps)" : "";
19296
19298
  blocks.push({
19297
19299
  type: "text",
19298
- text: `${result.ok ? "PASS" : "FAIL"} \u2014 ${result.passed ?? 0} passed, ${result.failed ?? 0} failed, ${result.errored ?? 0} errored, ${result.skipped ?? 0} skipped`
19300
+ text: `${result.ok ? "PASS" : "FAIL"} \u2014 ${result.passed ?? 0} passed, ${result.failed ?? 0} failed, ${result.errored ?? 0} errored, ${result.skipped ?? 0} skipped${note}`
19299
19301
  });
19300
19302
  } else {
19301
19303
  blocks.push({ type: "text", text: `Flow "${result.flow}" complete.` });
@@ -148170,6 +148170,7 @@ var path31 = __toESM(require("node:path"));
148170
148170
  // ../tool-server/src/tools/flows/flow-device.ts
148171
148171
  init_src();
148172
148172
  var DEVICE_BIND_KEYS = ["udid", "device_id"];
148173
+ var DEVICE_ARG_KEYS = [...DEVICE_BIND_KEYS, "device"];
148173
148174
  function deviceEntryId(d) {
148174
148175
  if (d.platform === "ios") return d.udid;
148175
148176
  if (d.platform === "chromium") return d.id;
@@ -148225,6 +148226,43 @@ function stripDeviceKeys(args) {
148225
148226
  for (const k of DEVICE_BIND_KEYS) delete out[k];
148226
148227
  return out;
148227
148228
  }
148229
+ function stepRequiresDevice(registry2, step) {
148230
+ switch (step.kind) {
148231
+ case "echo":
148232
+ case "wait":
148233
+ return false;
148234
+ case "tool":
148235
+ return toolRequiresDevice(registry2, step.name);
148236
+ case "when":
148237
+ case "run":
148238
+ case "launch":
148239
+ case "tap":
148240
+ case "long-press":
148241
+ case "type":
148242
+ case "await":
148243
+ case "assert":
148244
+ case "scroll-to":
148245
+ case "pinch":
148246
+ case "rotate":
148247
+ case "snapshot":
148248
+ return true;
148249
+ default: {
148250
+ const unclassified = step;
148251
+ void unclassified;
148252
+ return true;
148253
+ }
148254
+ }
148255
+ }
148256
+ function flowRequiresDevice(registry2, steps) {
148257
+ return steps.some((step) => stepRequiresDevice(registry2, step));
148258
+ }
148259
+ function toolRequiresDevice(registry2, toolName) {
148260
+ const toolDef = registry2.getTool(toolName);
148261
+ if (!toolDef) return true;
148262
+ const props = toolDef.inputSchema?.properties;
148263
+ if (!props) return false;
148264
+ return DEVICE_ARG_KEYS.some((k) => k in props);
148265
+ }
148228
148266
  function bindDeviceArgs(registry2, toolName, deviceId, args) {
148229
148267
  const toolDef = registry2.getTool(toolName);
148230
148268
  const props = toolDef?.inputSchema?.properties;
@@ -151834,7 +151872,8 @@ async function treeSourceGate(registry2, device, bundleId, signal) {
151834
151872
  return null;
151835
151873
  }
151836
151874
  async function runLaunch(state3, app) {
151837
- const { registry: registry2, device, signal } = state3;
151875
+ const env = deviceEnv(state3);
151876
+ const { registry: registry2, device, signal } = env;
151838
151877
  if (device.platform === "chromium") {
151839
151878
  if (state3.chromiumLaunched) {
151840
151879
  return {
@@ -151871,7 +151910,7 @@ async function runLaunch(state3, app) {
151871
151910
  };
151872
151911
  }
151873
151912
  try {
151874
- await invokeOnDevice(state3, "restart-app", { bundleId });
151913
+ await invokeOnDevice(env, "restart-app", { bundleId });
151875
151914
  } catch (err) {
151876
151915
  if (signal?.aborted) return ABORTED_OUTCOME;
151877
151916
  return { ok: false, reason: `restart-app failed: ${errMsg2(err)}` };
@@ -151882,6 +151921,12 @@ async function runLaunch(state3, app) {
151882
151921
  if (gate) return { ok: false, reason: gate };
151883
151922
  return { ok: true };
151884
151923
  }
151924
+ function deviceEnv(state3) {
151925
+ if (!state3.device) {
151926
+ throw new Error("internal: a step that acts on a device ran in a flow resolved as device-free");
151927
+ }
151928
+ return { ...state3, device: state3.device };
151929
+ }
151885
151930
  function createRunFlowTool(registry2) {
151886
151931
  return {
151887
151932
  id: "flow-execute",
@@ -151940,11 +151985,13 @@ returns a notice with the prerequisite instead of running.`,
151940
151985
  }
151941
151986
  const resolved = await resolveRunDevice(registry2, ctx, flow, params, flowsDir);
151942
151987
  const device = resolved.device;
151943
- const env = { registry: registry2, ctx, device, signal };
151944
- const statusBarPinned = await pinStatusBar(device);
151945
- if (device.platform === "chromium") await frontChromiumPage(registry2, device);
151988
+ const statusBarPinned = device !== null && await pinStatusBar(device);
151989
+ if (device?.platform === "chromium") await frontChromiumPage(registry2, device);
151946
151990
  const state3 = {
151947
- ...env,
151991
+ registry: registry2,
151992
+ ctx,
151993
+ device,
151994
+ signal,
151948
151995
  flowsDir,
151949
151996
  topFlowName: params.name,
151950
151997
  updateBaselines: Boolean(params.updateBaselines),
@@ -151964,10 +152011,16 @@ returns a notice with the prerequisite instead of running.`,
151964
152011
  });
151965
152012
  } finally {
151966
152013
  aborted2 = state3.signal?.aborted === true;
151967
- if (state3.pinned) await restoreStatusBar(device);
152014
+ if (state3.pinned && device) await restoreStatusBar(device);
151968
152015
  if (resolved.booted) await teardownBootedChromium(registry2, resolved.booted);
151969
152016
  }
151970
- return summarize(params.name, device.id, flow.executionPrerequisite, state3.reports, aborted2);
152017
+ return summarize(
152018
+ params.name,
152019
+ device?.id ?? "",
152020
+ flow.executionPrerequisite,
152021
+ state3.reports,
152022
+ aborted2
152023
+ );
151971
152024
  }
151972
152025
  };
151973
152026
  }
@@ -151978,6 +152031,9 @@ async function resolveRunDevice(registry2, ctx, flow, params, flowDir) {
151978
152031
  const booted = await bootChromiumForFlow(spec, flowDir);
151979
152032
  return { device: resolveDevice(booted.deviceId), booted };
151980
152033
  }
152034
+ if (!flowRequiresDevice(registry2, flow.steps)) {
152035
+ return { device: null, booted: null };
152036
+ }
151981
152037
  }
151982
152038
  const device = await resolveFlowDevice(registry2, ctx, {
151983
152039
  device: params.device,
@@ -152133,6 +152189,20 @@ async function execSteps(state3, steps, scope) {
152133
152189
  if (step.kind === "when") reportBlockSkipped(state3, step.steps, childScope(scope));
152134
152190
  continue;
152135
152191
  }
152192
+ if (!state3.device && stepRequiresDevice(state3.registry, step)) {
152193
+ state3.stopped = true;
152194
+ pushReport(state3, {
152195
+ index,
152196
+ kind: step.kind,
152197
+ status: "error",
152198
+ flow: scope.flow,
152199
+ target: stepTarget(step),
152200
+ ...depthOf(scope),
152201
+ reason: `step needs a device but the flow was resolved as device-free \u2014 pass an explicit device`
152202
+ });
152203
+ if (step.kind === "when") reportBlockSkipped(state3, step.steps, childScope(scope));
152204
+ continue;
152205
+ }
152136
152206
  if (state3.signal?.aborted) {
152137
152207
  state3.stopped = true;
152138
152208
  pushReport(state3, {
@@ -152193,10 +152263,11 @@ async function execWhenStep(state3, step, scope) {
152193
152263
  const inner = childScope(scope);
152194
152264
  let met;
152195
152265
  if (step.condition.kind === "platform") {
152196
- const platform = state3.device.platform === "ios-remote" ? "ios" : state3.device.platform;
152266
+ const guardEnv = deviceEnv(state3);
152267
+ const platform = guardEnv.device.platform === "ios-remote" ? "ios" : guardEnv.device.platform;
152197
152268
  met = platform === step.condition.platform;
152198
152269
  } else {
152199
- const probe3 = await probeWhenCondition(state3, step.condition);
152270
+ const probe3 = await probeWhenCondition(deviceEnv(state3), step.condition);
152200
152271
  if (probe3.aborted) {
152201
152272
  pushReport(state3, { ...marker, status: "skip", reason: "run aborted" });
152202
152273
  reportBlockSkipped(state3, step.steps, inner, "run aborted");
@@ -152288,7 +152359,7 @@ async function execLeafStep(state3, step, index, scope) {
152288
152359
  case "pinch":
152289
152360
  case "rotate": {
152290
152361
  try {
152291
- const r = await runDirective(state3, step);
152362
+ const r = await runDirective(deviceEnv(state3), step);
152292
152363
  if (r.aborted) return { ...base, status: "skip", reason: r.reason };
152293
152364
  return { ...base, status: r.ok ? "pass" : "fail", reason: r.reason };
152294
152365
  } catch (err) {
@@ -152303,7 +152374,7 @@ async function execLeafStep(state3, step, index, scope) {
152303
152374
  }
152304
152375
  case "snapshot": {
152305
152376
  try {
152306
- const r = await runSnapshot(state3, {
152377
+ const r = await runSnapshot(deviceEnv(state3), {
152307
152378
  flowsDir: state3.flowsDir,
152308
152379
  flowName: state3.topFlowName,
152309
152380
  name: step.name,
@@ -152323,7 +152394,7 @@ async function execLeafStep(state3, step, index, scope) {
152323
152394
  }
152324
152395
  }
152325
152396
  case "tool": {
152326
- const args = bindDeviceArgs(registry2, step.name, device.id, step.args);
152397
+ const args = bindDeviceArgs(registry2, step.name, device?.id ?? "", step.args);
152327
152398
  const outputHint = registry2.getTool(step.name)?.outputHint;
152328
152399
  if (step.delayMs && !await sleepOrAbort(step.delayMs, signal)) {
152329
152400
  return { ...base, status: "skip", tool: step.name, reason: "run aborted during delay" };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swmansion/argent",
3
- "version": "0.18.1-next.15",
3
+ "version": "0.18.1-next.16",
4
4
  "mcpName": "io.github.software-mansion/argent",
5
5
  "description": "MCP server for iOS Simulator and Android Emulator control",
6
6
  "license": "Apache-2.0",