@testrigor/testrigor-cli 1.0.0 → 2.0.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.
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
3
4
  const core_1 = require("@oclif/core");
4
- const Fs = require("@supercharge/fs");
5
- const FormData = require("form-data");
5
+ const fs_1 = tslib_1.__importDefault(require("@supercharge/fs"));
6
+ const fs_2 = require("fs");
6
7
  const listr2_1 = require("listr2");
7
- const node_fetch_commonjs_1 = require("node-fetch-commonjs");
8
8
  const command_base_1 = require("../../command-base");
9
9
  const environments_1 = require("../../config/environments");
10
10
  const chrome_extension_1 = require("../../flags/chrome-extension");
11
11
  const parser_1 = require("../../util/parser");
12
12
  const request_builder_1 = require("../../util/request-builder");
13
- const tunnel_1 = require("../../util/tunnel");
13
+ const tunnel_1 = tslib_1.__importDefault(require("../../util/tunnel"));
14
14
  const certificate_uploader_1 = require("../../util/certificate-uploader");
15
15
  const variable_file_uploader_1 = require("../../util/variable-file-uploader");
16
16
  const variables_path_parser_1 = require("../../util/variables-path-parser");
@@ -31,6 +31,7 @@ const JUNIT_REPORT_STATUS = {
31
31
  FAILED: "JUnit report generation is failed",
32
32
  RUNNING: "JUnit report is still in progress",
33
33
  };
34
+ const FAILED_TO_START_TITLE = "Test suite run failed";
34
35
  class Run extends command_base_1.CommandBase {
35
36
  initializeUrls(flags) {
36
37
  const baseUrlWeb = flags["base-url-web"];
@@ -120,7 +121,7 @@ class Run extends command_base_1.CommandBase {
120
121
  }
121
122
  if (variablesPath) {
122
123
  try {
123
- const file = await Fs.content(variablesPath);
124
+ const file = await fs_1.default.content(variablesPath);
124
125
  const parsed = JSON.parse(file.toString());
125
126
  const { textValues, fileInputs, certInputs } = (0, variables_path_parser_1.parseVariablesJson)(parsed);
126
127
  context.configuration.storedValues = textValues;
@@ -147,7 +148,7 @@ class Run extends command_base_1.CommandBase {
147
148
  context.configuration.baselineMutations = testCases;
148
149
  }
149
150
  }
150
- catch (e) {
151
+ catch {
151
152
  core_1.ux.error("--test-cases-path must be a valid JSON path");
152
153
  }
153
154
  }
@@ -158,7 +159,7 @@ class Run extends command_base_1.CommandBase {
158
159
  context.configuration.ruleMutations = rules;
159
160
  }
160
161
  }
161
- catch (e) {
162
+ catch {
162
163
  core_1.ux.error("--rules-path must be a valid JSON path");
163
164
  }
164
165
  }
@@ -169,7 +170,7 @@ class Run extends command_base_1.CommandBase {
169
170
  context.configuration.settings = settings;
170
171
  }
171
172
  }
172
- catch (e) {
173
+ catch {
173
174
  core_1.ux.error("--settings-path must be a valid JSON/YAML path");
174
175
  }
175
176
  }
@@ -187,7 +188,7 @@ class Run extends command_base_1.CommandBase {
187
188
  Object.assign(context.configuration, localTestNodes);
188
189
  }
189
190
  }
190
- catch (e) {
191
+ catch {
191
192
  core_1.ux.error("--local-test-nodes-path must be a valid JSON/YAML path");
192
193
  }
193
194
  }
@@ -197,12 +198,12 @@ class Run extends command_base_1.CommandBase {
197
198
  delete flags["file-path"];
198
199
  }
