@testingbot/cli 1.0.8 → 1.1.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.
@@ -15,8 +15,12 @@ export interface XCUITestRunInfo {
15
15
  version?: string;
16
16
  };
17
17
  environment?: XCUITestRunEnvironment;
18
- success: number;
18
+ success: number | boolean;
19
19
  report?: string;
20
+ test?: {
21
+ sessionId?: string;
22
+ environment?: XCUITestRunEnvironment;
23
+ };
20
24
  }
21
25
  export interface XCUITestStatusResponse {
22
26
  runs: XCUITestRunInfo[];
@@ -1 +1 @@
1
- {"version":3,"file":"xcuitest.d.ts","sourceRoot":"","sources":["../../src/providers/xcuitest.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,4BAA4B,CAAC;AAEzD,OAAO,WAAW,MAAM,uBAAuB,CAAC;AAQhD,OAAO,YAAY,MAAM,iBAAiB,CAAC;AAI3C,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAChD,YAAY,EAAE;QACZ,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,WAAW,CAAC,EAAE,sBAAsB,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,eAAe,EAAE,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,eAAe,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,YAAY,CAAC,eAAe,CAAC;IACjE,SAAS,CAAC,QAAQ,CAAC,GAAG,yDACkC;IAExD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,oBAAoB,CAAS;gBAElB,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe;YAIvD,QAAQ;IAuCT,GAAG,IAAI,OAAO,CAAC,cAAc,CAAC;YA6G7B,SAAS;YAcT,aAAa;YAab,QAAQ;YA0DR,SAAS;YA4BT,iBAAiB;IA8F/B,OAAO,CAAC,gBAAgB;IAwCxB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,aAAa;YAkBP,YAAY;IA2D1B,OAAO,CAAC,qBAAqB;IA6C7B,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,mBAAmB;CAa5B"}
1
+ {"version":3,"file":"xcuitest.d.ts","sourceRoot":"","sources":["../../src/providers/xcuitest.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,4BAA4B,CAAC;AAEzD,OAAO,WAAW,MAAM,uBAAuB,CAAC;AAQhD,OAAO,YAAY,MAAM,iBAAiB,CAAC;AAI3C,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAChD,YAAY,EAAE;QACZ,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,WAAW,CAAC,EAAE,sBAAsB,CAAC;IAErC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAIhB,IAAI,CAAC,EAAE;QACL,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,sBAAsB,CAAC;KACtC,CAAC;CACH;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,eAAe,EAAE,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,eAAe,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,YAAY,CAAC,eAAe,CAAC;IACjE,SAAS,CAAC,QAAQ,CAAC,GAAG,yDACkC;IAExD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,oBAAoB,CAAS;gBAElB,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe;YAIvD,QAAQ;IAuCT,GAAG,IAAI,OAAO,CAAC,cAAc,CAAC;YA6G7B,SAAS;YAcT,aAAa;YAab,QAAQ;YA0DR,SAAS;YAkCT,iBAAiB;IA2G/B,OAAO,CAAC,gBAAgB;IAwCxB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,aAAa;YAkBP,YAAY;IA4D1B,OAAO,CAAC,qBAAqB;IA6C7B,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,mBAAmB;CAa5B"}
@@ -223,6 +223,9 @@ class XCUITest extends base_provider_1.default {
223
223
  // Check for version update notification
224
224
  const latestVersion = response.headers?.['x-testingbotctl-version'];
225
225
  utils_1.default.checkForUpdate(latestVersion);
226
+ if (this.options.debug) {
227
+ logger_1.default.debug(`API response: ${JSON.stringify(response.data, null, 2)}`);
228
+ }
226
229
  return response.data;
227
230
  });
228
231
  }
@@ -258,7 +261,7 @@ class XCUITest extends base_provider_1.default {
258
261
  if (!this.options.quiet) {
259
262
  this.spinner.stop();
260
263
  for (const run of status.runs) {
261
- const passed = run.success === 1;
264
+ const passed = this.isRunSuccessful(run.success);
262
265
  const symbol = passed ? picocolors_1.default.green('✔') : picocolors_1.default.red('✘');
263
266
  const statusText = passed
264
267
  ? picocolors_1.default.green('Test completed successfully')
@@ -266,7 +269,7 @@ class XCUITest extends base_provider_1.default {
266
269
  console.log(` ${symbol} Run ${run.id} ${picocolors_1.default.dim(`(${this.getRunDisplayName(run)})`)}: ${statusText}`);
267
270
  }
268
271
  }
269
- const allSucceeded = status.runs.every((run) => run.success === 1);
272
+ const allSucceeded = status.runs.every((run) => this.isRunSuccessful(run.success));
270
273
  if (allSucceeded) {
271
274
  (0, terminal_title_1.setTitle)('xcuitest · ✔ passed');
272
275
  if (!this.options.quiet) {
@@ -274,11 +277,19 @@ class XCUITest extends base_provider_1.default {
274
277
  }
275
278
  }
276
279
  else {
277
- const failedRuns = status.runs.filter((run) => run.success !== 1);
280
+ const failedRuns = status.runs.filter((run) => !this.isRunSuccessful(run.success));
278
281
  (0, terminal_title_1.setTitle)(`xcuitest · ✘ ${failedRuns.length} failed`);
279
282
  logger_1.default.error(`${failedRuns.length} test run(s) failed:`);
280
283
  for (const run of failedRuns) {
281
- logger_1.default.error(` - Run ${run.id} (${this.getRunDisplayName(run)}): ${run.report || 'No report available'}`);
284
+ // The status payload does not carry a report field (reports are
285
+ // fetched separately via --report). Surface the session id so the
286
+ // run can be located on the TestingBot dashboard.
287
+ const sessionId = run.test?.sessionId;
288
+ const detail = run.report ||
289
+ (sessionId
290
+ ? `session ${sessionId}`
291
+ : 'see the TestingBot dashboard for details');
292
+ logger_1.default.error(` - Run ${run.id} (${this.getRunDisplayName(run)}): ${detail}`);
282
293
  }
283
294
  }
284
295
  // Fetch reports if requested
@@ -362,9 +373,11 @@ class XCUITest extends base_provider_1.default {
362
373
  }
363
374
  for (const run of runs) {
364
375
  try {
365
- const endpoint = reportFormat === 'junit'
366
- ? `${this.URL}/${this.appId}/${run.id}/junit_report`
367
- : `${this.URL}/${this.appId}/${run.id}/html_report`;
376
+ // Both endpoints return a JSON envelope ({ junit_report } /
377
+ // { html_report }) keyed by the report format, matching the Maestro
378
+ // per-run report endpoints.
379
+ const reportKey = reportFormat === 'junit' ? 'junit_report' : 'html_report';
380
+ const endpoint = `${this.URL}/${this.appId}/${run.id}/${reportKey}`;
368
381
  const response = await axios_1.default.get(endpoint, {
369
382
  headers: {
370
383
  'User-Agent': utils_1.default.getUserAgent(),
@@ -373,21 +386,20 @@ class XCUITest extends base_provider_1.default {
373
386
  username: this.credentials.userName,
374
387
  password: this.credentials.accessKey,
375
388
  },
376
- responseType: reportFormat === 'html' ? 'arraybuffer' : 'text',
377
389
  timeout: constants_1.HTTP.TIMEOUT_MS,
378
390
  });
379
391
  // Check for version update notification
380
392
  const latestVersion = response.headers?.['x-testingbotctl-version'];
381
393
  utils_1.default.checkForUpdate(latestVersion);
382
- const reportContent = response.data;
394
+ const reportContent = response.data?.[reportKey];
383
395
  if (!reportContent) {
384
- logger_1.default.error(`No report content received for run ${run.id}`);
396
+ logger_1.default.error(`No ${reportFormat} report found for run ${run.id}`);
385
397
  continue;
386
398
  }
387
399
  const extension = reportFormat === 'junit' ? 'xml' : 'html';
388
400
  const fileName = `xcuitest_report_${this.appId}_${run.id}.${extension}`;
389
401
  const filePath = node_path_1.default.join(outputDir, fileName);
390
- await node_fs_1.default.promises.writeFile(filePath, reportContent);
402
+ await node_fs_1.default.promises.writeFile(filePath, reportContent, 'utf-8');
391
403
  if (!this.options.quiet) {
392
404
  logger_1.default.info(` Saved report: ${filePath}`);
393
405
  }
package/dist/upload.d.ts CHANGED
@@ -12,6 +12,7 @@ export interface UploadOptions {
12
12
  }
13
13
  export interface UploadResult {
14
14
  id: number;
15
+ app_url?: string;
15
16
  }
16
17
  export default class Upload {
17
18
  upload(options: UploadOptions): Promise<UploadResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../src/upload.ts"],"names":[],"mappings":"AAMA,OAAO,WAAW,MAAM,sBAAsB,CAAC;AAK/C,MAAM,MAAM,WAAW,GACnB,yCAAyC,GACzC,0BAA0B,GAC1B,iBAAiB,CAAC;AAEtB,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,CAAC,OAAO,OAAO,MAAM;IACZ,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAkJlE,OAAO,CAAC,eAAe;IAuCvB;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;OAEG;IACH,OAAO,CAAC,cAAc;YAOR,YAAY;IAQ1B;;;OAGG;YACW,iBAAiB;IAqB/B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAuB3B;;;OAGG;IACU,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAUlE"}
1
+ {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../src/upload.ts"],"names":[],"mappings":"AAMA,OAAO,WAAW,MAAM,sBAAsB,CAAC;AAK/C,MAAM,MAAM,WAAW,GACnB,yCAAyC,GACzC,0BAA0B,GAC1B,iBAAiB,CAAC;AAEtB,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,CAAC,OAAO,OAAO,MAAM;IACZ,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IAuJlE,OAAO,CAAC,eAAe;IAuCvB;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;OAEG;IACH,OAAO,CAAC,cAAc;YAOR,YAAY;IAQ1B;;;OAGG;YACW,iBAAiB;IAqB/B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAuB3B;;;OAGG;IACU,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAUlE"}
package/dist/upload.js CHANGED
@@ -96,7 +96,12 @@ class Upload {
96
96
  console.log(` ${fileName}: done (${this.formatFileSize(totalSize)})`);
97
97
  }
98
98
  }
99
- return { id: result.id };
99
+ return {
100
+ id: result.id,
101
+ ...(typeof result.app_url === 'string'
102
+ ? { app_url: result.app_url }
103
+ : {}),
104
+ };
100
105
  }
101
106
  else {
102
107
  if (showProgress) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testingbot/cli",
3
- "version": "1.0.8",
3
+ "version": "1.1.0",
4
4
  "description": "CLI tool to run Espresso, XCUITest and Maestro tests on TestingBot's cloud infrastructure",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -61,6 +61,9 @@
61
61
  "testingbot-tunnel-launcher": "^1.1.18",
62
62
  "tracer": "^1.3.0"
63
63
  },
64
+ "overrides": {
65
+ "brace-expansion@^5.0.0": "5.0.6"
66
+ },
64
67
  "devDependencies": {
65
68
  "@eslint/js": "^10.0.1",
66
69
  "@tsconfig/node20": "^20.1.8",