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 +23 -0
- package/dist/qase.js +2 -1
- package/dist/reporters/testops-reporter.d.ts +30 -1
- package/dist/reporters/testops-reporter.js +93 -14
- package/dist/utils/qase-error.d.ts +2 -2
- package/package.json +1 -1
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
|
-
|
|
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('
|
|
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
|
|
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
|
-
|
|
119
|
-
|
|
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
|
-
|
|
129
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
/**
|