qase-javascript-commons 2.0.9 → 2.0.11

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/changelog.md CHANGED
@@ -1,3 +1,26 @@
1
+ # qase-javascript-commons@2.0.11
2
+
3
+ ## What's new
4
+
5
+ - Improved logging for better debugging and error reporting.
6
+
7
+ - Show the link to the test run in the console output when the test is failed.
8
+
9
+ ```text
10
+ [INFO] qase: See why this test failed: https://app.qase.io/run/DEMO/dashboard/123?status=%5B2%5D&search=5%20-%206%20=%20-2
11
+ ```
12
+
13
+ # qase-javascript-commons@2.0.10
14
+
15
+ ## What's new
16
+
17
+ Fixed an issue with sending test results duplicates when we use the `qase-cypress` reporter.
18
+ Now the reporter will send the test results only once.
19
+
20
+ The Cypress calls the `publish` method multiple times for the same test results because of the Cypress architecture.
21
+ It calls the `publish` method for each test file.
22
+
23
+
1
24
  # qase-javascript-commons@2.0.9
2
25
 
3
26
  ## What's new
package/dist/qase.js CHANGED
@@ -161,6 +161,7 @@ class QaseReporter {
161
161
  */
162
162
  async addTestResult(result) {
163
163
  if (!this.disabled) {
164
+ await this.startTestRunOperation;
164
165
  this.logTestItem(result);
165
166
  if (this.useFallback) {
166
167
  await this.addTestResultToFallback(result);
@@ -279,7 +280,7 @@ class QaseReporter {
279
280
  batch,
280
281
  useV2,
281
282
  defect,
282
- }, apiClient, environment, rootSuite);
283
+ }, apiClient, environment, rootSuite, api.host);
283
284
  }
