qase-javascript-commons 2.0.0-beta.8 → 2.0.0-beta.9
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 +22 -0
- package/dist/models/index.d.ts +1 -1
- package/dist/models/index.js +3 -1
- package/dist/models/step-data.d.ts +6 -1
- package/dist/models/test-step.d.ts +7 -3
- package/dist/models/test-step.js +6 -0
- package/dist/qase.d.ts +2 -4
- package/dist/qase.js +19 -18
- package/dist/reporters/abstract-reporter.d.ts +6 -36
- package/dist/reporters/abstract-reporter.js +4 -84
- package/dist/reporters/report-reporter.d.ts +2 -3
- package/dist/reporters/report-reporter.js +4 -4
- package/dist/reporters/testops-reporter.d.ts +2 -3
- package/dist/reporters/testops-reporter.js +37 -12
- package/dist/utils/logger.d.ts +24 -0
- package/dist/utils/logger.js +121 -0
- package/dist/writer/fs-writer.d.ts +5 -0
- package/dist/writer/fs-writer.js +20 -0
- package/dist/writer/writer-interface.d.ts +1 -0
- package/package.json +1 -1
package/changelog.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
# qase-javascript-commons@2.0.0-beta.9
|
|
2
|
+
|
|
3
|
+
## What's new
|
|
4
|
+
|
|
5
|
+
Improved debug logging for better testing and reporting errors.
|
|
6
|
+
|
|
7
|
+
- Separate `logger` class for use in reporters, supporting logging to console and files.
|
|
8
|
+
- Extra debug logs in both reporter modes: TestOps and Local.
|
|
9
|
+
|
|
10
|
+
Fixed an issue with duplicate test runs created when the testing framework
|
|
11
|
+
(such as Cypress) uses more than one instance of the Qase reporter.
|
|
12
|
+
Now reporter handles Qase test runs in the following way:
|
|
13
|
+
|
|
14
|
+
1. The first instance of the reporter creates a Qase test run and stores the run ID
|
|
15
|
+
in the ENV variable `QASE_TESTOPS_RUN_ID`.
|
|
16
|
+
2. Other instances of the reporter read this variable and report test results
|
|
17
|
+
to the existing test run.
|
|
18
|
+
|
|
19
|
+
Nothing has changed in cases when there is a single instance of a reporter or
|
|
20
|
+
when it is using a test run, created with other tools, such as with an API request
|
|
21
|
+
or manually in the Qase app.
|
|
22
|
+
|
|
1
23
|
# qase-javascript-commons@2.0.0-beta.8
|
|
2
24
|
|
|
3
25
|
## What's new
|
package/dist/models/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { type TestResultType, Relation, Suite, SuiteData } from './test-result';
|
|
2
2
|
export { TestExecution, TestStatusEnum } from './test-execution';
|
|
3
|
-
export { type TestStepType } from './test-step';
|
|
3
|
+
export { type TestStepType, StepType } from './test-step';
|
|
4
4
|
export { StepStatusEnum } from './step-execution';
|
|
5
5
|
export { Attachment } from './attachment';
|
|
6
6
|
export { Report } from './report';
|
package/dist/models/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.StepStatusEnum = exports.TestStatusEnum = void 0;
|
|
3
|
+
exports.StepStatusEnum = exports.StepType = exports.TestStatusEnum = void 0;
|
|
4
4
|
var test_execution_1 = require("./test-execution");
|
|
5
5
|
Object.defineProperty(exports, "TestStatusEnum", { enumerable: true, get: function () { return test_execution_1.TestStatusEnum; } });
|
|
6
|
+
var test_step_1 = require("./test-step");
|
|
7
|
+
Object.defineProperty(exports, "StepType", { enumerable: true, get: function () { return test_step_1.StepType; } });
|
|
6
8
|
var step_execution_1 = require("./step-execution");
|
|
7
9
|
Object.defineProperty(exports, "StepStatusEnum", { enumerable: true, get: function () { return step_execution_1.StepStatusEnum; } });
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StepGherkinData, StepTextData } from './step-data';
|
|
2
2
|
import { StepExecution } from './step-execution';
|
|
3
3
|
import { Attachment } from './attachment';
|
|
4
|
+
export declare enum StepType {
|
|
5
|
+
TEXT = "text",
|
|
6
|
+
GHERKIN = "gherkin"
|
|
7
|
+
}
|
|
4
8
|
export type TestStepType = {
|
|
5
9
|
id: string;
|
|
6
|
-
step_type:
|
|
7
|
-
data:
|
|
10
|
+
step_type: StepType;
|
|
11
|
+
data: StepTextData | StepGherkinData;
|
|
8
12
|
parent_id: string | null;
|
|
9
13
|
execution: StepExecution;
|
|
10
14
|
attachments: Attachment[];
|
package/dist/models/test-step.js
CHANGED
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StepType = void 0;
|
|
4
|
+
var StepType;
|
|
5
|
+
(function (StepType) {
|
|
6
|
+
StepType["TEXT"] = "text";
|
|
7
|
+
StepType["GHERKIN"] = "gherkin";
|
|
8
|
+
})(StepType || (exports.StepType = StepType = {}));
|
package/dist/qase.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AbstractReporter
|
|
1
|
+
import { AbstractReporter } from './reporters';
|
|
2
2
|
import { OptionsType } from './options';
|
|
3
3
|
import { TestResultType } from './models';
|
|
4
4
|
/**
|
|
@@ -36,9 +36,8 @@ export declare class QaseReporter extends AbstractReporter {
|
|
|
36
36
|
private useFallback;
|
|
37
37
|
/**
|
|
38
38
|
* @param {OptionsType} options
|
|
39
|
-
* @param {LoggerInterface} logger
|
|
40
39
|
*/
|
|
41
|
-
constructor(options: OptionsType
|
|
40
|
+
constructor(options: OptionsType);
|
|
42
41
|
/**
|
|
43
42
|
* @returns {Promise<void>}
|
|
44
43
|
*/
|
|
@@ -64,7 +63,6 @@ export declare class QaseReporter extends AbstractReporter {
|
|
|
64
63
|
* @todo implement mode registry
|
|
65
64
|
* @param {ModeEnum} mode
|
|
66
65
|
* @param {OptionsType} options
|
|
67
|
-
* @param {LoggerInterface} logger
|
|
68
66
|
* @returns {ReporterInterface}
|
|
69
67
|
* @private
|
|
70
68
|
*/
|
package/dist/qase.js
CHANGED
|
@@ -66,12 +66,11 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
68
|
* @param {OptionsType} options
|
|
69
|
-
* @param {LoggerInterface} logger
|
|
70
69
|
*/
|
|
71
|
-
constructor(options
|
|
70
|
+
constructor(options) {
|
|
72
71
|
const env = (0, env_1.envToConfig)((0, env_schema_1.default)({ schema: env_1.envValidationSchema }));
|
|
73
72
|
const composedOptions = (0, options_1.composeOptions)(options, env);
|
|
74
|
-
super({ debug: composedOptions.debug, captureLogs: composedOptions.captureLogs }
|
|
73
|
+
super({ debug: composedOptions.debug, captureLogs: composedOptions.captureLogs });
|
|
75
74
|
/**
|
|
76
75
|
* @type {boolean}
|
|
77
76
|
* @private
|
|
@@ -82,17 +81,18 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
82
81
|
* @private
|
|
83
82
|
*/
|
|
84
83
|
this.useFallback = false;
|
|
84
|
+
this.logger.logDebug(`Config: ${JSON.stringify(composedOptions)}`);
|
|
85
85
|
try {
|
|
86
86
|
this.upstreamReporter = this.createReporter(
|
|
87
87
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
88
|
-
composedOptions.mode || options_1.ModeEnum.off, composedOptions
|
|
88
|
+
composedOptions.mode || options_1.ModeEnum.off, composedOptions);
|
|
89
89
|
}
|
|
90
90
|
catch (error) {
|
|
91
91
|
if (error instanceof disabled_exception_1.DisabledException) {
|
|
92
92
|
this.disabled = true;
|
|
93
93
|
}
|
|
94
94
|
else {
|
|
95
|
-
this.logError('Unable to create upstream reporter:', error);
|
|
95
|
+
this.logger.logError('Unable to create upstream reporter:', error);
|
|
96
96
|
if (composedOptions.fallback != undefined) {
|
|
97
97
|
this.disabled = true;
|
|
98
98
|
return;
|
|
@@ -103,7 +103,7 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
103
103
|
try {
|
|
104
104
|
this.fallbackReporter = this.createReporter(
|
|
105
105
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
106
|
-
composedOptions.fallback || options_1.ModeEnum.off, composedOptions
|
|
106
|
+
composedOptions.fallback || options_1.ModeEnum.off, composedOptions);
|
|
107
107
|
}
|
|
108
108
|
catch (error) {
|
|
109
109
|
if (error instanceof disabled_exception_1.DisabledException) {
|
|
@@ -112,7 +112,7 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
else {
|
|
115
|
-
this.logError('Unable to create fallback reporter:', error);
|
|
115
|
+
this.logger.logError('Unable to create fallback reporter:', error);
|
|
116
116
|
if (this.useFallback && this.upstreamReporter === undefined) {
|
|
117
117
|
this.disabled = true;
|
|
118
118
|
}
|
|
@@ -124,11 +124,12 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
124
124
|
*/
|
|
125
125
|
async startTestRun() {
|
|
126
126
|
if (!this.disabled) {
|
|
127
|
+
this.logger.logDebug('Starting test run');
|
|
127
128
|
try {
|
|
128
129
|
await this.upstreamReporter?.startTestRun();
|
|
129
130
|
}
|
|
130
131
|
catch (error) {
|
|
131
|
-
this.logError('Unable to start test run in the upstream reporter: ', error);
|
|
132
|
+
this.logger.logError('Unable to start test run in the upstream reporter: ', error);
|
|
132
133
|
if (this.fallbackReporter == undefined) {
|
|
133
134
|
this.disabled = true;
|
|
134
135
|
return;
|
|
@@ -137,7 +138,7 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
137
138
|
await this.fallbackReporter?.startTestRun();
|
|
138
139
|
}
|
|
139
140
|
catch (error) {
|
|
140
|
-
this.logError('Unable to start test run in the fallback reporter: ', error);
|
|
141
|
+
this.logger.logError('Unable to start test run in the fallback reporter: ', error);
|
|
141
142
|
this.disabled = true;
|
|
142
143
|
}
|
|
143
144
|
}
|
|
@@ -157,7 +158,7 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
157
158
|
await this.upstreamReporter?.addTestResult(result);
|
|
158
159
|
}
|
|
159
160
|
catch (error) {
|
|
160
|
-
this.logError('Unable to add the result to the upstream reporter:', error);
|
|
161
|
+
this.logger.logError('Unable to add the result to the upstream reporter:', error);
|
|
161
162
|
if (this.fallbackReporter == undefined) {
|
|
162
163
|
this.disabled = true;
|
|
163
164
|
return;
|
|
@@ -179,7 +180,7 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
179
180
|
await this.fallbackReporter?.addTestResult(result);
|
|
180
181
|
}
|
|
181
182
|
catch (error) {
|
|
182
|
-
this.logError('Unable to add the result to the fallback reporter:', error);
|
|
183
|
+
this.logger.logError('Unable to add the result to the fallback reporter:', error);
|
|
183
184
|
this.disabled = true;
|
|
184
185
|
}
|
|
185
186
|
}
|
|
@@ -188,6 +189,7 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
188
189
|
*/
|
|
189
190
|
async publish() {
|
|
190
191
|
if (!this.disabled) {
|
|
192
|
+
this.logger.logDebug('Publishing test run results');
|
|
191
193
|
if (this.useFallback) {
|
|
192
194
|
await this.publishFallback();
|
|
193
195
|
}
|
|
@@ -195,7 +197,7 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
195
197
|
await this.upstreamReporter?.publish();
|
|
196
198
|
}
|
|
197
199
|
catch (error) {
|
|
198
|
-
this.logError('Unable to publish the run results to the upstream reporter:', error);
|
|
200
|
+
this.logger.logError('Unable to publish the run results to the upstream reporter:', error);
|
|
199
201
|
if (this.fallbackReporter == undefined) {
|
|
200
202
|
this.disabled = true;
|
|
201
203
|
return;
|
|
@@ -216,7 +218,7 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
216
218
|
await this.fallbackReporter?.publish();
|
|
217
219
|
}
|
|
218
220
|
catch (error) {
|
|
219
|
-
this.logError('Unable to publish the run results to the fallback reporter:', error);
|
|
221
|
+
this.logger.logError('Unable to publish the run results to the fallback reporter:', error);
|
|
220
222
|
this.disabled = true;
|
|
221
223
|
}
|
|
222
224
|
}
|
|
@@ -224,11 +226,10 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
224
226
|
* @todo implement mode registry
|
|
225
227
|
* @param {ModeEnum} mode
|
|
226
228
|
* @param {OptionsType} options
|
|
227
|
-
* @param {LoggerInterface} logger
|
|
228
229
|
* @returns {ReporterInterface}
|
|
229
230
|
* @private
|
|
230
231
|
*/
|
|
231
|
-
createReporter(mode, options
|
|
232
|
+
createReporter(mode, options) {
|
|
232
233
|
const { frameworkPackage, frameworkName, reporterName, environment, report = {}, testops = {}, ...commonOptions } = options;
|
|
233
234
|
switch (mode) {
|
|
234
235
|
case options_1.ModeEnum.testops: {
|
|
@@ -259,7 +260,7 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
259
260
|
batch,
|
|
260
261
|
debug: commonOptions.debug,
|
|
261
262
|
captureLogs: commonOptions.captureLogs,
|
|
262
|
-
}, apiClient,
|
|
263
|
+
}, apiClient, typeof environment === 'number' ? environment : undefined);
|
|
263
264
|
}
|
|
264
265
|
case options_1.ModeEnum.report: {
|
|
265
266
|
const localOptions = report.connections?.[writer_1.DriverEnum.local];
|
|
@@ -267,7 +268,7 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
267
268
|
return new reporters_1.ReportReporter({
|
|
268
269
|
debug: commonOptions.debug,
|
|
269
270
|
captureLogs: commonOptions.captureLogs,
|
|
270
|
-
}, writer,
|
|
271
|
+
}, writer, typeof environment === 'number' ? environment.toString() : environment, testops.run?.id);
|
|
271
272
|
}
|
|
272
273
|
case options_1.ModeEnum.off:
|
|
273
274
|
throw new disabled_exception_1.DisabledException();
|
|
@@ -280,7 +281,7 @@ class QaseReporter extends reporters_1.AbstractReporter {
|
|
|
280
281
|
* @private
|
|
281
282
|
*/
|
|
282
283
|
logTestItem(test) {
|
|
283
|
-
this.log(resultLogMap[test.execution.status](test));
|
|
284
|
+
this.logger.log(resultLogMap[test.execution.status](test));
|
|
284
285
|
}
|
|
285
286
|
}
|
|
286
287
|
exports.QaseReporter = QaseReporter;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { TestResultType } from '../models';
|
|
2
2
|
export interface LoggerInterface {
|
|
3
3
|
log(message: string): void;
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
logError(message: string, error?: unknown): void;
|
|
5
|
+
logDebug(message: string): void;
|
|
6
6
|
}
|
|
7
7
|
export interface ReporterOptionsType {
|
|
8
8
|
debug?: boolean | undefined;
|
|
@@ -22,17 +22,16 @@ export interface ReporterInterface {
|
|
|
22
22
|
* @implements ReporterInterface
|
|
23
23
|
*/
|
|
24
24
|
export declare abstract class AbstractReporter implements ReporterInterface {
|
|
25
|
-
private logger;
|
|
26
25
|
/**
|
|
27
26
|
* @type {boolean | undefined}
|
|
28
27
|
* @private
|
|
29
28
|
*/
|
|
30
|
-
private readonly
|
|
29
|
+
private readonly captureLogs;
|
|
31
30
|
/**
|
|
32
|
-
* @type {
|
|
31
|
+
* @type {LoggerInterface}
|
|
33
32
|
* @private
|
|
34
33
|
*/
|
|
35
|
-
|
|
34
|
+
protected readonly logger: LoggerInterface;
|
|
36
35
|
/**
|
|
37
36
|
* @type {TestResultType[]}
|
|
38
37
|
* @protected
|
|
@@ -48,10 +47,9 @@ export declare abstract class AbstractReporter implements ReporterInterface {
|
|
|
48
47
|
abstract startTestRun(): Promise<void>;
|
|
49
48
|
/**
|
|
50
49
|
* @param {ReporterOptionsType} options
|
|
51
|
-
* @param {LoggerInterface} logger
|
|
52
50
|
* @protected
|
|
53
51
|
*/
|
|
54
|
-
protected constructor(options: ReporterOptionsType | undefined
|
|
52
|
+
protected constructor(options: ReporterOptionsType | undefined);
|
|
55
53
|
/**
|
|
56
54
|
* @returns {TestResultType[]}
|
|
57
55
|
*/
|
|
@@ -68,32 +66,4 @@ export declare abstract class AbstractReporter implements ReporterInterface {
|
|
|
68
66
|
* @param {TestResultType[]} results
|
|
69
67
|
*/
|
|
70
68
|
setTestResults(results: TestResultType[]): void;
|
|
71
|
-
/**
|
|
72
|
-
* @param {string} message
|
|
73
|
-
* @protected
|
|
74
|
-
*/
|
|
75
|
-
protected log(message: string): void;
|
|
76
|
-
/**
|
|
77
|
-
* @param {string} message
|
|
78
|
-
* @param error
|
|
79
|
-
* @protected
|
|
80
|
-
*/
|
|
81
|
-
protected logError(message: string, error?: unknown): void;
|
|
82
|
-
/**
|
|
83
|
-
* @param {string} message
|
|
84
|
-
* @param error
|
|
85
|
-
* @private
|
|
86
|
-
*/
|
|
87
|
-
private doLogError;
|
|
88
|
-
/**
|
|
89
|
-
* @param {AxiosError} error
|
|
90
|
-
* @private
|
|
91
|
-
*/
|
|
92
|
-
private logApiError;
|
|
93
|
-
/**
|
|
94
|
-
* @param errorFields
|
|
95
|
-
* @returns {string | undefined}
|
|
96
|
-
* @private
|
|
97
|
-
*/
|
|
98
|
-
private formatErrorFields;
|
|
99
69
|
}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.AbstractReporter = void 0;
|
|
7
|
-
const lodash_get_1 = __importDefault(require("lodash.get"));
|
|
8
|
-
const qase_error_1 = require("../utils/qase-error");
|
|
9
|
-
const is_axios_error_1 = require("../utils/is-axios-error");
|
|
10
4
|
const uuid_1 = require("uuid");
|
|
5
|
+
const logger_1 = require("../utils/logger");
|
|
11
6
|
/**
|
|
12
7
|
* @abstract
|
|
13
8
|
* @class AbstractReporter
|
|
@@ -16,19 +11,17 @@ const uuid_1 = require("uuid");
|
|
|
16
11
|
class AbstractReporter {
|
|
17
12
|
/**
|
|
18
13
|
* @param {ReporterOptionsType} options
|
|
19
|
-
* @param {LoggerInterface} logger
|
|
20
14
|
* @protected
|
|
21
15
|
*/
|
|
22
|
-
constructor(options
|
|
23
|
-
this.logger = logger;
|
|
16
|
+
constructor(options) {
|
|
24
17
|
/**
|
|
25
18
|
* @type {TestResultType[]}
|
|
26
19
|
* @protected
|
|
27
20
|
*/
|
|
28
21
|
this.results = [];
|
|
29
22
|
const { debug, captureLogs } = options ?? {};
|
|
30
|
-
this.debug = debug;
|
|
31
23
|
this.captureLogs = captureLogs;
|
|
24
|
+
this.logger = new logger_1.Logger({ debug });
|
|
32
25
|
}
|
|
33
26
|
/**
|
|
34
27
|
* @returns {TestResultType[]}
|
|
@@ -47,6 +40,7 @@ class AbstractReporter {
|
|
|
47
40
|
*/
|
|
48
41
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
49
42
|
async addTestResult(result) {
|
|
43
|
+
this.logger.logDebug(`Adding test result: ${JSON.stringify(result)}`);
|
|
50
44
|
if (result.testops_id === null || !Array.isArray(result.testops_id)) {
|
|
51
45
|
this.results.push(result);
|
|
52
46
|
return;
|
|
@@ -70,79 +64,5 @@ class AbstractReporter {
|
|
|
70
64
|
setTestResults(results) {
|
|
71
65
|
this.results = results;
|
|
72
66
|
}
|
|
73
|
-
/**
|
|
74
|
-
* @param {string} message
|
|
75
|
-
* @protected
|
|
76
|
-
*/
|
|
77
|
-
log(message) {
|
|
78
|
-
if (this.debug) {
|
|
79
|
-
this.logger.log(`qase: ${message}`);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* @param {string} message
|
|
84
|
-
* @param error
|
|
85
|
-
* @protected
|
|
86
|
-
*/
|
|
87
|
-
logError(message, error) {
|
|
88
|
-
this.doLogError(`qase: ${message}`, error);
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* @param {string} message
|
|
92
|
-
* @param error
|
|
93
|
-
* @private
|
|
94
|
-
*/
|
|
95
|
-
doLogError(message, error) {
|
|
96
|
-
this.logger.log(message);
|
|
97
|
-
this.logger.group();
|
|
98
|
-
if (error instanceof Error) {
|
|
99
|
-
if ((0, is_axios_error_1.isAxiosError)(error)) {
|
|
100
|
-
this.logApiError(error);
|
|
101
|
-
}
|
|
102
|
-
else if (error instanceof qase_error_1.QaseError && error.cause) {
|
|
103
|
-
this.doLogError('Caused by:', error.cause);
|
|
104
|
-
}
|
|
105
|
-
this.logger.log(`${error.stack || `${error.name}: ${error.message}`}`);
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
this.logger.log(String(error));
|
|
109
|
-
}
|
|
110
|
-
this.logger.groupEnd();
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* @param {AxiosError} error
|
|
114
|
-
* @private
|
|
115
|
-
*/
|
|
116
|
-
logApiError(error) {
|
|
117
|
-
const errorMessage = (0, lodash_get_1.default)(error, 'response.data.errorMessage')
|
|
118
|
-
?? (0, lodash_get_1.default)(error, 'response.data.error')
|
|
119
|
-
?? (0, lodash_get_1.default)(error, 'response.statusText')
|
|
120
|
-
?? 'Unknown error';
|
|
121
|
-
const errorFields = this.formatErrorFields((0, lodash_get_1.default)(error, 'response.data.errorFields'));
|
|
122
|
-
this.logger.log(`Message: ${String(errorMessage)}`);
|
|
123
|
-
if (errorFields) {
|
|
124
|
-
this.logger.group();
|
|
125
|
-
this.logger.log(errorFields);
|
|
126
|
-
this.logger.groupEnd();
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* @param errorFields
|
|
131
|
-
* @returns {string | undefined}
|
|
132
|
-
* @private
|
|
133
|
-
*/
|
|
134
|
-
formatErrorFields(errorFields) {
|
|
135
|
-
if (Array.isArray(errorFields)) {
|
|
136
|
-
return errorFields.reduce((acc, item) => {
|
|
137
|
-
const field = (0, lodash_get_1.default)(item, 'field');
|
|
138
|
-
const error = (0, lodash_get_1.default)(item, 'error');
|
|
139
|
-
if (field && error) {
|
|
140
|
-
return acc + `${String(field)}: ${String(error)}\n`;
|
|
141
|
-
}
|
|
142
|
-
return acc;
|
|
143
|
-
}, '');
|
|
144
|
-
}
|
|
145
|
-
return undefined;
|
|
146
|
-
}
|
|
147
67
|
}
|
|
148
68
|
exports.AbstractReporter = AbstractReporter;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AbstractReporter,
|
|
1
|
+
import { AbstractReporter, ReporterOptionsType } from './abstract-reporter';
|
|
2
2
|
import { WriterInterface } from '../writer';
|
|
3
3
|
/**
|
|
4
4
|
* @class ReportReporter
|
|
@@ -12,11 +12,10 @@ export declare class ReportReporter extends AbstractReporter {
|
|
|
12
12
|
/**
|
|
13
13
|
* @param {ReporterOptionsType} options
|
|
14
14
|
* @param {WriterInterface} writer
|
|
15
|
-
* @param {LoggerInterface} logger
|
|
16
15
|
* @param {string | undefined} environment
|
|
17
16
|
* @param {number | undefined} runId
|
|
18
17
|
*/
|
|
19
|
-
constructor(options: ReporterOptionsType | undefined, writer: WriterInterface,
|
|
18
|
+
constructor(options: ReporterOptionsType | undefined, writer: WriterInterface, environment?: string, runId?: number);
|
|
20
19
|
/**
|
|
21
20
|
* @returns {Promise<void>}
|
|
22
21
|
*/
|
|
@@ -37,12 +37,11 @@ class ReportReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
37
37
|
/**
|
|
38
38
|
* @param {ReporterOptionsType} options
|
|
39
39
|
* @param {WriterInterface} writer
|
|
40
|
-
* @param {LoggerInterface} logger
|
|
41
40
|
* @param {string | undefined} environment
|
|
42
41
|
* @param {number | undefined} runId
|
|
43
42
|
*/
|
|
44
|
-
constructor(options, writer,
|
|
45
|
-
super(options
|
|
43
|
+
constructor(options, writer, environment, runId) {
|
|
44
|
+
super(options);
|
|
46
45
|
this.writer = writer;
|
|
47
46
|
this.startTime = Date.now();
|
|
48
47
|
this.environment = environment;
|
|
@@ -60,6 +59,7 @@ class ReportReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
60
59
|
*
|
|
61
60
|
*/
|
|
62
61
|
async publish() {
|
|
62
|
+
this.writer.clearPreviousResults();
|
|
63
63
|
const report = {
|
|
64
64
|
title: 'Test report',
|
|
65
65
|
execution: {
|
|
@@ -120,7 +120,7 @@ class ReportReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
120
120
|
await this.writer.writeTestResult(result);
|
|
121
121
|
}
|
|
122
122
|
const path = await this.writer.writeReport(report);
|
|
123
|
-
this.log(`Report saved to ${path}`);
|
|
123
|
+
this.logger.log(`Report saved to ${path}`);
|
|
124
124
|
}
|
|
125
125
|
/**
|
|
126
126
|
* @param {TestStepType[]} steps
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { QaseApiInterface, ResultStepStatus, TestStepResultCreateStatusEnum } from 'qaseio';
|
|
2
|
-
import { AbstractReporter,
|
|
2
|
+
import { AbstractReporter, ReporterOptionsType } from './abstract-reporter';
|
|
3
3
|
import { StepStatusEnum, TestResultType, TestStatusEnum } from '../models';
|
|
4
4
|
export type TestOpsRunType = {
|
|
5
5
|
id?: number | undefined;
|
|
@@ -93,10 +93,9 @@ export declare class TestOpsReporter extends AbstractReporter {
|
|
|
93
93
|
/**
|
|
94
94
|
* @param {ReporterOptionsType & TestOpsOptionsType} options
|
|
95
95
|
* @param {QaseApiInterface} api
|
|
96
|
-
* @param {LoggerInterface} logger
|
|
97
96
|
* @param {number} environment
|
|
98
97
|
*/
|
|
99
|
-
constructor(options: ReporterOptionsType & TestOpsOptionsType, api: QaseApiInterface,
|
|
98
|
+
constructor(options: ReporterOptionsType & TestOpsOptionsType, api: QaseApiInterface, environment?: number);
|
|
100
99
|
/**
|
|
101
100
|
* @returns {Promise<void>}
|
|
102
101
|
*/
|
|
@@ -19,12 +19,11 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
19
19
|
/**
|
|
20
20
|
* @param {ReporterOptionsType & TestOpsOptionsType} options
|
|
21
21
|
* @param {QaseApiInterface} api
|
|
22
|
-
* @param {LoggerInterface} logger
|
|
23
22
|
* @param {number} environment
|
|
24
23
|
*/
|
|
25
|
-
constructor(options, api,
|
|
24
|
+
constructor(options, api, environment) {
|
|
26
25
|
const { project, uploadAttachments, run, ...restOptions } = options;
|
|
27
|
-
super(restOptions
|
|
26
|
+
super(restOptions);
|
|
28
27
|
this.api = api;
|
|
29
28
|
/**
|
|
30
29
|
* @type {number}
|
|
@@ -72,15 +71,19 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
72
71
|
*/
|
|
73
72
|
async checkOrCreateTestRun() {
|
|
74
73
|
if (this.run.id !== undefined) {
|
|
74
|
+
this.logger.logDebug('Check test run');
|
|
75
75
|
await this.checkRun(this.run.id);
|
|
76
76
|
this.isTestRunReady = true;
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
|
+
this.logger.logDebug('Create test run');
|
|
79
80
|
const { result } = await this.createRun(this.run.title, this.run.description, this.environment);
|
|
80
81
|
if (!result?.id) {
|
|
81
82
|
throw new Error('Cannot create run.');
|
|
82
83
|
}
|
|
84
|
+
this.logger.logDebug(`Test run created: ${result.id}`);
|
|
83
85
|
this.run.id = result.id;
|
|
86
|
+
process.env['QASE_TESTOPS_RUN_ID'] = String(result.id);
|
|
84
87
|
this.isTestRunReady = true;
|
|
85
88
|
}
|
|
86
89
|
/**
|
|
@@ -109,14 +112,14 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
109
112
|
results: results,
|
|
110
113
|
});
|
|
111
114
|
}
|
|
112
|
-
this.
|
|
115
|
+
this.logger.logDebug(`Results sent to Qase: ${testResults.length}`);
|
|
113
116
|
}
|
|
114
117
|
/**
|
|
115
118
|
* @returns {Promise<void>}
|
|
116
119
|
*/
|
|
117
120
|
async publish() {
|
|
118
121
|
if (this.results.length === 0) {
|
|
119
|
-
this.log((0, chalk_1.default) `{yellow No results to send to Qase}`);
|
|
122
|
+
this.logger.log((0, chalk_1.default) `{yellow No results to send to Qase}`);
|
|
120
123
|
return;
|
|
121
124
|
}
|
|
122
125
|
if (this.firstIndex < this.results.length) {
|
|
@@ -127,13 +130,13 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
127
130
|
}
|
|
128
131
|
try {
|
|
129
132
|
await this.api.runs.completeRun(this.projectCode, this.run.id);
|
|
130
|
-
this.log((0, chalk_1.default) `{green Run ${this.run.id} completed}`);
|
|
133
|
+
this.logger.log((0, chalk_1.default) `{green Run ${this.run.id} completed}`);
|
|
131
134
|
}
|
|
132
135
|
catch (error) {
|
|
133
136
|
throw new qase_error_1.QaseError('Error on completing run', { cause: error });
|
|
134
137
|
}
|
|
135
138
|
const runUrl = `${this.baseUrl}/run/${this.projectCode}/dashboard/${this.run.id}`;
|
|
136
|
-
this.log((0, chalk_1.default) `{blue Test run link: ${runUrl}}`);
|
|
139
|
+
this.logger.log((0, chalk_1.default) `{blue Test run link: ${runUrl}}`);
|
|
137
140
|
}
|
|
138
141
|
/**
|
|
139
142
|
* @param {TestResultType} result
|
|
@@ -143,7 +146,7 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
143
146
|
async transformTestResult(result) {
|
|
144
147
|
const attachments = await this.uploadAttachments(result.attachments);
|
|
145
148
|
const steps = await this.transformSteps(result.steps);
|
|
146
|
-
|
|
149
|
+
const model = {
|
|
147
150
|
title: result.title,
|
|
148
151
|
execution: this.getExecution(result.execution),
|
|
149
152
|
testops_id: Array.isArray(result.testops_id) ? null : result.testops_id,
|
|
@@ -153,6 +156,8 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
153
156
|
relations: this.getRelation(result.relations),
|
|
154
157
|
message: result.message,
|
|
155
158
|
};
|
|
159
|
+
this.logger.logDebug(`Transformed result: ${JSON.stringify(model)}`);
|
|
160
|
+
return model;
|
|
156
161
|
}
|
|
157
162
|
/**
|
|
158
163
|
* @param {TestResultType} result
|
|
@@ -183,6 +188,7 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
183
188
|
title: result.title,
|
|
184
189
|
suite_title: result.relations?.suite ? result.relations?.suite?.data.map((suite) => suite.title).join('\t') : null,
|
|
185
190
|
};
|
|
191
|
+
this.logger.logDebug(`Transformed result: ${JSON.stringify(resultCreate)}`);
|
|
186
192
|
return resultCreate;
|
|
187
193
|
}
|
|
188
194
|
/**
|
|
@@ -233,13 +239,23 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
233
239
|
const attachmentHashes = await this.uploadAttachments(step.attachments);
|
|
234
240
|
const resultStep = {
|
|
235
241
|
data: {
|
|
236
|
-
action:
|
|
242
|
+
action: '',
|
|
237
243
|
attachments: attachmentHashes,
|
|
238
244
|
},
|
|
239
245
|
execution: {
|
|
240
246
|
status: TestOpsReporter.stepStatusMap[step.execution.status],
|
|
241
247
|
},
|
|
242
248
|
};
|
|
249
|
+
if (step.step_type === models_1.StepType.TEXT) {
|
|
250
|
+
if ('action' in step.data && resultStep.data != undefined) {
|
|
251
|
+
resultStep.data.action = step.data.action;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (step.step_type === models_1.StepType.GHERKIN) {
|
|
255
|
+
if ('keyword' in step.data && resultStep.data != undefined) {
|
|
256
|
+
resultStep.data.action = step.data.keyword;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
243
259
|
if (step.steps.length > 0) {
|
|
244
260
|
resultStep.steps = await this.transformSteps(step.steps);
|
|
245
261
|
}
|
|
@@ -258,9 +274,18 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
258
274
|
const attachmentHashes = await this.uploadAttachments(step.attachments);
|
|
259
275
|
const resultStep = {
|
|
260
276
|
status: TestOpsReporter.stepStatusMapV1[step.execution.status],
|
|
261
|
-
action: step.data.action,
|
|
262
277
|
attachments: attachmentHashes,
|
|
263
278
|
};
|
|
279
|
+
if (step.step_type === models_1.StepType.TEXT) {
|
|
280
|
+
if ('action' in step.data) {
|
|
281
|
+
resultStep.action = step.data.action;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
if (step.step_type === models_1.StepType.GHERKIN) {
|
|
285
|
+
if ('keyword' in step.data) {
|
|
286
|
+
resultStep.action = step.data.keyword;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
264
289
|
if (step.steps.length > 0) {
|
|
265
290
|
resultStep.steps = await this.transformStepsV1(step.steps);
|
|
266
291
|
}
|
|
@@ -276,7 +301,7 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
276
301
|
async checkRun(runId) {
|
|
277
302
|
try {
|
|
278
303
|
const resp = await this.api.runs.getRun(this.projectCode, runId);
|
|
279
|
-
this.log(`Get run result on checking run "${String(resp.data.result?.id)}"`);
|
|
304
|
+
this.logger.log(`Get run result on checking run "${String(resp.data.result?.id)}"`);
|
|
280
305
|
}
|
|
281
306
|
catch (error) {
|
|
282
307
|
throw new qase_error_1.QaseError('Error on checking run', { cause: error });
|
|
@@ -336,7 +361,7 @@ class TestOpsReporter extends abstract_reporter_1.AbstractReporter {
|
|
|
336
361
|
}
|
|
337
362
|
}
|
|
338
363
|
catch (error) {
|
|
339
|
-
this.logError('Cannot upload attachment:', error);
|
|
364
|
+
this.logger.logError('Cannot upload attachment:', error);
|
|
340
365
|
}
|
|
341
366
|
}
|
|
342
367
|
return acc;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare class Logger {
|
|
2
|
+
private readonly debug;
|
|
3
|
+
private readonly filePath;
|
|
4
|
+
constructor(options: {
|
|
5
|
+
debug?: boolean | undefined;
|
|
6
|
+
dir?: string;
|
|
7
|
+
});
|
|
8
|
+
log(message: string): void;
|
|
9
|
+
logError(message: string, error?: unknown): void;
|
|
10
|
+
logDebug(message: string): void;
|
|
11
|
+
private logToFile;
|
|
12
|
+
private doLogError;
|
|
13
|
+
/**
|
|
14
|
+
* @param {AxiosError} error
|
|
15
|
+
* @private
|
|
16
|
+
*/
|
|
17
|
+
private logApiError;
|
|
18
|
+
/**
|
|
19
|
+
* @param errorFields
|
|
20
|
+
* @returns {string | undefined}
|
|
21
|
+
* @private
|
|
22
|
+
*/
|
|
23
|
+
private formatErrorFields;
|
|
24
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
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
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.Logger = void 0;
|
|
30
|
+
const fs = __importStar(require("fs"));
|
|
31
|
+
const path = __importStar(require("path"));
|
|
32
|
+
const is_axios_error_1 = require("./is-axios-error");
|
|
33
|
+
const qase_error_1 = require("./qase-error");
|
|
34
|
+
const lodash_get_1 = __importDefault(require("lodash.get"));
|
|
35
|
+
class Logger {
|
|
36
|
+
constructor(options) {
|
|
37
|
+
this.debug = options.debug;
|
|
38
|
+
const dir = options.dir ?? './logs';
|
|
39
|
+
if (!fs.existsSync(dir)) {
|
|
40
|
+
fs.mkdirSync(dir);
|
|
41
|
+
}
|
|
42
|
+
this.filePath = path.join(dir, 'log.txt');
|
|
43
|
+
}
|
|
44
|
+
log(message) {
|
|
45
|
+
const logMessage = `[INFO] qase: ${message}`;
|
|
46
|
+
console.log(logMessage);
|
|
47
|
+
if (this.debug) {
|
|
48
|
+
this.logToFile(logMessage);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
logError(message, error) {
|
|
52
|
+
const logMessage = `[ERROR] qase: ${this.doLogError(message, error)}`;
|
|
53
|
+
console.error(logMessage);
|
|
54
|
+
if (this.debug) {
|
|
55
|
+
this.logToFile(logMessage);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
logDebug(message) {
|
|
59
|
+
if (this.debug) {
|
|
60
|
+
const logMessage = `[DEBUG] qase: ${message}`;
|
|
61
|
+
console.log(logMessage);
|
|
62
|
+
this.logToFile(logMessage);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
logToFile(message) {
|
|
66
|
+
const formattedMessage = `[${new Date().toISOString()}] ${message}\n`;
|
|
67
|
+
fs.appendFileSync(this.filePath, formattedMessage);
|
|
68
|
+
}
|
|
69
|
+
doLogError(message, error) {
|
|
70
|
+
let logMessage = message;
|
|
71
|
+
if (error instanceof Error) {
|
|
72
|
+
if ((0, is_axios_error_1.isAxiosError)(error)) {
|
|
73
|
+
logMessage += this.logApiError(error);
|
|
74
|
+
}
|
|
75
|
+
else if (error instanceof qase_error_1.QaseError && error.cause) {
|
|
76
|
+
logMessage += this.doLogError('\n Caused by:', error.cause);
|
|
77
|
+
}
|
|
78
|
+
logMessage += `\n ${error.stack || `${error.name}: ${error.message}`}`;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
logMessage += `\n ${String(error)}`;
|
|
82
|
+
}
|
|
83
|
+
return logMessage;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* @param {AxiosError} error
|
|
87
|
+
* @private
|
|
88
|
+
*/
|
|
89
|
+
logApiError(error) {
|
|
90
|
+
let logMessage = '\n';
|
|
91
|
+
const errorMessage = (0, lodash_get_1.default)(error, 'response.data.errorMessage')
|
|
92
|
+
?? (0, lodash_get_1.default)(error, 'response.data.error')
|
|
93
|
+
?? (0, lodash_get_1.default)(error, 'response.statusText')
|
|
94
|
+
?? 'Unknown error';
|
|
95
|
+
const errorFields = this.formatErrorFields((0, lodash_get_1.default)(error, 'response.data.errorFields'));
|
|
96
|
+
logMessage += `Message: ${String(errorMessage)}`;
|
|
97
|
+
if (errorFields) {
|
|
98
|
+
logMessage += `\n ${errorFields}`;
|
|
99
|
+
}
|
|
100
|
+
return logMessage;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* @param errorFields
|
|
104
|
+
* @returns {string | undefined}
|
|
105
|
+
* @private
|
|
106
|
+
*/
|
|
107
|
+
formatErrorFields(errorFields) {
|
|
108
|
+
if (Array.isArray(errorFields)) {
|
|
109
|
+
return errorFields.reduce((acc, item) => {
|
|
110
|
+
const field = (0, lodash_get_1.default)(item, 'field');
|
|
111
|
+
const error = (0, lodash_get_1.default)(item, 'error');
|
|
112
|
+
if (field && error) {
|
|
113
|
+
return acc + `${String(field)}: ${String(error)}\n`;
|
|
114
|
+
}
|
|
115
|
+
return acc;
|
|
116
|
+
}, '');
|
|
117
|
+
}
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
exports.Logger = Logger;
|
|
@@ -17,6 +17,10 @@ export declare class FsWriter implements WriterInterface {
|
|
|
17
17
|
* @param {FsWriterOptionsType | undefined} options
|
|
18
18
|
*/
|
|
19
19
|
constructor(options: FsWriterOptionsType | undefined);
|
|
20
|
+
/**
|
|
21
|
+
* @returns {void}
|
|
22
|
+
*/
|
|
23
|
+
clearPreviousResults(): void;
|
|
20
24
|
/**
|
|
21
25
|
* @param {Attachment[]} attachments
|
|
22
26
|
* @returns {Attachment[]}
|
|
@@ -32,4 +36,5 @@ export declare class FsWriter implements WriterInterface {
|
|
|
32
36
|
* @param {TestResultType} result
|
|
33
37
|
*/
|
|
34
38
|
writeTestResult(result: TestResultType): Promise<void>;
|
|
39
|
+
private deleteFolderRecursive;
|
|
35
40
|
}
|
package/dist/writer/fs-writer.js
CHANGED
|
@@ -47,6 +47,12 @@ class FsWriter {
|
|
|
47
47
|
this.formatter = new formatter_1.JsonpFormatter();
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* @returns {void}
|
|
52
|
+
*/
|
|
53
|
+
clearPreviousResults() {
|
|
54
|
+
this.deleteFolderRecursive(this.path);
|
|
55
|
+
}
|
|
50
56
|
/**
|
|
51
57
|
* @param {Attachment[]} attachments
|
|
52
58
|
* @returns {Attachment[]}
|
|
@@ -102,5 +108,19 @@ class FsWriter {
|
|
|
102
108
|
const filePath = path.join(resultsPath, `${result.id}.${this.format}`);
|
|
103
109
|
(0, fs_1.writeFileSync)(filePath, await this.formatter.format(result));
|
|
104
110
|
}
|
|
111
|
+
deleteFolderRecursive(directoryPath) {
|
|
112
|
+
if ((0, fs_1.existsSync)(directoryPath)) {
|
|
113
|
+
(0, fs_1.readdirSync)(directoryPath).forEach((file) => {
|
|
114
|
+
const curPath = path.join(directoryPath, file);
|
|
115
|
+
if ((0, fs_1.lstatSync)(curPath).isDirectory()) { // recurse
|
|
116
|
+
this.deleteFolderRecursive(curPath);
|
|
117
|
+
}
|
|
118
|
+
else { // delete file
|
|
119
|
+
(0, fs_1.unlinkSync)(curPath);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
(0, fs_1.rmdirSync)(directoryPath);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
105
125
|
}
|
|
106
126
|
exports.FsWriter = FsWriter;
|