qase-javascript-commons 2.0.0-beta.1 → 2.0.0-beta.2
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/config/config-validation-schema.js +22 -6
- package/dist/env/env-enum.d.ts +14 -7
- package/dist/env/env-enum.js +14 -6
- package/dist/env/env-to-config.js +6 -3
- package/dist/env/env-type.d.ts +7 -4
- package/dist/env/env-validation-schema.js +15 -4
- package/dist/formatter/index.d.ts +1 -0
- package/dist/formatter/index.js +3 -1
- package/dist/formatter/jsonp-formatter.d.ts +13 -0
- package/dist/formatter/jsonp-formatter.js +28 -0
- package/dist/models/attachment.d.ts +8 -0
- package/dist/models/attachment.js +2 -0
- package/dist/models/execution-sum.d.ts +6 -0
- package/dist/models/execution-sum.js +2 -0
- package/dist/models/host-data.d.ts +11 -0
- package/dist/models/host-data.js +2 -0
- package/dist/models/index.d.ts +6 -2
- package/dist/models/index.js +4 -4
- package/dist/models/report.d.ts +14 -0
- package/dist/models/report.js +2 -0
- package/dist/models/short-result.d.ts +7 -0
- package/dist/models/short-result.js +2 -0
- package/dist/models/stats.d.ts +8 -0
- package/dist/models/stats.js +2 -0
- package/dist/models/step-data.d.ts +4 -0
- package/dist/models/step-data.js +2 -0
- package/dist/models/step-execution.d.ts +11 -0
- package/dist/models/step-execution.js +9 -0
- package/dist/models/test-execution.d.ts +19 -0
- package/dist/models/test-execution.js +15 -0
- package/dist/models/test-result.d.ts +14 -20
- package/dist/models/test-result.js +0 -13
- package/dist/models/test-step.d.ts +9 -11
- package/dist/models/test-step.js +0 -7
- package/dist/options/options-type.d.ts +1 -0
- package/dist/qase.d.ts +22 -2
- package/dist/qase.js +103 -25
- package/dist/reporters/abstract-reporter.d.ts +18 -7
- package/dist/reporters/abstract-reporter.js +37 -2
- package/dist/reporters/report-reporter.d.ts +24 -12
- package/dist/reporters/report-reporter.js +152 -13
- package/dist/reporters/testops-reporter.d.ts +26 -49
- package/dist/reporters/testops-reporter.js +87 -155
- package/dist/writer/driver-enum.d.ts +7 -0
- package/dist/writer/driver-enum.js +9 -1
- package/dist/writer/fs-writer.d.ts +17 -8
- package/dist/writer/fs-writer.js +55 -8
- package/dist/writer/index.d.ts +1 -1
- package/dist/writer/index.js +2 -1
- package/dist/writer/writer-interface.d.ts +4 -2
- package/package.json +4 -3
package/dist/qase.d.ts
CHANGED
|
@@ -18,12 +18,22 @@ export declare class QaseReporter extends AbstractReporter {
|
|
|
18
18
|
* @type {ReporterInterface}
|
|
19
19
|
* @private
|
|
20
20
|
*/
|
|
21
|
-
private upstreamReporter?;
|
|
21
|
+
private readonly upstreamReporter?;
|
|
22
|
+
/**
|
|
23
|
+
* @type {ReporterInterface}
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
private readonly fallbackReporter?;
|
|
22
27
|
/**
|
|
23
28
|
* @type {boolean}
|
|
24
29
|
* @private
|
|
25
30
|
*/
|
|
26
31
|
private disabled;
|
|
32
|
+
/**
|
|
33
|
+
* @type {boolean}
|
|
34
|
+
* @private
|
|
35
|
+
*/
|
|
36
|
+
private useFallback;
|
|
27
37
|
/**
|
|
28
38
|
* @param {OptionsType} options
|
|
29
39
|
* @param {LoggerInterface} logger
|
|
@@ -33,18 +43,28 @@ export declare class QaseReporter extends AbstractReporter {
|
|
|
33
43
|
* @param {TestResultType} result
|
|
34
44
|
*/
|
|
35
45
|
addTestResult(result: TestResultType): void;
|
|
46
|
+
/**
|
|
47
|
+
* @param {TestResultType} result
|
|
48
|
+
* @private
|
|
49
|
+
*/
|
|
50
|
+
private addTestResultToFallback;
|
|
36
51
|
/**
|
|
37
52
|
* @returns {Promise<void>}
|
|
38
53
|
*/
|
|
39
54
|
publish(): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* @returns {Promise<void>}
|
|
57
|
+
*/
|
|
58
|
+
private publishFallback;
|
|
40
59
|
/**
|
|
41
60
|
* @todo implement mode registry
|
|
61
|
+
* @param {ModeEnum} mode
|
|
42
62
|
* @param {OptionsType} options
|
|
43
63
|
* @param {LoggerInterface} logger
|
|
44
64
|
* @returns {ReporterInterface}
|
|
45
65
|
* @private
|
|
46
66
|
*/
|
|
47
|
-
private
|
|
67
|
+
private createReporter;
|
|
48
68
|
/**
|
|
49
69
|
* @param {TestResultType} test
|
|
50
70
|
* @private
|
package/dist/qase.js
CHANGED
|
@@ -13,7 +13,6 @@ const options_1 = require("./options");
|
|
|
13
13
|
const env_1 = require("./env");
|
|
14
14
|
const models_1 = require("./models");
|
|
15
15
|
const writer_1 = require("./writer");
|
|
16
|
-
const formatter_1 = require("./formatter");
|
|
17
16
|
const get_package_version_1 = require("./utils/get-package-version");
|
|
18
17
|
const custom_boundary_1 = require("./utils/custom-boundary");
|
|
19
18
|
const disabled_exception_1 = require("./utils/disabled-exception");
|
|
@@ -21,12 +20,12 @@ const disabled_exception_1 = require("./utils/disabled-exception");
|
|
|
21
20
|
* @type {Record<TestStatusEnum, (test: TestResultType) => string>}
|
|
22
21
|
*/
|
|
23
22
|
const resultLogMap = {
|
|
24
|
-
[models_1.TestStatusEnum.failed]: (test) => (0, chalk_1.default) `{red Test ${test.title} ${test.status}}`,
|
|
25
|
-
[models_1.TestStatusEnum.passed]: (test) => (0, chalk_1.default) `{green Test ${test.title} ${test.status}}`,
|
|
26
|
-
[models_1.TestStatusEnum.skipped]: (test) => (0, chalk_1.default) `{blueBright Test ${test.title} ${test.status}}`,
|
|
27
|
-
[models_1.TestStatusEnum.blocked]: (test) => (0, chalk_1.default) `{blueBright Test ${test.title} ${test.status}}`,
|
|
28
|
-
[models_1.TestStatusEnum.disabled]: (test) => (0, chalk_1.default) `{grey Test ${test.title} ${test.status}}`,
|
|
29
|
-
[models_1.TestStatusEnum.invalid]: (test) => (0, chalk_1.default) `{yellowBright Test ${test.title} ${test.status}}`,
|
|
23
|
+
[models_1.TestStatusEnum.failed]: (test) => (0, chalk_1.default) `{red Test ${test.title} ${test.execution.status}}`,
|
|
24
|
+
[models_1.TestStatusEnum.passed]: (test) => (0, chalk_1.default) `{green Test ${test.title} ${test.execution.status}}`,
|
|
25
|
+
[models_1.TestStatusEnum.skipped]: (test) => (0, chalk_1.default) `{blueBright Test ${test.title} ${test.execution.status}}`,
|
|
26
|
+
[models_1.TestStatusEnum.blocked]: (test) => (0, chalk_1.default) `{blueBright Test ${test.title} ${test.execution.status}}`,
|
|
27
|
+
[models_1.TestStatusEnum.disabled]: (test) => (0, chalk_1.default) `{grey Test ${test.title} ${test.execution.status}}`,
|
|
28
|
+
[models_1.TestStatusEnum.invalid]: (test) => (0, chalk_1.default) `{yellowBright Test ${test.title} ${test.execution.status}}`,
|
|
30
29
|
};
|
|
31
30
|
/**
|
|
32
31
|
* @class QaseReporter
|
|
@@ -58,7 +57,7 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
58
57
|
client.push(`qase-core-reporter=${qaseReporterVersion}`);
|
|
59
58
|
}
|
|
60
59
|
if (qaseApiVersion) {
|
|
61
|
-
client.push(`
|
|
60
|
+
client.push(`qaseio=${String(qaseApiVersion)}`);
|
|
62
61
|
}
|
|
63
62
|
return {
|
|
64
63
|
'X-Client': client.join('; '),
|
|
@@ -78,15 +77,45 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
78
77
|
* @private
|
|
79
78
|
*/
|
|
80
79
|
this.disabled = false;
|
|
80
|
+
/**
|
|
81
|
+
* @type {boolean}
|
|
82
|
+
* @private
|
|
83
|
+
*/
|
|
84
|
+
this.useFallback = false;
|
|
81
85
|
try {
|
|
82
|
-
this.upstreamReporter = this.
|
|
86
|
+
this.upstreamReporter = this.createReporter(
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
88
|
+
composedOptions.mode || options_1.ModeEnum.off, composedOptions, logger);
|
|
83
89
|
}
|
|
84
90
|
catch (error) {
|
|
85
91
|
if (error instanceof disabled_exception_1.DisabledException) {
|
|
86
92
|
this.disabled = true;
|
|
87
93
|
}
|
|
88
94
|
else {
|
|
89
|
-
|
|
95
|
+
this.logError('Unable to create upstream reporter:', error);
|
|
96
|
+
if (composedOptions.fallback != undefined) {
|
|
97
|
+
this.disabled = true;
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
this.useFallback = true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
try {
|
|
104
|
+
this.fallbackReporter = this.createReporter(
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
106
|
+
composedOptions.fallback || options_1.ModeEnum.off, composedOptions, logger);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
if (error instanceof disabled_exception_1.DisabledException) {
|
|
110
|
+
if (this.useFallback) {
|
|
111
|
+
this.disabled = true;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
this.logError('Unable to create fallback reporter:', error);
|
|
116
|
+
if (this.useFallback && this.upstreamReporter === undefined) {
|
|
117
|
+
this.disabled = true;
|
|
118
|
+
}
|
|
90
119
|
}
|
|
91
120
|
}
|
|
92
121
|
}
|
|
@@ -95,42 +124,91 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
95
124
|
*/
|
|
96
125
|
addTestResult(result) {
|
|
97
126
|
if (!this.disabled) {
|
|
127
|
+
this.logTestItem(result);
|
|
128
|
+
if (this.useFallback) {
|
|
129
|
+
this.addTestResultToFallback(result);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
98
132
|
try {
|
|
99
|
-
this.logTestItem(result);
|
|
100
133
|
this.upstreamReporter?.addTestResult(result);
|
|
101
134
|
}
|
|
102
135
|
catch (error) {
|
|
103
|
-
this.logError('Unable to
|
|
104
|
-
this.
|
|
136
|
+
this.logError('Unable to add the result to the upstream reporter:', error);
|
|
137
|
+
if (this.fallbackReporter == undefined) {
|
|
138
|
+
this.disabled = true;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (!this.useFallback) {
|
|
142
|
+
this.fallbackReporter.setTestResults(this.upstreamReporter?.getTestResults() ?? []);
|
|
143
|
+
this.useFallback = true;
|
|
144
|
+
}
|
|
145
|
+
this.addTestResultToFallback(result);
|
|
105
146
|
}
|
|
106
147
|
}
|
|
107
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* @param {TestResultType} result
|
|
151
|
+
* @private
|
|
152
|
+
*/
|
|
153
|
+
addTestResultToFallback(result) {
|
|
154
|
+
try {
|
|
155
|
+
this.fallbackReporter?.addTestResult(result);
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
this.logError('Unable to add the result to the fallback reporter:', error);
|
|
159
|
+
this.disabled = true;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
108
162
|
/**
|
|
109
163
|
* @returns {Promise<void>}
|
|
110
164
|
*/
|
|
111
165
|
async publish() {
|
|
112
166
|
if (!this.disabled) {
|
|
167
|
+
if (this.useFallback) {
|
|
168
|
+
await this.publishFallback();
|
|
169
|
+
}
|
|
113
170
|
try {
|
|
114
171
|
await this.upstreamReporter?.publish();
|
|
115
172
|
}
|
|
116
173
|
catch (error) {
|
|
117
|
-
this.logError('Unable to publish run results:', error);
|
|
118
|
-
this.
|
|
174
|
+
this.logError('Unable to publish the run results to the upstream reporter:', error);
|
|
175
|
+
if (this.fallbackReporter == undefined) {
|
|
176
|
+
this.disabled = true;
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (!this.useFallback) {
|
|
180
|
+
this.fallbackReporter.setTestResults(this.upstreamReporter?.getTestResults() ?? []);
|
|
181
|
+
this.useFallback = true;
|
|
182
|
+
}
|
|
183
|
+
await this.publishFallback();
|
|
119
184
|
}
|
|
120
185
|
}
|
|
121
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* @returns {Promise<void>}
|
|
189
|
+
*/
|
|
190
|
+
async publishFallback() {
|
|
191
|
+
try {
|
|
192
|
+
await this.fallbackReporter?.publish();
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
this.logError('Unable to publish the run results to the fallback reporter:', error);
|
|
196
|
+
this.disabled = true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
122
199
|
/**
|
|
123
200
|
* @todo implement mode registry
|
|
201
|
+
* @param {ModeEnum} mode
|
|
124
202
|
* @param {OptionsType} options
|
|
125
203
|
* @param {LoggerInterface} logger
|
|
126
204
|
* @returns {ReporterInterface}
|
|
127
205
|
* @private
|
|
128
206
|
*/
|
|
129
|
-
|
|
130
|
-
const { frameworkPackage, frameworkName, reporterName,
|
|
207
|
+
createReporter(mode, options, logger) {
|
|
208
|
+
const { frameworkPackage, frameworkName, reporterName, environment, report = {}, testops = {}, ...commonOptions } = options;
|
|
131
209
|
switch (mode) {
|
|
132
210
|
case options_1.ModeEnum.testops: {
|
|
133
|
-
const { api: { token, headers, ...api } = {},
|
|
211
|
+
const { api: { token, headers, ...api } = {}, project, run: { title, description, ...run } = {}, plan = {}, chunk, uploadAttachments, } = testops;
|
|
134
212
|
if (!token) {
|
|
135
213
|
throw new Error(`Either "testops.api.token" parameter or "${env_1.EnvApiEnum.token}" environment variable is required in "testops" mode`);
|
|
136
214
|
}
|
|
@@ -143,25 +221,25 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
143
221
|
...headers,
|
|
144
222
|
...QaseReporter.createHeaders(frameworkPackage, frameworkName, reporterName),
|
|
145
223
|
},
|
|
146
|
-
...api
|
|
224
|
+
...api,
|
|
147
225
|
}, custom_boundary_1.CustomBoundaryFormData);
|
|
148
226
|
return new reporters_1.TestOpsReporter({
|
|
149
|
-
baseUrl,
|
|
150
227
|
project,
|
|
151
228
|
uploadAttachments,
|
|
152
229
|
run: {
|
|
153
230
|
title: title ?? `Automated run ${new Date().toISOString()}`,
|
|
154
231
|
description: description ?? `${reporterName} automated run`,
|
|
155
|
-
environment: typeof environment === 'number' ? environment : undefined,
|
|
156
232
|
...run,
|
|
157
233
|
},
|
|
234
|
+
plan,
|
|
235
|
+
chunk,
|
|
158
236
|
...commonOptions,
|
|
159
|
-
}, apiClient, logger);
|
|
237
|
+
}, apiClient, logger, typeof environment === 'number' ? environment : undefined);
|
|
160
238
|
}
|
|
161
239
|
case options_1.ModeEnum.report: {
|
|
162
240
|
const localOptions = report.connections?.[writer_1.DriverEnum.local];
|
|
163
|
-
const writer = new writer_1.FsWriter(localOptions
|
|
164
|
-
return new reporters_1.ReportReporter(commonOptions, writer, logger);
|
|
241
|
+
const writer = new writer_1.FsWriter(localOptions);
|
|
242
|
+
return new reporters_1.ReportReporter(commonOptions, writer, logger, typeof environment === 'number' ? environment.toString() : environment, testops.run?.id);
|
|
165
243
|
}
|
|
166
244
|
case options_1.ModeEnum.off:
|
|
167
245
|
throw new disabled_exception_1.DisabledException();
|
|
@@ -174,7 +252,7 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
174
252
|
* @private
|
|
175
253
|
*/
|
|
176
254
|
logTestItem(test) {
|
|
177
|
-
this.log(resultLogMap[test.status](test));
|
|
255
|
+
this.log(resultLogMap[test.execution.status](test));
|
|
178
256
|
}
|
|
179
257
|
}
|
|
180
258
|
exports.QaseReporter = QaseReporter;
|
|
@@ -4,12 +4,14 @@ export interface LoggerInterface {
|
|
|
4
4
|
group(): void;
|
|
5
5
|
groupEnd(): void;
|
|
6
6
|
}
|
|
7
|
-
export
|
|
7
|
+
export interface ReporterOptionsType {
|
|
8
8
|
debug?: boolean | undefined;
|
|
9
|
-
}
|
|
9
|
+
}
|
|
10
10
|
export interface ReporterInterface {
|
|
11
11
|
addTestResult(result: TestResultType): void;
|
|
12
12
|
publish(): Promise<void>;
|
|
13
|
+
getTestResults(): TestResultType[];
|
|
14
|
+
setTestResults(results: TestResultType[]): void;
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* @abstract
|
|
@@ -22,11 +24,8 @@ export declare abstract class AbstractReporter implements ReporterInterface {
|
|
|
22
24
|
* @type {boolean | undefined}
|
|
23
25
|
* @private
|
|
24
26
|
*/
|
|
25
|
-
private debug;
|
|
26
|
-
|
|
27
|
-
* @param {TestResultType} result
|
|
28
|
-
*/
|
|
29
|
-
abstract addTestResult(result: TestResultType): void;
|
|
27
|
+
private readonly debug;
|
|
28
|
+
protected results: TestResultType[];
|
|
30
29
|
/**
|
|
31
30
|
* @returns {Promise<void>}
|
|
32
31
|
*/
|
|
@@ -37,6 +36,18 @@ export declare abstract class AbstractReporter implements ReporterInterface {
|
|
|
37
36
|
* @protected
|
|
38
37
|
*/
|
|
39
38
|
protected constructor(options: ReporterOptionsType | undefined, logger?: LoggerInterface);
|
|
39
|
+
/**
|
|
40
|
+
* @returns {TestResultType[]}
|
|
41
|
+
*/
|
|
42
|
+
getTestResults(): TestResultType[];
|
|
43
|
+
/**
|
|
44
|
+
* @param {TestResultType} result
|
|
45
|
+
*/
|
|
46
|
+
addTestResult(result: TestResultType): void;
|
|
47
|
+
/**
|
|
48
|
+
* @param {TestResultType[]} results
|
|
49
|
+
*/
|
|
50
|
+
setTestResults(results: TestResultType[]): void;
|
|
40
51
|
/**
|
|
41
52
|
* @param {string} message
|
|
42
53
|
* @protected
|
|
@@ -7,6 +7,7 @@ exports.AbstractReporter = void 0;
|
|
|
7
7
|
const lodash_get_1 = __importDefault(require("lodash.get"));
|
|
8
8
|
const qase_error_1 = require("../utils/qase-error");
|
|
9
9
|
const is_axios_error_1 = require("../utils/is-axios-error");
|
|
10
|
+
const uuid_1 = require("uuid");
|
|
10
11
|
/**
|
|
11
12
|
* @abstract
|
|
12
13
|
* @class AbstractReporter
|
|
@@ -20,9 +21,43 @@ class AbstractReporter {
|
|
|
20
21
|
*/
|
|
21
22
|
constructor(options, logger = console) {
|
|
22
23
|
this.logger = logger;
|
|
24
|
+
this.results = [];
|
|
23
25
|
const { debug } = options ?? {};
|
|
24
26
|
this.debug = debug;
|
|
25
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* @returns {TestResultType[]}
|
|
30
|
+
*/
|
|
31
|
+
getTestResults() {
|
|
32
|
+
return this.results;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* @param {TestResultType} result
|
|
36
|
+
*/
|
|
37
|
+
addTestResult(result) {
|
|
38
|
+
if (result.testops_id === null || !Array.isArray(result.testops_id)) {
|
|
39
|
+
this.results.push(result);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
// if we have multiple ids, we need to create multiple test results and set duration to 0 for all but the first one
|
|
43
|
+
let firstCase = true;
|
|
44
|
+
for (const id of result.testops_id) {
|
|
45
|
+
const testResultCopy = { ...result };
|
|
46
|
+
testResultCopy.testops_id = id;
|
|
47
|
+
testResultCopy.id = (0, uuid_1.v4)();
|
|
48
|
+
if (!firstCase) {
|
|
49
|
+
testResultCopy.execution.duration = 0;
|
|
50
|
+
}
|
|
51
|
+
firstCase = false;
|
|
52
|
+
this.results.push(testResultCopy);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* @param {TestResultType[]} results
|
|
57
|
+
*/
|
|
58
|
+
setTestResults(results) {
|
|
59
|
+
this.results = results;
|
|
60
|
+
}
|
|
26
61
|
/**
|
|
27
62
|
* @param {string} message
|
|
28
63
|
* @protected
|
|
@@ -49,13 +84,13 @@ class AbstractReporter {
|
|
|
49
84
|
this.logger.log(message);
|
|
50
85
|
this.logger.group();
|
|
51
86
|
if (error instanceof Error) {
|
|
52
|
-
this.logger.log(`${error.stack || `${error.name}: ${error.message}`}`);
|
|
53
87
|
if ((0, is_axios_error_1.isAxiosError)(error)) {
|
|
54
88
|
this.logApiError(error);
|
|
55
89
|
}
|
|
56
90
|
else if (error instanceof qase_error_1.QaseError && error.cause) {
|
|
57
91
|
this.doLogError('Caused by:', error.cause);
|
|
58
92
|
}
|
|
93
|
+
this.logger.log(`${error.stack || `${error.name}: ${error.message}`}`);
|
|
59
94
|
}
|
|
60
95
|
else {
|
|
61
96
|
this.logger.log(String(error));
|
|
@@ -72,7 +107,7 @@ class AbstractReporter {
|
|
|
72
107
|
?? (0, lodash_get_1.default)(error, 'response.statusText')
|
|
73
108
|
?? 'Unknown error';
|
|
74
109
|
const errorFields = this.formatErrorFields((0, lodash_get_1.default)(error, 'response.data.errorFields'));
|
|
75
|
-
this.logger.log(String(errorMessage));
|
|
110
|
+
this.logger.log(`Message: ${String(errorMessage)}`);
|
|
76
111
|
if (errorFields) {
|
|
77
112
|
this.logger.group();
|
|
78
113
|
this.logger.log(errorFields);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { AbstractReporter,
|
|
2
|
-
import { TestResultType } from '../models';
|
|
1
|
+
import { AbstractReporter, LoggerInterface, ReporterOptionsType } from './abstract-reporter';
|
|
3
2
|
import { WriterInterface } from '../writer';
|
|
4
3
|
/**
|
|
5
4
|
* @class ReportReporter
|
|
@@ -7,25 +6,38 @@ import { WriterInterface } from '../writer';
|
|
|
7
6
|
*/
|
|
8
7
|
export declare class ReportReporter extends AbstractReporter {
|
|
9
8
|
private writer;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
*/
|
|
14
|
-
private results;
|
|
9
|
+
private readonly environment;
|
|
10
|
+
private readonly runId;
|
|
11
|
+
private readonly startTime;
|
|
15
12
|
/**
|
|
16
13
|
* @param {ReporterOptionsType} options
|
|
17
14
|
* @param {WriterInterface} writer
|
|
18
15
|
* @param {LoggerInterface} logger
|
|
16
|
+
* @param {string | undefined} environment
|
|
17
|
+
* @param {number | undefined} runId
|
|
19
18
|
*/
|
|
20
|
-
constructor(options: ReporterOptionsType | undefined, writer: WriterInterface, logger?: LoggerInterface);
|
|
21
|
-
/**
|
|
22
|
-
* @param {TestResultType} result
|
|
23
|
-
*/
|
|
24
|
-
addTestResult(result: TestResultType): void;
|
|
19
|
+
constructor(options: ReporterOptionsType | undefined, writer: WriterInterface, logger?: LoggerInterface, environment?: string, runId?: number);
|
|
25
20
|
/**
|
|
26
21
|
* @returns {Promise<void>}
|
|
27
22
|
*
|
|
28
23
|
* eslint-disable-next-line @typescript-eslint/require-await
|
|
29
24
|
*/
|
|
30
25
|
publish(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* @param {TestStepType[]} steps
|
|
28
|
+
* @returns {TestStepType[]}
|
|
29
|
+
*/
|
|
30
|
+
private copyStepAttachments;
|
|
31
|
+
/**
|
|
32
|
+
* @returns {HostData}
|
|
33
|
+
*/
|
|
34
|
+
private getHostInfo;
|
|
35
|
+
/**
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
private getComputerName;
|
|
39
|
+
/**
|
|
40
|
+
* @returns {string}
|
|
41
|
+
*/
|
|
42
|
+
private getDetailedOSInfo;
|
|
31
43
|
}
|
|
@@ -1,7 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
26
|
exports.ReportReporter = void 0;
|
|
4
27
|
const abstract_reporter_1 = require("./abstract-reporter");
|
|
28
|
+
const models_1 = require("../models");
|
|
29
|
+
const os = __importStar(require("os"));
|
|
30
|
+
const cp = __importStar(require("child_process"));
|
|
31
|
+
const process = __importStar(require("process"));
|
|
5
32
|
/**
|
|
6
33
|
* @class ReportReporter
|
|
7
34
|
* @extends AbstractReporter
|
|
@@ -11,21 +38,15 @@ class ReportReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
11
38
|
* @param {ReporterOptionsType} options
|
|
12
39
|
* @param {WriterInterface} writer
|
|
13
40
|
* @param {LoggerInterface} logger
|
|
41
|
+
* @param {string | undefined} environment
|
|
42
|
+
* @param {number | undefined} runId
|
|
14
43
|
*/
|
|
15
|
-
constructor(options, writer, logger) {
|
|
44
|
+
constructor(options, writer, logger, environment, runId) {
|
|
16
45
|
super(options, logger);
|
|
17
46
|
this.writer = writer;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
*/
|
|
22
|
-
this.results = [];
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* @param {TestResultType} result
|
|
26
|
-
*/
|
|
27
|
-
addTestResult(result) {
|
|
28
|
-
this.results.push(result);
|
|
47
|
+
this.startTime = Date.now();
|
|
48
|
+
this.environment = environment;
|
|
49
|
+
this.runId = runId;
|
|
29
50
|
}
|
|
30
51
|
/**
|
|
31
52
|
* @returns {Promise<void>}
|
|
@@ -33,8 +54,126 @@ class ReportReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
33
54
|
* eslint-disable-next-line @typescript-eslint/require-await
|
|
34
55
|
*/
|
|
35
56
|
async publish() {
|
|
36
|
-
const
|
|
57
|
+
const report = {
|
|
58
|
+
title: 'Test report',
|
|
59
|
+
execution: {
|
|
60
|
+
start_time: this.startTime,
|
|
61
|
+
end_time: Date.now(),
|
|
62
|
+
duration: Date.now() - this.startTime,
|
|
63
|
+
cumulative_duration: 0,
|
|
64
|
+
},
|
|
65
|
+
stats: {
|
|
66
|
+
total: 0,
|
|
67
|
+
passed: 0,
|
|
68
|
+
failed: 0,
|
|
69
|
+
skipped: 0,
|
|
70
|
+
broken: 0,
|
|
71
|
+
muted: 0,
|
|
72
|
+
},
|
|
73
|
+
results: [],
|
|
74
|
+
threads: [],
|
|
75
|
+
suites: [],
|
|
76
|
+
environment: this.environment ?? '',
|
|
77
|
+
host_data: this.getHostInfo(),
|
|
78
|
+
};
|
|
79
|
+
for (const result of this.results) {
|
|
80
|
+
report.stats.total++;
|
|
81
|
+
switch (result.execution.status) {
|
|
82
|
+
case models_1.TestStatusEnum.passed:
|
|
83
|
+
report.stats.passed++;
|
|
84
|
+
break;
|
|
85
|
+
case models_1.TestStatusEnum.failed:
|
|
86
|
+
report.stats.failed++;
|
|
87
|
+
break;
|
|
88
|
+
case models_1.TestStatusEnum.skipped:
|
|
89
|
+
report.stats.skipped++;
|
|
90
|
+
break;
|
|
91
|
+
case models_1.TestStatusEnum.invalid:
|
|
92
|
+
report.stats.broken++;
|
|
93
|
+
break;
|
|
94
|
+
case models_1.TestStatusEnum.blocked:
|
|
95
|
+
report.stats.muted++;
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
if (result.execution.thread && !report.threads.includes(result.execution.thread)) {
|
|
99
|
+
report.threads.push(result.execution.thread);
|
|
100
|
+
}
|
|
101
|
+
report.execution.cumulative_duration += result.execution.duration ?? 0;
|
|
102
|
+
report.results.push({
|
|
103
|
+
duration: result.execution.duration ?? 0,
|
|
104
|
+
id: result.id,
|
|
105
|
+
status: result.execution.status,
|
|
106
|
+
thread: result.execution.thread,
|
|
107
|
+
title: result.title,
|
|
108
|
+
});
|
|
109
|
+
if (result.attachments.length > 0) {
|
|
110
|
+
result.attachments = this.writer.writeAttachment(result.attachments);
|
|
111
|
+
}
|
|
112
|
+
result.steps = this.copyStepAttachments(result.steps);
|
|
113
|
+
result.run_id = this.runId ?? null;
|
|
114
|
+
await this.writer.writeTestResult(result);
|
|
115
|
+
}
|
|
116
|
+
const path = await this.writer.writeReport(report);
|
|
37
117
|
this.log(`Report saved to ${path}`);
|
|
38
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* @param {TestStepType[]} steps
|
|
121
|
+
* @returns {TestStepType[]}
|
|
122
|
+
*/
|
|
123
|
+
copyStepAttachments(steps) {
|
|
124
|
+
for (const step of steps) {
|
|
125
|
+
if (step.attachments.length > 0) {
|
|
126
|
+
step.attachments = this.writer.writeAttachment(step.attachments);
|
|
127
|
+
}
|
|
128
|
+
if (step.steps.length > 0) {
|
|
129
|
+
step.steps = this.copyStepAttachments(step.steps);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return steps;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* @returns {HostData}
|
|
136
|
+
*/
|
|
137
|
+
getHostInfo() {
|
|
138
|
+
return {
|
|
139
|
+
system: process.platform,
|
|
140
|
+
node: this.getComputerName(),
|
|
141
|
+
release: os.release(),
|
|
142
|
+
version: this.getDetailedOSInfo(),
|
|
143
|
+
machine: os.arch(),
|
|
144
|
+
python: '',
|
|
145
|
+
pip: '',
|
|
146
|
+
node_version: cp.execSync('node --version').toString().trim(),
|
|
147
|
+
npm: cp.execSync('npm --version').toString().trim(),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* @returns {string}
|
|
152
|
+
*/
|
|
153
|
+
getComputerName() {
|
|
154
|
+
switch (process.platform) {
|
|
155
|
+
case 'win32':
|
|
156
|
+
return process.env['COMPUTERNAME'] ?? '';
|
|
157
|
+
case 'darwin':
|
|
158
|
+
return cp.execSync('scutil --get ComputerName').toString().trim();
|
|
159
|
+
case 'linux': {
|
|
160
|
+
const prettyname = cp.execSync('hostnamectl --pretty').toString().trim();
|
|
161
|
+
return prettyname === '' ? os.hostname() : prettyname;
|
|
162
|
+
}
|
|
163
|
+
default:
|
|
164
|
+
return os.hostname();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* @returns {string}
|
|
169
|
+
*/
|
|
170
|
+
getDetailedOSInfo() {
|
|
171
|
+
if (process.platform === 'darwin') {
|
|
172
|
+
return cp.execSync('uname -a').toString().trim();
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
return `${os.type()} ${os.release()} ${os.arch()}`;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
39
178
|
}
|
|
40
179
|
exports.ReportReporter = ReportReporter;
|