284
285
  case options_1.ModeEnum.report: {
285
286
  const localOptions = report.connections?.[writer_1.DriverEnum.local];
@@ -102,8 +102,9 @@ export declare class TestOpsReporter extends AbstractReporter {
102
102
  * @param {QaseApiInterface} api
103
103
  * @param {string | undefined} environment
104
104
  * @param {string | undefined} rootSuite
105
+ * @param {string | undefined} baseUrl
105
106
  */
106
- constructor(logger: LoggerInterface, options: TestOpsOptionsType, api: QaseApiInterface, environment?: string, rootSuite?: string);
107
+ constructor(logger: LoggerInterface, options: TestOpsOptionsType, api: QaseApiInterface, environment?: string, rootSuite?: string, baseUrl?: string);
107
108
  /**
108
109
  * @returns {Promise<void>}
109
110
  */
@@ -190,4 +191,32 @@ export declare class TestOpsReporter extends AbstractReporter {
190
191
  * @private
191
192
  */
192
193
  private uploadAttachments;
194
+ /**
195
+ * Process error and throw QaseError
196
+ * @param {Error | AxiosError} error
197
+ * @param {string} message
198
+ * @param {object} model
199
+ * @private
200
+ */
201
+ private processError;
202
+ /**
203
+ * @param {string | undefined} url
204
+ * @return string
205
+ * @private
206
+ */
207
+ private getBaseUrl;
208
+ /**
209
+ * @param {number | null} id
210
+ * @param {string} title
211
+ * @return string
212
+ * @private
213
+ */
214
+ private prepareFailedTestLink;
215
+ /**
216
+ * Show link to failed test
217
+ * @param {number | null} id
218
+ * @param {string} title
219
+ * @private
220
+ */
221
+ private showLink;
193
222
  }
@@ -10,6 +10,7 @@ const qaseio_1 = require("qaseio");
10
10
  const abstract_reporter_1 = require("./abstract-reporter");
11
11
  const models_1 = require("../models");
12
12
  const qase_error_1 = require("../utils/qase-error");
13
+ const axios_1 = __importDefault(require("axios"));
13
14
  const defaultChunkSize = 200;
14
15
  /**
15
16
  * @class TestOpsReporter
@@ -22,8 +23,9 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
22
23
  * @param {QaseApiInterface} api
23
24
  * @param {string | undefined} environment
24
25
  * @param {string | undefined} rootSuite
26
+ * @param {string | undefined} baseUrl
25
27
  */
26
- constructor(logger, options, api, environment, rootSuite) {
28
+ constructor(logger, options, api, environment, rootSuite, baseUrl) {
27
29
  const { project, uploadAttachments, run, } = options;
28
30
  super(logger);
29
31
  this.api = api;
@@ -37,8 +39,7 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
37
39
  * @private
38
40
  */
39
41
  this.isTestRunReady = false;
40
- const baseUrl = 'https://app.qase.io';
41
- this.baseUrl = baseUrl.replace(/\/$/, '');
42
+ this.baseUrl = this.getBaseUrl(baseUrl);
42
43
  this.projectCode = project;
43
44
  this.isUploadAttachments = uploadAttachments;
44
45
  this.run = { complete: true, ...run };
@@ -59,6 +60,16 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
59
60
  * @returns {Promise<void>}
60
61
  */
61
62
  async addTestResult(result) {
63
+ if (result.execution.status === models_1.TestStatusEnum.failed) {
64
+ if (Array.isArray(result.testops_id)) {
65
+ for (const id of result.testops_id) {
66
+ this.showLink(id, result.title);
67
+ }
68
+ }
69
+ else {
70
+ this.showLink(result.testops_id, result.title);
71
+ }
72
+ }
62
73
  await super.addTestResult(result);
63
74
  if (!this.isTestRunReady) {
64
75
  return;
@@ -80,7 +91,7 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
80
91
  this.isTestRunReady = true;
81
92
  return;
82
93
  }
83
- this.logger.logDebug('Create test run');
94
+ this.logger.logDebug('Creating test run');
84
95
  let environmentId;
85
96
  if (this.environment != undefined) {
86
97
  try {
@@ -91,7 +102,7 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
91
102
  }
92
103
  }
93
104
  catch (error) {
94
- throw new qase_error_1.QaseError('Cannot get environments', { cause: error });
105
+ throw this.processError(error, 'Error on getting environments');
95
106
  }
96
107
  }
97
108
  const { result } = await this.createRun(this.run.title, this.run.description, environmentId);
@@ -115,9 +126,14 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
115
126
  const resultCreateV2 = await this.transformTestResult(result);
116
127
  results.push(resultCreateV2);
117
128
  }
118
- await this.api.result.createResultsV2(this.projectCode, this.run.id, {
119
- results: results,
120
- });
129
+ try {
130
+ await this.api.result.createResultsV2(this.projectCode, this.run.id, {
131
+ results: results,
132
+ });
133
+ }
134
+ catch (error) {
135
+ throw this.processError(error, 'Error on uploading results', results);
136
+ }
121
137
  }
122
138
  else {
123
139
  const results = [];
@@ -125,9 +141,14 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
125
141
  const resultCreate = await this.transformTestResultV1(result);
126
142
  results.push(resultCreate);
127
143
  }
128
- await this.api.results.createResultBulk(this.projectCode, this.run.id, {
129
- results: results,
130
- });
144
+ try {
145
+ await this.api.results.createResultBulk(this.projectCode, this.run.id, {
146
+ results: results,
147
+ });
148
+ }
149
+ catch (error) {
150
+ throw this.processError(error, 'Error on uploading results', results);
151
+ }
131
152
  }
132
153
  this.logger.logDebug(`Results sent to Qase: ${testResults.length}`);
133
154
  }
@@ -142,6 +163,8 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
142
163
  if (this.firstIndex < this.results.length) {
143
164
  await this.publishResults(this.results.slice(this.firstIndex));
144
165
  }
166
+ // Clear results because we don't need to send them again then we use Cypress reporter
167
+ this.results.length = 0;
145
168
  if (!this.run.complete) {
146
169
  return;
147
170
  }
@@ -150,7 +173,7 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
150
173
  this.logger.log((0, chalk_1.default) `{green Run ${this.run.id} completed}`);