199
200
  else {
200
- const fileExists = await Fs.isFile(filePath);
201
+ const fileExists = await fs_1.default.isFile(filePath);
201
202
  if (!fileExists || !(0, utils_1.isValidFileExtensionToUpload)(filePath)) {
202
203
  core_1.ux.error("--file-path must be one of the valid format types: [zip, exe, msi, apk, aab, ipa, app]");
203
204
  }
204
- const fileName = Fs.basename(filePath);
205
- const fileSize = Fs.statSync(filePath).size;
205
+ const fileName = fs_1.default.basename(filePath);
206
+ const fileSize = fs_1.default.statSync(filePath).size;
206
207
  context.fileProperties = { fileName, fileSize };
207
208
  }
208
209
  }
@@ -222,6 +223,11 @@ class Run extends command_base_1.CommandBase {
222
223
  enabled: () => (flags.localhost || !!localTestNodesPath) && context.isMobile,
223
224
  task: (ctx, task) => {
224
225
  task.title = "Starting mobile server";
226
+ // A driver that fails to install is tolerated (xcuitest is useless on
227
+ // Linux, uiautomator2 on a Mac targeting iOS), but losing all of them
228
+ // means the server has nothing to drive - fail there, with the
229
+ // reasons, instead of timing out on the health check 30s later.
230
+ const driverFailures = [];
225
231
  return task.newListr([
226
232
  {
227
233
  task: async (_ctx, subtask) => {
@@ -241,14 +247,22 @@ class Run extends command_base_1.CommandBase {
241
247
  ? `Updating ${driver.name} (${status.version} → ${driver.version})`
242
248
  : `Installing ${driver.name}@${driver.version}`;
243
249
  const err = await (0, appium_1.ensureDriver)(driver.name, driver.version);
244
- subtask.title = err
245
- ? `Driver ${driver.name} skipped — ${err}`
246
- : `Driver ${driver.name}@${driver.version} ready`;
250
+ if (err) {
251
+ driverFailures.push(`${driver.name}@${driver.version}: ${err}`);
252
+ subtask.title = `Driver ${driver.name} skipped — ${err.split("\n")[0]}`;
253
+ }
254
+ else {
255
+ subtask.title = `Driver ${driver.name}@${driver.version} ready`;
256
+ }
247
257
  },
248
258
  rendererOptions: { timer: listr2_1.PRESET_TIMER },
249
259
  })),
250
260
  {
251
261
  task: async (ctx, subtask) => {
262
+ if (driverFailures.length === appium_1.REQUIRED_DRIVERS.length) {
263
+ throw new Error("No mobile driver could be installed, so the mobile server has nothing to run:\n" +
264
+ driverFailures.map((f) => ` - ${f}`).join("\n"));
265
+ }
252
266
  const result = await (0, appium_1.startAppium)();
253
267
  ctx.appiumStartedByUs = !result.alreadyRunning;
254
268
  subtask.title = result.alreadyRunning
@@ -296,90 +310,143 @@ class Run extends command_base_1.CommandBase {
296
310
  },
297
311
  {
298
312
  title: "Running test suite",
299
- task: async (ctx, task) => task.newListr([
300
- {
301
- // Checking last run id
302
- task: async (ctx) => {
303
- let pollBranch = flags.branch;
304
- if (this.isSingleTestCaseExecution(testCaseUuids, flags.branch)) {
305
- pollBranch = `single-test-execution-${testCaseUuids[0]}`;
306
- }
307
- const statusResponse = await this.fetchStatus(testSuiteId, token, pollBranch, ctx.configuration.labels, ctx.configuration.excludedLabels);
308
- context.lastRunId = (0, utils_1.extractRunIdFromDetailsUrl)(statusResponse.detailsUrl);
313
+ task: async (ctx, task) => {
314
+ const steps = task.newListr([
315
+ {
316
+ task: async (ctx) => {
317
+ let pollBranch = flags.branch;
318
+ if (this.isSingleTestCaseExecution(testCaseUuids, flags.branch)) {
319
+ pollBranch = `single-test-execution-${testCaseUuids[0]}`;
320
+ }
321
+ const statusResponse = await this.fetchStatus(testSuiteId, token, pollBranch, ctx.configuration.labels, ctx.configuration.excludedLabels);
322
+ context.lastRunId = (0, utils_1.extractRunIdFromDetailsUrl)(statusResponse.detailsUrl);
323
+ },
324
+ exitOnError: false,
309
325
  },
310
- exitOnError: false,
311
- },
312
- {
313
- title: "Uploading variable files",
314
- enabled: () => !!context.storedValueFileInputs?.length,
315
- task: (ctx) => this.uploadVariableFiles(ctx, testSuiteId, token),
316
- exitOnError: false,
317
- },
318
- {
319
- title: "Uploading client certificates",
320
- enabled: () => !!context.storedValueCertInputs?.length,
321
- task: (ctx, task) => this.uploadClientCertificates(ctx, testSuiteId, token, task),
322
- exitOnError: false,
323
- },
324
- {
325
- enabled: () => !flags["file-path"] && !flags["chrome-extension"],
326
- task: async (ctx) => {
327
- if (flags.url) {
328
- ctx.configuration.url = flags.url;
329
- }
330
- if (flags.branch && flags.commit) {
331
- ctx.configuration.branch = {
332
- name: flags.branch,
333
- commit: flags.commit,
334
- };
335
- }
336
- const response = await this.callRetest(testSuiteId, ctx.configuration, token);
337
- ctx.response = (await response.json());
338
- if (!response.ok) {
339
- const errorMessage = JSON.stringify(ctx.response);
340
- throw new Error(`Test suite failed to start: ${ctx.response?.msg ||
341
- ctx.response?.errName ||
342
- errorMessage}`);
343
- }
344
- if (ctx.response?.taskId) {
345
- task.title = `Running test suite [ ${this.TESTRIGOR_URL}/test-suites/${testSuiteId}/runs/${ctx.response?.taskId} ]`;
346
- }
326
+ {
327
+ title: "Uploading variable files",
328
+ enabled: () => !!context.storedValueFileInputs?.length,
329
+ task: (ctx) => this.uploadVariableFiles(ctx, testSuiteId, token),
330
+ exitOnError: false,
347
331
  },
348
- exitOnError: false,
349
- },
350
- {
351
- title: "Uploading Chrome extension(s)",
352
- enabled: () => !!context.chromeExtensions?.length,
353
- task: async (ctx) => {
354
- if (flags.url) {
355
- ctx.configuration.url = flags.url;
356
- }
357
- if (flags.branch && flags.commit) {
358
- ctx.configuration.branch = {
359
- name: flags.branch,
360
- commit: flags.commit,
361
- };
362
- }
363
- const { form, cleanup } = (0, request_builder_1.buildChromeExtensionFormData)(ctx.chromeExtensions);
364
- form.append("data", JSON.stringify(ctx.configuration));
365
- const controller = new AbortController();
366
- const timeoutId = setTimeout(() => controller.abort(), utils_1.UPLOAD_TIMEOUT_MS);
367
- try {
368
- // Prepare headers
369
- const requestHeaders = {
370
- ...form.getHeaders(),
371
- Accept: "application/json",
372
- "auth-token": token,
373
- };
374
- const response = await (0, node_fetch_commonjs_1.default)(`${this.TESTRIGOR_API2_URL}/apps/${testSuiteId}/retest`, {
332
+ {
333
+ title: "Uploading client certificates",
334
+ enabled: () => !!context.storedValueCertInputs?.length,
335
+ task: (ctx, task) => this.uploadClientCertificates(ctx, testSuiteId, token, task),
336
+ exitOnError: false,
337
+ },
338
+ {
339
+ enabled: () => !flags["file-path"] && !flags["chrome-extension"],
340
+ task: async (ctx) => {
341
+ if (flags.url) {
342
+ ctx.configuration.url = flags.url;
343
+ }
344
+ if (flags.branch && flags.commit) {
345
+ ctx.configuration.branch = {
346
+ name: flags.branch,
347
+ commit: flags.commit,
348
+ };
349
+ }
350
+ const response = await this.callRetest(testSuiteId, ctx.configuration, token);
351
+ ctx.response = (await response.json());
352
+ if (!response.ok) {
353
+ task.title = FAILED_TO_START_TITLE;
354
+ const errorMessage = JSON.stringify(ctx.response);
355
+ throw new Error(`Test suite failed to start: ${ctx.response?.msg ||
356
+ ctx.response?.errName ||
357
+ errorMessage}`);
358
+ }
359
+ if (ctx.response?.taskId) {
360
+ task.title = `Running test suite [ ${this.TESTRIGOR_URL}/test-suites/${testSuiteId}/runs/${ctx.response?.taskId} ]`;
361
+ }
362
+ },
363
+ exitOnError: false,
364
+ },
365
+ {
366
+ title: "Uploading Chrome extension(s)",
367
+ enabled: () => !!context.chromeExtensions?.length,
368
+ task: async (ctx) => {
369
+ if (flags.url) {
370
+ ctx.configuration.url = flags.url;
371
+ }
372
+ if (flags.branch && flags.commit) {
373
+ ctx.configuration.branch = {
374
+ name: flags.branch,
375
+ commit: flags.commit,
376
+ };
377
+ }
378
+ const form = await (0, request_builder_1.buildChromeExtensionFormData)(ctx.chromeExtensions);
379
+ form.append("data", JSON.stringify(ctx.configuration));
380
+ const controller = new AbortController();
381
+ const timeoutId = setTimeout(() => controller.abort(), utils_1.UPLOAD_TIMEOUT_MS);
382
+ try {
383
+ const response = await fetch(`${this.TESTRIGOR_API2_URL}/apps/${testSuiteId}/retest`, {
384
+ method: "POST",
385
+ body: form,
386
+ headers: {
387
+ Accept: "application/json",
388
+ "auth-token": token,
389
+ },
390
+ signal: controller.signal,
391
+ });
392
+ const retestApi2Response = (await response.json());
393
+ if (!response.ok || retestApi2Response.status >= 300) {
394
+ throw new Error(`Chrome extension upload failed: ${retestApi2Response?.message ||
395
+ retestApi2Response?.errors}`);
396
+ }
397
+ ctx.response = {
398
+ result: "ok",
399
+ msg: retestApi2Response.message,
400
+ taskId: retestApi2Response.data?.taskId,
401
+ queueId: retestApi2Response.data?.queueId,
402
+ };
403
+ if (ctx.response?.taskId) {
404
+ task.title = `Running test suite [ ${this.TESTRIGOR_URL}/test-suites/${testSuiteId}/runs/${ctx.response?.taskId} ]`;
405
+ }
406
+ }
407
+ catch (error) {
408
+ if (error.name === "AbortError") {
409
+ throw new Error("Chrome extension upload timed out. Please check your network connection.");
410
+ }
411
+ throw error;
412
+ }
413
+ finally {
414
+ clearTimeout(timeoutId);
415
+ }
416
+ },
417
+ exitOnError: false,
418
+ },
419
+ {
420
+ title: "Uploading file",
421
+ enabled: () => context.fileProperties &&
422
+ context.fileProperties.fileSize < utils_1.MAX_FILE_SIZE_100_MB,
423
+ task: async (ctx) => {
424
+ if (flags.branch && flags.commit) {
425
+ ctx.configuration.branch = {
426
+ name: flags.branch,
427
+ commit: flags.commit,
428
+ };
429
+ }
430
+ if (!flags["file-path"]) {
431
+ throw new Error("file-path is not provided");
432
+ }
433
+ const configuration = ctx.configuration;
434
+ const filePath = flags["file-path"];
435
+ const form = new FormData();
436
+ form.append("file", await (0, fs_2.openAsBlob)(filePath), fs_1.default.basename(filePath));
437
+ form.append("data", JSON.stringify(configuration));
438
+ const response = await fetch(`${this.TESTRIGOR_API2_URL}/apps/${testSuiteId}/retest`, {
375
439
  method: "POST",
376
440
  body: form,
377
- headers: requestHeaders,
378
- signal: controller.signal,
441
+ headers: {
442
+ Accept: "application/json",
443
+ "auth-token": token,
444
+ },
379
445
  });
380
446
  const retestApi2Response = (await response.json());
381
447
  if (!response.ok || retestApi2Response.status >= 300) {
382
- throw new Error(`Chrome extension upload failed: ${retestApi2Response?.message ||
448
+ task.title = FAILED_TO_START_TITLE;
449
+ throw new Error(`Test suite failed to start: ${retestApi2Response?.message ||
383
450
  retestApi2Response?.errors}`);
384
451
  }
385
452
  ctx.response = {
@@ -388,145 +455,101 @@ class Run extends command_base_1.CommandBase {
388
455
  taskId: retestApi2Response.data?.taskId,
389
456
  queueId: retestApi2Response.data?.queueId,
390
457
  };
391
- if (ctx.response?.taskId) {
392
- task.title = `Running test suite [ ${this.TESTRIGOR_URL}/test-suites/${testSuiteId}/runs/${ctx.response?.taskId} ]`;
458
+ },
459
+ exitOnError: false,
460
+ },
461
+ {
462
+ title: "Uploading file (> 100 MB)",
463
+ enabled: () => context.fileProperties &&
464
+ context.fileProperties.fileSize >= utils_1.MAX_FILE_SIZE_100_MB,
465
+ task: async (ctx) => {
466
+ if (flags.branch && flags.commit) {
467
+ ctx.configuration.branch = {
468
+ name: flags.branch,
469
+ commit: flags.commit,
470
+ };
393
471
  }
394
- }
395
- catch (error) {
396
- if (error.name === "AbortError") {
397
- throw new Error("Chrome extension upload timed out. Please check your network connection.");
472
+ if (!flags["file-path"]) {
473
+ throw new Error("file-path is not provided");
398
474
  }
399
- throw error;
400
- }
401
- finally {
402
- clearTimeout(timeoutId);
403
- cleanup();
404
- }
405
- },
406
- exitOnError: false,
407
- },
408
- {
409
- title: "Uploading file",
410
- enabled: () => context.fileProperties &&
411
- context.fileProperties.fileSize < utils_1.MAX_FILE_SIZE_100_MB,
412
- task: async (ctx) => {
413
- if (flags.branch && flags.commit) {
414
- ctx.configuration.branch = {
415
- name: flags.branch,
416
- commit: flags.commit,
417
- };
418
- }
419
- if (!flags["file-path"]) {
420
- throw new Error("file-path is not provided");
421
- }
422
- const configuration = ctx.configuration;
423
- const filePath = flags["file-path"];
424
- const form = new FormData();
425
- form.append("file", Fs.createReadStream(filePath));
426
- form.append("data", JSON.stringify(configuration));
427
- const response = await (0, node_fetch_commonjs_1.default)(`${this.TESTRIGOR_API2_URL}/apps/${testSuiteId}/retest`, {
428
- method: "POST",
429
- body: form,
430
- headers: {
431
- ...form.getHeaders(),
432
- Accept: "application/json",
433
- "auth-token": token,
434
- },
435
- });
436
- const retestApi2Response = (await response.json());
437
- if (!response.ok || retestApi2Response.status >= 300) {
438
- throw new Error(`Test suite failed to start: ${retestApi2Response?.message ||
439
- retestApi2Response?.errors}`);
440
- }
441
- ctx.response = {
442
- result: "ok",
443
- msg: retestApi2Response.message,
444
- taskId: retestApi2Response.data?.taskId,
445
- queueId: retestApi2Response.data?.queueId,
446
- };
475
+ if (!ctx.fileProperties) {
476
+ throw new Error(`Error getting details of file provided by --file-path ${flags["file-path"]}`);
477
+ }
478
+ const configuration = ctx.configuration;
479
+ const filePath = flags["file-path"];
480
+ const response = await this.uploadFile(task, testSuiteId, configuration, filePath, token, ctx.fileProperties);
481
+ ctx.response = (await response.json());
482
+ if (!response.ok) {
483
+ task.title = FAILED_TO_START_TITLE;
484
+ throw new Error(`Test suite failed to start: ${ctx.response?.msg || ctx.response?.errName}`);
485
+ }
486
+ },
487
+ exitOnError: false,
447
488
  },
448
- exitOnError: false,
449
- },
450
- {
451
- title: "Uploading file (> 100 MB)",
452
- enabled: () => context.fileProperties &&
453
- context.fileProperties.fileSize >= utils_1.MAX_FILE_SIZE_100_MB,
454
- task: async (ctx) => {
455
- if (flags.branch && flags.commit) {
456
- ctx.configuration.branch = {
457
- name: flags.branch,
458
- commit: flags.commit,
459
- };
460
- }
461
- if (!flags["file-path"]) {
462
- throw new Error("file-path is not provided");
463
- }
464
- if (!ctx.fileProperties) {
465
- throw new Error(`Error getting details of file provided by --file-path ${flags["file-path"]}`);
466
- }
467
- const configuration = ctx.configuration;
468
- const filePath = flags["file-path"];
469
- const response = await this.uploadFile(task, testSuiteId, configuration, filePath, token, ctx.fileProperties);
470
- ctx.response = (await response.json());
471
- if (!response.ok) {
472
- throw new Error(`Test suite failed to start: ${ctx.response?.msg || ctx.response?.errName}`);
473
- }
489
+ {
490
+ title: "Waiting for test suite run creation",
491
+ enabled: (ctx) => ctx.response?.queueId,
492
+ task: async (ctx, currentTask) => {
493
+ let pollBranch = flags.branch;
494
+ if (this.isSingleTestCaseExecution(testCaseUuids, flags.branch)) {
495
+ pollBranch = `single-test-execution-${testCaseUuids[0]}`;
496
+ }
497
+ const detailsUrl = await this.waitForTestSuiteToBeCreated(testSuiteId, token, ctx.lastRunId, pollBranch, ctx.configuration.labels, ctx.configuration.excludedLabels);
498
+ task.title = `Running test suite [ ${detailsUrl} ]`;
499
+ currentTask.title = "Test suite run created successfully";
500
+ },
501
+ exitOnError: false,
474
502
  },
475
- exitOnError: false,
476
- },
477
- {
478
- title: "Waiting for test suite run creation",
479
- enabled: (ctx) => ctx.response?.queueId,
480
- task: async (ctx, currentTask) => {
481
- let pollBranch = flags.branch;
482
- if (this.isSingleTestCaseExecution(testCaseUuids, flags.branch)) {
483
- pollBranch = `single-test-execution-${testCaseUuids[0]}`;
484
- }
485
- const detailsUrl = await this.waitForTestSuiteToBeCreated(testSuiteId, token, ctx.lastRunId, pollBranch, ctx.configuration.labels, ctx.configuration.excludedLabels);
486
- task.title = `Running test suite [ ${detailsUrl} ]`;
487
- currentTask.title = "Test suite run created successfully";
503
+ {
504
+ title: "Checking status",
505
+ enabled: (ctx) => ctx.response?.result === "ok" && !flags.async,
506
+ task: async (ctx, task) => {
507
+ let pollBranch = flags.branch;
508
+ if (this.isSingleTestCaseExecution(testCaseUuids, flags.branch)) {
509
+ pollBranch = `single-test-execution-${testCaseUuids[0]}`;
510
+ }
511
+ return task.newListr([
512
+ {
513
+ task: async (ctx, statusTask) => {
514
+ await this.waitForTestSuiteToFinish(testSuiteId, token, statusTask, pollBranch, ctx.configuration.labels, ctx.configuration.excludedLabels);
515
+ },
516
+ },
517
+ ]);
518
+ },
519
+ exitOnError: false,
488
520
  },
489
- exitOnError: false,
490
- },
491
- {
492
- title: "Checking status",
493
- enabled: (ctx) => ctx.response?.result === "ok" && !flags.async,
494
- task: async (ctx, task) => {
495
- let pollBranch = flags.branch;
496
- if (this.isSingleTestCaseExecution(testCaseUuids, flags.branch)) {
497
- pollBranch = `single-test-execution-${testCaseUuids[0]}`;
498
- }
499
- return task.newListr([
521
+ {
522
+ title: "Generating JUnit report",
523
+ enabled: (ctx) => ctx.response?.result === "ok" &&
524
+ !flags.async &&
525
+ flags["junit-report-save-path"] &&
526
+ ctx.response?.taskId,
527
+ task: async (ctx, task) => task.newListr([
500
528
  {
501
529
  task: async (ctx, statusTask) => {
502
- await this.waitForTestSuiteToFinish(testSuiteId, token, statusTask, pollBranch, ctx.configuration.labels, ctx.configuration.excludedLabels);
530
+ await this.startAndWaitForJunitReportToFinish(testSuiteId, String(ctx.response?.taskId), String(flags["junit-report-save-path"]), token, statusTask);
503
531
  },
504
532
  },
505
- ]);
533
+ ]),
534
+ exitOnError: false,
506
535
  },
507
- exitOnError: false,
508
- },
509
- {
510
- title: "Generating JUnit report",
511
- enabled: (ctx) => ctx.response?.result === "ok" &&
512
- !flags.async &&
513
- flags["junit-report-save-path"] &&
514
- ctx.response?.taskId,
515
- task: async (ctx, task) => task.newListr([
516
- {
517
- task: async (ctx, statusTask) => {
518
- await this.startAndWaitForJunitReportToFinish(testSuiteId, String(ctx.response?.taskId), String(flags["junit-report-save-path"]), token, statusTask);
519
- },
536
+ {
537
+ task: () => {
538
+ const failed = steps.tasks.find((step) => step.hasFailed());
539
+ if (failed) {
540
+ throw new Error(failed.message?.error ?? FAILED_TO_START_TITLE);
541
+ }
520
542
  },
521
- ]),
522
- exitOnError: false,
523
- },
524
- ], {
525
- concurrent: false,
526
- rendererOptions: { collapseSubtasks: false, timer: listr2_1.PRESET_TIMER },
527
- fallbackRendererCondition: true,
528
- fallbackRendererOptions: { timer: listr2_1.PRESET_TIMER },
529
- }),
543
+ exitOnError: true,
544
+ },
545
+ ], {
546
+ concurrent: false,
547
+ rendererOptions: { collapseSubtasks: false, timer: listr2_1.PRESET_TIMER },
548
+ fallbackRendererCondition: true,
549
+ fallbackRendererOptions: { timer: listr2_1.PRESET_TIMER },
550
+ });
551
+ return steps;
552
+ },
530
553
  exitOnError: false,
531
554
  rendererOptions: {
532
555
  timer: listr2_1.PRESET_TIMER,
@@ -568,7 +591,7 @@ class Run extends command_base_1.CommandBase {
568
591
  }
569
592
  async fetchStatus(testSuiteId, token, branch, labels, excludedLabels) {
570
593
  const statusApiEndpoint = this.getStatusApiEndpoint(testSuiteId, branch, labels, excludedLabels);
571
- const response = await (0, node_fetch_commonjs_1.default)(statusApiEndpoint, {
594
+ const response = await fetch(statusApiEndpoint, {
572
595
  method: "GET",
573
596
  headers: {
574
597
  Accept: "application/json",
@@ -659,7 +682,7 @@ class Run extends command_base_1.CommandBase {
659
682
  }
660
683
  }
661
684
  async callRetest(testSuiteId, configuration, token) {
662
- return (0, node_fetch_commonjs_1.default)(`${this.TESTRIGOR_API_URL}/apps/${testSuiteId}/retest`, {
685
+ return fetch(`${this.TESTRIGOR_API_URL}/apps/${testSuiteId}/retest`, {
663
686
  method: "POST",
664
687
  body: JSON.stringify(configuration),
665
688
  headers: {
@@ -670,7 +693,7 @@ class Run extends command_base_1.CommandBase {
670
693
  });
671
694
  }
672
695
  async fetchSuiteType(testSuiteId, token) {
673
- const response = await (0, node_fetch_commonjs_1.default)(`${this.TESTRIGOR_API_URL}/apps/${testSuiteId}/status`, {
696
+ const response = await fetch(`${this.TESTRIGOR_API_URL}/apps/${testSuiteId}/status`, {
674
697
  method: "GET",
675
698
  headers: {
676
699
  Accept: "application/json",
@@ -691,7 +714,7 @@ class Run extends command_base_1.CommandBase {
691
714
  const body = {
692
715
  fileName: fileProperties.fileName,
693
716
  };
694
- const preSignedUrl = await (0, node_fetch_commonjs_1.default)(`${this.TESTRIGOR_API2_URL}/apps/${testSuiteId}/retest/pre-signed-url`, {
717
+ const preSignedUrl = await fetch(`${this.TESTRIGOR_API2_URL}/apps/${testSuiteId}/retest/pre-signed-url`, {
695
718
  method: "POST",
696
719
  body: JSON.stringify(body),
697
720
  headers: {
@@ -707,13 +730,9 @@ class Run extends command_base_1.CommandBase {
707
730
  throw new Error(`Failed to prepare upload: ${preSignedUrlResponse.message}`);
708
731
  }
709
732
  const preSignedUrlData = preSignedUrlResponse.data;
710
- const fileToBeUploaded = Fs.createReadStream(filePath);
711
- const uploadFileResponse = await (0, node_fetch_commonjs_1.default)(preSignedUrlData.url, {
733
+ const uploadFileResponse = await fetch(preSignedUrlData.url, {
712
734
  method: "PUT",
713
- body: fileToBeUploaded,
714
- headers: {
715
- "Content-length": `${fileProperties.fileSize}`,
716
- },
735
+ body: await (0, fs_2.openAsBlob)(filePath),
717
736
  });
718
737
  if (!uploadFileResponse.ok) {
719
738
  throw new Error(`Failed to upload file: ${uploadFileResponse.statusText}`);
@@ -774,7 +793,7 @@ class Run extends command_base_1.CommandBase {
774
793
  }
775
794
  }
776
795
  async fetchTestSuiteStatus(statusApiEndpoint, token) {
777
- return await (0, node_fetch_commonjs_1.default)(statusApiEndpoint, {
796
+ return await fetch(statusApiEndpoint, {
778
797
  method: "GET",
779
798
  headers: {
780
799
  Accept: "application/json",
@@ -810,7 +829,7 @@ class Run extends command_base_1.CommandBase {
810
829
  const url = `${this.TESTRIGOR_API2_URL}/apps/${testSuiteId}/runs/${runId}/junit_report`;
811
830
  for (;;) {
812
831
  // eslint-disable-next-line no-await-in-loop
813
- const response = await (0, node_fetch_commonjs_1.default)(url, {
832
+ const response = await fetch(url, {
814
833
  method: "GET",
815
834
  headers: {
816
835
  Accept: "application/json",
@@ -823,7 +842,7 @@ class Run extends command_base_1.CommandBase {
823
842
  throw new Error(`Unexpected contentType of junit report: ${contentType}`);
824
843
  }
825
844
  const xmlData = await response.text();
826
- await Fs.writeFile(savePath, xmlData);
845
+ await fs_1.default.writeFile(savePath, xmlData);
827
846
  task.title = JUNIT_REPORT_STATUS.READY;
828
847
  return;
829
848
  }
@@ -839,7 +858,6 @@ class Run extends command_base_1.CommandBase {
839
858
  }
840
859
  }
841
860
  }
842
- exports.default = Run;
843
861
  Run.description = "Run all tests of a Test Suite";
844
862
  Run.examples = [];
845
863
  Run.flags = {
@@ -928,3 +946,4 @@ Run.args = {
928
946
  required: false,
929
947
  }),
930
948
  };
949
+ exports.default = Run;