151
174
  }
152
175
  catch (error) {
153
- throw new qase_error_1.QaseError('Error on completing run', { cause: error });
176
+ throw this.processError(error, 'Error on completing run');
154
177
  }
155
178
  const runUrl = `${this.baseUrl}/run/${this.projectCode}/dashboard/${this.run.id}`;
156
179
  this.logger.log((0, chalk_1.default) `{blue Test run link: ${runUrl}}`);
@@ -357,7 +380,7 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
357
380
  this.logger.log(`Get run result on checking run "${String(resp.data.result?.id)}"`);
358
381
  }
359
382
  catch (error) {
360
- throw new qase_error_1.QaseError('Error on checking run', { cause: error });
383
+ throw this.processError(error, 'Error on checking run');
361
384
  }
362
385
  }
363
386
  /**
@@ -383,7 +406,7 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
383
406
  return data;
384
407
  }
385
408
  catch (error) {
386
- throw new qase_error_1.QaseError('Cannot create run', { cause: error });
409
+ throw this.processError(error, 'Error on creating run');
387
410
  }
388
411
  }
389
412
  /**
@@ -436,6 +459,62 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
436
459
  }
437
460
  return acc;
438
461
  }
462
+ /**
463
+ * Process error and throw QaseError
464
+ * @param {Error | AxiosError} error
465
+ * @param {string} message
466
+ * @param {object} model
467
+ * @private
468
+ */
469
+ processError(error, message, model) {
470
+ if (!axios_1.default.isAxiosError(error)) {
471
+ return new qase_error_1.QaseError(message, { cause: error });
472
+ }
473
+ if (error.response?.status === 401) {
474
+ return new qase_error_1.QaseError(message + ': \n Unauthorized. Please check your API token. Maybe it is expired or invalid.');
475
+ }
476
+ if (error.response?.status === 404) {
477
+ return new qase_error_1.QaseError(message + ': Not found.');
478
+ }
479
+ if (error.response?.status === 400) {
480
+ return new qase_error_1.QaseError(message + ': Bad request. Body: \n ' + JSON.stringify(model));
481
+ }
482
+ return new qase_error_1.QaseError(message, { cause: error });
483
+ }
484
+ /**
485
+ * @param {string | undefined} url
486
+ * @return string
487
+ * @private
488
+ */
489
+ getBaseUrl(url) {
490
+ if (!url || url === 'qase.io') {
491
+ return 'https://app.qase.io';
492
+ }
493
+ return `https://${url.replace('api', 'app')}`;
494
+ }
495
+ /**
496
+ * @param {number | null} id
497
+ * @param {string} title
498
+ * @return string
499
+ * @private
500
+ */
501
+ prepareFailedTestLink(id, title) {
502
+ const baseLink = `${this.baseUrl}/run/${this.projectCode}/dashboard/${this.run.id}?source=logs&status=%5B2%5D&search=`;
503
+ if (id) {
504
+ return `${baseLink}${id}`;
505
+ }
506
+ return `${baseLink}${encodeURI(title)}`;
507
+ }
508
+ /**
509
+ * Show link to failed test
510
+ * @param {number | null} id
511
+ * @param {string} title
512
+ * @private
513
+ */
514
+ showLink(id, title) {
515
+ const link = this.prepareFailedTestLink(id, title);
516
+ this.logger.log((0, chalk_1.default) `{blue See why this test failed: ${link}}`);
517
+ }
439
518
  }
440
519
  exports.TestOpsReporter = TestOpsReporter;
441
520
  /**
@@ -1,6 +1,6 @@
1
- export type ErrorOptionsType = {
1
+ export interface ErrorOptionsType {
2
2
  cause?: unknown;
3
- };
3
+ }
4
4
  export interface QaseErrorInterface extends Error {
5
5
  cause?: unknown;
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qase-javascript-commons",
3
- "version": "2.0.9",
3
+ "version": "2.0.11",
4
4
  "description": "Qase JS Reporters",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",