@tiden/reporter-commons 0.1.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.
- package/CHANGELOG.md +25 -0
- package/LICENSE +201 -0
- package/README.md +34 -0
- package/dist/client/interface.d.ts +8 -0
- package/dist/client/interface.js +2 -0
- package/dist/client/reporter-api-models.d.ts +96 -0
- package/dist/client/reporter-api-models.js +2 -0
- package/dist/client/reporter-api.d.ts +14 -0
- package/dist/client/reporter-api.js +25 -0
- package/dist/client/services/api-error-handler.d.ts +10 -0
- package/dist/client/services/api-error-handler.js +44 -0
- package/dist/client/services/attachment-service.d.ts +29 -0
- package/dist/client/services/attachment-service.js +268 -0
- package/dist/client/services/result-transformer.d.ts +21 -0
- package/dist/client/services/result-transformer.js +180 -0
- package/dist/client/services/run-service.d.ts +20 -0
- package/dist/client/services/run-service.js +68 -0
- package/dist/client/tiden-client.d.ts +34 -0
- package/dist/client/tiden-client.js +99 -0
- package/dist/client/tiden-http.d.ts +11 -0
- package/dist/client/tiden-http.js +23 -0
- package/dist/config/config-loader-interface.d.ts +4 -0
- package/dist/config/config-loader-interface.js +2 -0
- package/dist/config/config-loader.d.ts +10 -0
- package/dist/config/config-loader.js +60 -0
- package/dist/config/config-type.d.ts +2 -0
- package/dist/config/config-type.js +2 -0
- package/dist/config/config-validation-schema.d.ts +212 -0
- package/dist/config/config-validation-schema.js +213 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.js +7 -0
- package/dist/core/options-resolver.d.ts +19 -0
- package/dist/core/options-resolver.js +47 -0
- package/dist/core/reporter-factory.d.ts +18 -0
- package/dist/core/reporter-factory.js +63 -0
- package/dist/core/status-processor.d.ts +17 -0
- package/dist/core/status-processor.js +48 -0
- package/dist/env/env-enum.d.ts +64 -0
- package/dist/env/env-enum.js +75 -0
- package/dist/env/env-to-config.d.ts +7 -0
- package/dist/env/env-to-config.js +60 -0
- package/dist/env/env-type.d.ts +29 -0
- package/dist/env/env-type.js +3 -0
- package/dist/env/env-validation-schema.d.ts +6 -0
- package/dist/env/env-validation-schema.js +113 -0
- package/dist/env/index.d.ts +4 -0
- package/dist/env/index.js +13 -0
- package/dist/formatter/formatter-interface.d.ts +3 -0
- package/dist/formatter/formatter-interface.js +2 -0
- package/dist/formatter/index.d.ts +4 -0
- package/dist/formatter/index.js +9 -0
- package/dist/formatter/json-formatter.d.ts +13 -0
- package/dist/formatter/json-formatter.js +28 -0
- package/dist/formatter/jsonp-formatter.d.ts +13 -0
- package/dist/formatter/jsonp-formatter.js +29 -0
- package/dist/formatter/report-serializer.d.ts +20 -0
- package/dist/formatter/report-serializer.js +92 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +30 -0
- package/dist/internal/filter-positive-ids.d.ts +17 -0
- package/dist/internal/filter-positive-ids.js +38 -0
- package/dist/internal/ids-parser.d.ts +9 -0
- package/dist/internal/ids-parser.js +21 -0
- package/dist/internal/index.d.ts +8 -0
- package/dist/internal/index.js +15 -0
- package/dist/internal/step-parser.d.ts +11 -0
- package/dist/internal/step-parser.js +28 -0
- package/dist/internal/suite-file.d.ts +13 -0
- package/dist/internal/suite-file.js +16 -0
- package/dist/internal/suite-normalizer.d.ts +6 -0
- package/dist/internal/suite-normalizer.js +11 -0
- package/dist/internal/title.d.ts +5 -0
- package/dist/internal/title.js +15 -0
- package/dist/models/attachment.d.ts +8 -0
- package/dist/models/attachment.js +2 -0
- package/dist/models/config/TidenOptionsType.d.ts +33 -0
- package/dist/models/config/TidenOptionsType.js +2 -0
- package/dist/models/configuration.d.ts +12 -0
- package/dist/models/configuration.js +2 -0
- package/dist/models/error.d.ts +7 -0
- package/dist/models/error.js +24 -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 +12 -0
- package/dist/models/host-data.js +2 -0
- package/dist/models/index.d.ts +11 -0
- package/dist/models/index.js +15 -0
- 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 +9 -0
- package/dist/models/stats.js +2 -0
- package/dist/models/step-data.d.ts +19 -0
- package/dist/models/step-data.js +2 -0
- package/dist/models/step-execution.d.ts +13 -0
- package/dist/models/step-execution.js +23 -0
- package/dist/models/test-execution.d.ts +20 -0
- package/dist/models/test-execution.js +32 -0
- package/dist/models/test-result.d.ts +44 -0
- package/dist/models/test-result.js +50 -0
- package/dist/models/test-step.d.ts +18 -0
- package/dist/models/test-step.js +53 -0
- package/dist/options/composeOptions.d.ts +8 -0
- package/dist/options/composeOptions.js +12 -0
- package/dist/options/index.d.ts +3 -0
- package/dist/options/index.js +7 -0
- package/dist/options/mode-enum.d.ts +8 -0
- package/dist/options/mode-enum.js +12 -0
- package/dist/options/options-type.d.ts +38 -0
- package/dist/options/options-type.js +3 -0
- package/dist/profilers/abstract-profiler.d.ts +5 -0
- package/dist/profilers/abstract-profiler.js +6 -0
- package/dist/profilers/fetch-interceptor.d.ts +60 -0
- package/dist/profilers/fetch-interceptor.js +277 -0
- package/dist/profilers/http-interceptor.d.ts +76 -0
- package/dist/profilers/http-interceptor.js +252 -0
- package/dist/profilers/index.d.ts +5 -0
- package/dist/profilers/index.js +11 -0
- package/dist/profilers/network-profiler.d.ts +61 -0
- package/dist/profilers/network-profiler.js +94 -0
- package/dist/reporters/abstract-reporter.d.ts +68 -0
- package/dist/reporters/abstract-reporter.js +78 -0
- package/dist/reporters/index.d.ts +3 -0
- package/dist/reporters/index.js +9 -0
- package/dist/reporters/report-reporter.d.ts +50 -0
- package/dist/reporters/report-reporter.js +167 -0
- package/dist/reporters/run-reporter.d.ts +65 -0
- package/dist/reporters/run-reporter.js +155 -0
- package/dist/reporters/shared/fallback-coordinator.d.ts +47 -0
- package/dist/reporters/shared/fallback-coordinator.js +119 -0
- package/dist/reporters/shared/run-constants.d.ts +11 -0
- package/dist/reporters/shared/run-constants.js +14 -0
- package/dist/state/state.d.ts +16 -0
- package/dist/state/state.js +70 -0
- package/dist/steps/step.d.ts +16 -0
- package/dist/steps/step.js +86 -0
- package/dist/tiden.d.ts +48 -0
- package/dist/tiden.js +223 -0
- package/dist/utils/disabled-exception.d.ts +6 -0
- package/dist/utils/disabled-exception.js +10 -0
- package/dist/utils/get-package-version.d.ts +5 -0
- package/dist/utils/get-package-version.js +25 -0
- package/dist/utils/hostData.d.ts +8 -0
- package/dist/utils/hostData.js +140 -0
- package/dist/utils/is-axios-error.d.ts +6 -0
- package/dist/utils/is-axios-error.js +11 -0
- package/dist/utils/logger.d.ts +33 -0
- package/dist/utils/logger.js +141 -0
- package/dist/utils/mimeTypes.d.ts +5 -0
- package/dist/utils/mimeTypes.js +50 -0
- package/dist/utils/project-mapping-utils.d.ts +17 -0
- package/dist/utils/project-mapping-utils.js +29 -0
- package/dist/utils/signature.d.ts +11 -0
- package/dist/utils/signature.js +34 -0
- package/dist/utils/status-mapping-utils.d.ts +14 -0
- package/dist/utils/status-mapping-utils.js +45 -0
- package/dist/utils/test-status-utils.d.ts +8 -0
- package/dist/utils/test-status-utils.js +152 -0
- package/dist/utils/tiden-error.d.ts +18 -0
- package/dist/utils/tiden-error.js +19 -0
- package/dist/utils/token-masker.d.ts +11 -0
- package/dist/utils/token-masker.js +26 -0
- package/dist/utils/validate-json.d.ts +20 -0
- package/dist/utils/validate-json.js +41 -0
- package/dist/writer/driver-enum.d.ts +13 -0
- package/dist/writer/driver-enum.js +18 -0
- package/dist/writer/fs-writer.d.ts +40 -0
- package/dist/writer/fs-writer.js +139 -0
- package/dist/writer/index.d.ts +3 -0
- package/dist/writer/index.js +8 -0
- package/dist/writer/writer-interface.d.ts +7 -0
- package/dist/writer/writer-interface.js +2 -0
- package/package.json +83 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NetworkProfiler = void 0;
|
|
4
|
+
const node_async_hooks_1 = require("node:async_hooks");
|
|
5
|
+
const abstract_profiler_1 = require("./abstract-profiler");
|
|
6
|
+
const http_interceptor_1 = require("./http-interceptor");
|
|
7
|
+
const fetch_interceptor_1 = require("./fetch-interceptor");
|
|
8
|
+
// Module-level ALS store — shared across all NetworkProfiler instances to
|
|
9
|
+
// allow nested run() calls to see the same context.
|
|
10
|
+
const store = new node_async_hooks_1.AsyncLocalStorage();
|
|
11
|
+
class NetworkProfiler extends abstract_profiler_1.AbstractProfiler {
|
|
12
|
+
skipDomains;
|
|
13
|
+
// Stored for Phase 13 use (controls whether to capture network steps on test failure)
|
|
14
|
+
_trackOnFail;
|
|
15
|
+
/**
|
|
16
|
+
* Fallback accumulator for steps captured outside any run() context.
|
|
17
|
+
* Used by frameworks where test bodies cannot be wrapped in run() (Jest, Vitest, WDIO).
|
|
18
|
+
* Public so interceptors can push to it via ProfilerRef.
|
|
19
|
+
*/
|
|
20
|
+
fallbackSteps = [];
|
|
21
|
+
httpInterceptor = null;
|
|
22
|
+
fetchInterceptor = null;
|
|
23
|
+
constructor(options = {}) {
|
|
24
|
+
super();
|
|
25
|
+
this.skipDomains = options.skipDomains ?? [];
|
|
26
|
+
this._trackOnFail = options.trackOnFail ?? true;
|
|
27
|
+
}
|
|
28
|
+
get trackOnFail() {
|
|
29
|
+
return this._trackOnFail;
|
|
30
|
+
}
|
|
31
|
+
shouldSkip(url) {
|
|
32
|
+
return this.skipDomains.some((domain) => url.includes(domain));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Install HTTP/HTTPS monkey-patches and subscribe to undici diagnostics_channel
|
|
36
|
+
* so that outgoing requests inside a `run()` context are captured as REQUEST steps.
|
|
37
|
+
*/
|
|
38
|
+
enable() {
|
|
39
|
+
this.httpInterceptor = new http_interceptor_1.HttpInterceptor(store, this);
|
|
40
|
+
this.httpInterceptor.install();
|
|
41
|
+
this.fetchInterceptor = new fetch_interceptor_1.FetchInterceptor(store, this);
|
|
42
|
+
this.fetchInterceptor.subscribe();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* No-op per v1.3 design decision (flag-based activation model).
|
|
46
|
+
* Satisfies the AbstractProfiler contract.
|
|
47
|
+
*/
|
|
48
|
+
disable() {
|
|
49
|
+
// Intentional no-op
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Uninstall HTTP/HTTPS monkey-patches and unsubscribe from undici diagnostics_channel —
|
|
53
|
+
* permanently removes interception.
|
|
54
|
+
*/
|
|
55
|
+
restore() {
|
|
56
|
+
this.fetchInterceptor?.unsubscribe();
|
|
57
|
+
this.fetchInterceptor = null;
|
|
58
|
+
this.httpInterceptor?.uninstall();
|
|
59
|
+
this.httpInterceptor = null;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Wraps `fn` in an AsyncLocalStorage context so that any HTTP requests
|
|
63
|
+
* made inside `fn` are attributed to the step accumulator for this call.
|
|
64
|
+
*
|
|
65
|
+
* Returns `{ result, steps }` where `result` is the return value of `fn`
|
|
66
|
+
* and `steps` is the array of REQUEST steps captured during execution.
|
|
67
|
+
*/
|
|
68
|
+
async run(fn) {
|
|
69
|
+
const accumulator = [];
|
|
70
|
+
const result = await store.run(accumulator, fn);
|
|
71
|
+
return { result, steps: accumulator };
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Returns the current ALS store when called inside a `run()` context.
|
|
75
|
+
* Returns an empty array when called outside (no active context).
|
|
76
|
+
*/
|
|
77
|
+
getSteps() {
|
|
78
|
+
return store.getStore() ?? [];
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Returns a copy of steps accumulated outside any run() context (fallback accumulator).
|
|
82
|
+
* Used by frameworks where test bodies cannot be wrapped in run() (Jest, Vitest, WDIO).
|
|
83
|
+
*/
|
|
84
|
+
getAllSteps() {
|
|
85
|
+
return [...this.fallbackSteps];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Clears the fallback step accumulator. Call after collecting steps per test.
|
|
89
|
+
*/
|
|
90
|
+
clearSteps() {
|
|
91
|
+
this.fallbackSteps.length = 0;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.NetworkProfiler = NetworkProfiler;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Attachment, TestResultType } from '../models';
|
|
2
|
+
import { LoggerInterface } from '../utils/logger';
|
|
3
|
+
export interface InternalReporterInterface {
|
|
4
|
+
addTestResult(result: TestResultType): Promise<void>;
|
|
5
|
+
publish(): Promise<void>;
|
|
6
|
+
startTestRun(): Promise<void>;
|
|
7
|
+
getTestResults(): TestResultType[];
|
|
8
|
+
setTestResults(results: TestResultType[]): void;
|
|
9
|
+
sendResults(): Promise<void>;
|
|
10
|
+
complete(): Promise<void>;
|
|
11
|
+
uploadAttachment(attachments: Attachment): Promise<string>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* @abstract
|
|
15
|
+
* @class AbstractReporter
|
|
16
|
+
* @implements InternalReporterInterface
|
|
17
|
+
*/
|
|
18
|
+
export declare abstract class AbstractReporter implements InternalReporterInterface {
|
|
19
|
+
/**
|
|
20
|
+
* @type {LoggerInterface}
|
|
21
|
+
* @private
|
|
22
|
+
*/
|
|
23
|
+
protected readonly logger: LoggerInterface;
|
|
24
|
+
/**
|
|
25
|
+
* @type {TestResultType[]}
|
|
26
|
+
* @protected
|
|
27
|
+
*/
|
|
28
|
+
protected results: TestResultType[];
|
|
29
|
+
/**
|
|
30
|
+
* @returns {Promise<void>}
|
|
31
|
+
*/
|
|
32
|
+
abstract publish(): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* @returns {Promise<void>}
|
|
35
|
+
*/
|
|
36
|
+
abstract startTestRun(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* @returns {Promise<void>}
|
|
39
|
+
*/
|
|
40
|
+
abstract complete(): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* @returns {Promise<void>}
|
|
43
|
+
*/
|
|
44
|
+
abstract sendResults(): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* @param {Attachment} attachment
|
|
47
|
+
* @returns {Promise<string>}
|
|
48
|
+
*/
|
|
49
|
+
abstract uploadAttachment(attachment: Attachment): Promise<string>;
|
|
50
|
+
/**
|
|
51
|
+
* @protected
|
|
52
|
+
* @param {LoggerInterface} logger
|
|
53
|
+
*/
|
|
54
|
+
protected constructor(logger: LoggerInterface);
|
|
55
|
+
/**
|
|
56
|
+
* @returns {TestResultType[]}
|
|
57
|
+
*/
|
|
58
|
+
getTestResults(): TestResultType[];
|
|
59
|
+
/**
|
|
60
|
+
* @param {TestResultType} result
|
|
61
|
+
*/
|
|
62
|
+
addTestResult(result: TestResultType): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* @param {TestResultType[]} results
|
|
65
|
+
*/
|
|
66
|
+
setTestResults(results: TestResultType[]): void;
|
|
67
|
+
protected removeAnsiEscapeCodes(str: string): string;
|
|
68
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AbstractReporter = void 0;
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
/**
|
|
6
|
+
* @abstract
|
|
7
|
+
* @class AbstractReporter
|
|
8
|
+
* @implements InternalReporterInterface
|
|
9
|
+
*/
|
|
10
|
+
class AbstractReporter {
|
|
11
|
+
/**
|
|
12
|
+
* @type {LoggerInterface}
|
|
13
|
+
* @private
|
|
14
|
+
*/
|
|
15
|
+
logger;
|
|
16
|
+
/**
|
|
17
|
+
* @type {TestResultType[]}
|
|
18
|
+
* @protected
|
|
19
|
+
*/
|
|
20
|
+
results = [];
|
|
21
|
+
/**
|
|
22
|
+
* @protected
|
|
23
|
+
* @param {LoggerInterface} logger
|
|
24
|
+
*/
|
|
25
|
+
constructor(logger) {
|
|
26
|
+
this.logger = logger;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @returns {TestResultType[]}
|
|
30
|
+
*/
|
|
31
|
+
getTestResults() {
|
|
32
|
+
const results = this.results;
|
|
33
|
+
this.results = [];
|
|
34
|
+
return results;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* @param {TestResultType} result
|
|
38
|
+
*/
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
40
|
+
async addTestResult(result) {
|
|
41
|
+
this.logger.logDebug(`Adding test result: ${JSON.stringify(result)}`);
|
|
42
|
+
if (result.execution.stacktrace) {
|
|
43
|
+
result.execution.stacktrace = this.removeAnsiEscapeCodes(result.execution.stacktrace);
|
|
44
|
+
}
|
|
45
|
+
if (result.message) {
|
|
46
|
+
result.message = this.removeAnsiEscapeCodes(result.message);
|
|
47
|
+
}
|
|
48
|
+
if (result.case_id === null || !Array.isArray(result.case_id)) {
|
|
49
|
+
this.results.push(result);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// if we have multiple ids, we need to create multiple test results and set duration to 0 for all but the first one
|
|
53
|
+
let firstCase = true;
|
|
54
|
+
for (const id of result.case_id) {
|
|
55
|
+
const testResultCopy = { ...result, execution: { ...result.execution } };
|
|
56
|
+
testResultCopy.case_id = id;
|
|
57
|
+
testResultCopy.id = (0, uuid_1.v4)();
|
|
58
|
+
if (!firstCase) {
|
|
59
|
+
testResultCopy.execution.duration = 0;
|
|
60
|
+
}
|
|
61
|
+
firstCase = false;
|
|
62
|
+
this.results.push(testResultCopy);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* @param {TestResultType[]} results
|
|
67
|
+
*/
|
|
68
|
+
setTestResults(results) {
|
|
69
|
+
this.results = results;
|
|
70
|
+
}
|
|
71
|
+
removeAnsiEscapeCodes(str) {
|
|
72
|
+
const ansiEscapeSequences = new RegExp([
|
|
73
|
+
'\x1B[[(?);]{0,2}(;?\\d)*.',
|
|
74
|
+
].join('|'), 'g');
|
|
75
|
+
return str.replace(ansiEscapeSequences, '');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.AbstractReporter = AbstractReporter;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RunReporter = exports.ReportReporter = exports.AbstractReporter = void 0;
|
|
4
|
+
var abstract_reporter_1 = require("./abstract-reporter");
|
|
5
|
+
Object.defineProperty(exports, "AbstractReporter", { enumerable: true, get: function () { return abstract_reporter_1.AbstractReporter; } });
|
|
6
|
+
var report_reporter_1 = require("./report-reporter");
|
|
7
|
+
Object.defineProperty(exports, "ReportReporter", { enumerable: true, get: function () { return report_reporter_1.ReportReporter; } });
|
|
8
|
+
var run_reporter_1 = require("./run-reporter");
|
|
9
|
+
Object.defineProperty(exports, "RunReporter", { enumerable: true, get: function () { return run_reporter_1.RunReporter; } });
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { AbstractReporter } from './abstract-reporter';
|
|
2
|
+
import { Attachment } from '../models';
|
|
3
|
+
import { WriterInterface } from '../writer';
|
|
4
|
+
import { LoggerInterface } from '../utils/logger';
|
|
5
|
+
import { HostData } from '../models/host-data';
|
|
6
|
+
import { ReportSerializerInterface } from '../formatter/report-serializer';
|
|
7
|
+
/**
|
|
8
|
+
* @class ReportReporter
|
|
9
|
+
* @extends AbstractReporter
|
|
10
|
+
*/
|
|
11
|
+
export declare class ReportReporter extends AbstractReporter {
|
|
12
|
+
private writer;
|
|
13
|
+
private frameworkName;
|
|
14
|
+
private reporterName;
|
|
15
|
+
private readonly environment;
|
|
16
|
+
private readonly runId;
|
|
17
|
+
private readonly rootSuite;
|
|
18
|
+
private readonly hostData;
|
|
19
|
+
private readonly serializer;
|
|
20
|
+
private startTime;
|
|
21
|
+
/**
|
|
22
|
+
* @param {LoggerInterface} logger
|
|
23
|
+
* @param {WriterInterface} writer
|
|
24
|
+
* @param {string} frameworkName
|
|
25
|
+
* @param {string} reporterName
|
|
26
|
+
* @param {string | undefined} environment
|
|
27
|
+
* @param {string | undefined} rootSuite
|
|
28
|
+
* @param {number | undefined} runId
|
|
29
|
+
* @param {HostData | undefined} hostData
|
|
30
|
+
* @param {ReportSerializerInterface} serializer
|
|
31
|
+
*/
|
|
32
|
+
constructor(logger: LoggerInterface, writer: WriterInterface, frameworkName: string, reporterName: string, environment?: string, rootSuite?: string, runId?: number, hostData?: HostData, serializer?: ReportSerializerInterface);
|
|
33
|
+
/**
|
|
34
|
+
* @returns {Promise<void>}
|
|
35
|
+
*/
|
|
36
|
+
startTestRun(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* @returns {Promise<void>}
|
|
39
|
+
*
|
|
40
|
+
*/
|
|
41
|
+
publish(): Promise<void>;
|
|
42
|
+
sendResults(): Promise<void>;
|
|
43
|
+
complete(): Promise<void>;
|
|
44
|
+
uploadAttachment(attachment: Attachment): Promise<string>;
|
|
45
|
+
/**
|
|
46
|
+
* @param {TestStepType[]} steps
|
|
47
|
+
* @returns {TestStepType[]}
|
|
48
|
+
*/
|
|
49
|
+
private copyStepAttachments;
|
|
50
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReportReporter = void 0;
|
|
4
|
+
const abstract_reporter_1 = require("./abstract-reporter");
|
|
5
|
+
const models_1 = require("../models");
|
|
6
|
+
const hostData_1 = require("../utils/hostData");
|
|
7
|
+
const report_serializer_1 = require("../formatter/report-serializer");
|
|
8
|
+
/**
|
|
9
|
+
* @class ReportReporter
|
|
10
|
+
* @extends AbstractReporter
|
|
11
|
+
*/
|
|
12
|
+
class ReportReporter extends abstract_reporter_1.AbstractReporter {
|
|
13
|
+
writer;
|
|
14
|
+
frameworkName;
|
|
15
|
+
reporterName;
|
|
16
|
+
environment;
|
|
17
|
+
runId;
|
|
18
|
+
rootSuite;
|
|
19
|
+
hostData;
|
|
20
|
+
serializer;
|
|
21
|
+
startTime = Date.now();
|
|
22
|
+
/**
|
|
23
|
+
* @param {LoggerInterface} logger
|
|
24
|
+
* @param {WriterInterface} writer
|
|
25
|
+
* @param {string} frameworkName
|
|
26
|
+
* @param {string} reporterName
|
|
27
|
+
* @param {string | undefined} environment
|
|
28
|
+
* @param {string | undefined} rootSuite
|
|
29
|
+
* @param {number | undefined} runId
|
|
30
|
+
* @param {HostData | undefined} hostData
|
|
31
|
+
* @param {ReportSerializerInterface} serializer
|
|
32
|
+
*/
|
|
33
|
+
constructor(logger, writer, frameworkName, reporterName, environment, rootSuite, runId, hostData, serializer = new report_serializer_1.ReportSerializer()) {
|
|
34
|
+
super(logger);
|
|
35
|
+
this.writer = writer;
|
|
36
|
+
this.frameworkName = frameworkName;
|
|
37
|
+
this.reporterName = reporterName;
|
|
38
|
+
this.environment = environment;
|
|
39
|
+
this.runId = runId;
|
|
40
|
+
this.rootSuite = rootSuite;
|
|
41
|
+
this.hostData = hostData;
|
|
42
|
+
this.serializer = serializer;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* @returns {Promise<void>}
|
|
46
|
+
*/
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
48
|
+
async startTestRun() {
|
|
49
|
+
this.startTime = Date.now();
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* @returns {Promise<void>}
|
|
53
|
+
*
|
|
54
|
+
*/
|
|
55
|
+
async publish() {
|
|
56
|
+
await this.sendResults();
|
|
57
|
+
await this.complete();
|
|
58
|
+
}
|
|
59
|
+
async sendResults() {
|
|
60
|
+
this.writer.clearPreviousResults();
|
|
61
|
+
for (const result of this.results) {
|
|
62
|
+
if (result.attachments.length > 0) {
|
|
63
|
+
result.attachments = this.writer.writeAttachment(result.attachments);
|
|
64
|
+
}
|
|
65
|
+
result.steps = this.copyStepAttachments(result.steps);
|
|
66
|
+
result.run_id = this.runId ?? null;
|
|
67
|
+
if (result.relations != null && this.rootSuite != null) {
|
|
68
|
+
const data = {
|
|
69
|
+
title: this.rootSuite,
|
|
70
|
+
public_id: null,
|
|
71
|
+
};
|
|
72
|
+
result.relations.suite?.data.unshift(data);
|
|
73
|
+
}
|
|
74
|
+
else if (this.rootSuite != null) {
|
|
75
|
+
result.relations = {
|
|
76
|
+
suite: {
|
|
77
|
+
data: [
|
|
78
|
+
{
|
|
79
|
+
title: this.rootSuite,
|
|
80
|
+
public_id: null,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// Serialize to spec-compliant format before writing
|
|
87
|
+
const serialized = this.serializer.serializeResult(result);
|
|
88
|
+
await this.writer.writeTestResult(serialized);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async complete() {
|
|
92
|
+
const endTime = Date.now();
|
|
93
|
+
const report = {
|
|
94
|
+
title: 'Test run',
|
|
95
|
+
execution: {
|
|
96
|
+
start_time: this.startTime / 1000,
|
|
97
|
+
end_time: endTime / 1000,
|
|
98
|
+
duration: endTime - this.startTime,
|
|
99
|
+
cumulative_duration: 0,
|
|
100
|
+
},
|
|
101
|
+
stats: {
|
|
102
|
+
total: 0,
|
|
103
|
+
passed: 0,
|
|
104
|
+
failed: 0,
|
|
105
|
+
skipped: 0,
|
|
106
|
+
blocked: 0,
|
|
107
|
+
invalid: 0,
|
|
108
|
+
muted: 0,
|
|
109
|
+
},
|
|
110
|
+
results: [],
|
|
111
|
+
threads: [],
|
|
112
|
+
suites: [],
|
|
113
|
+
environment: this.environment ?? '',
|
|
114
|
+
host_data: this.hostData ?? (0, hostData_1.getHostInfo)(this.frameworkName, this.reporterName),
|
|
115
|
+
};
|
|
116
|
+
for (const result of this.results) {
|
|
117
|
+
report.stats.total++;
|
|
118
|
+
switch (result.execution.status) {
|
|
119
|
+
case models_1.TestStatusEnum.passed:
|
|
120
|
+
report.stats.passed++;
|
|
121
|
+
break;
|
|
122
|
+
case models_1.TestStatusEnum.failed:
|
|
123
|
+
report.stats.failed++;
|
|
124
|
+
break;
|
|
125
|
+
case models_1.TestStatusEnum.skipped:
|
|
126
|
+
report.stats.skipped++;
|
|
127
|
+
break;
|
|
128
|
+
case models_1.TestStatusEnum.invalid:
|
|
129
|
+
report.stats.invalid++;
|
|
130
|
+
break;
|
|
131
|
+
case models_1.TestStatusEnum.blocked:
|
|
132
|
+
report.stats.blocked++;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
report.execution.cumulative_duration += result.execution.duration ?? 0;
|
|
136
|
+
report.results.push({
|
|
137
|
+
duration: result.execution.duration ?? 0,
|
|
138
|
+
id: result.id,
|
|
139
|
+
status: result.execution.status,
|
|
140
|
+
thread: result.execution.thread,
|
|
141
|
+
title: result.title,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
const path = await this.writer.writeReport(report);
|
|
145
|
+
this.logger.log(`Report saved to ${path}`);
|
|
146
|
+
}
|
|
147
|
+
uploadAttachment(attachment) {
|
|
148
|
+
this.writer.writeAttachment([attachment]);
|
|
149
|
+
return Promise.resolve('');
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* @param {TestStepType[]} steps
|
|
153
|
+
* @returns {TestStepType[]}
|
|
154
|
+
*/
|
|
155
|
+
copyStepAttachments(steps) {
|
|
156
|
+
for (const step of steps) {
|
|
157
|
+
if (step.attachments.length > 0) {
|
|
158
|
+
step.attachments = this.writer.writeAttachment(step.attachments);
|
|
159
|
+
}
|
|
160
|
+
if (step.steps.length > 0) {
|
|
161
|
+
step.steps = this.copyStepAttachments(step.steps);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return steps;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
exports.ReportReporter = ReportReporter;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { AbstractReporter } from './abstract-reporter';
|
|
2
|
+
import { Attachment, TestResultType } from '../models';
|
|
3
|
+
import { LoggerInterface } from '../utils/logger';
|
|
4
|
+
import { IClient } from '../client/interface';
|
|
5
|
+
/**
|
|
6
|
+
* @class RunReporter
|
|
7
|
+
* @extends AbstractReporter
|
|
8
|
+
*/
|
|
9
|
+
export declare class RunReporter extends AbstractReporter {
|
|
10
|
+
private api;
|
|
11
|
+
private withState;
|
|
12
|
+
/** Not read internally (no dashboard link without a workspace id) — kept for callers/telemetry. */
|
|
13
|
+
readonly projectCode: string;
|
|
14
|
+
private readonly batchSize;
|
|
15
|
+
private runId;
|
|
16
|
+
private firstIndex;
|
|
17
|
+
private isTestRunReady;
|
|
18
|
+
private mutex;
|
|
19
|
+
/**
|
|
20
|
+
* @param {LoggerInterface} logger
|
|
21
|
+
* @param {IClient} api
|
|
22
|
+
* @param {boolean} withState
|
|
23
|
+
* @param {string} projectCode
|
|
24
|
+
* @param {number | undefined} batchSize
|
|
25
|
+
*/
|
|
26
|
+
constructor(logger: LoggerInterface, api: IClient, withState: boolean,
|
|
27
|
+
/** Not read internally (no dashboard link without a workspace id) — kept for callers/telemetry. */
|
|
28
|
+
projectCode: string, batchSize?: number, runId?: number);
|
|
29
|
+
/**
|
|
30
|
+
* @returns {Promise<void>}
|
|
31
|
+
*/
|
|
32
|
+
startTestRun(): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* @param {TestResultType} result
|
|
35
|
+
* @returns {Promise<void>}
|
|
36
|
+
*/
|
|
37
|
+
addTestResult(result: TestResultType): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* @returns {Promise<void>}
|
|
40
|
+
*/
|
|
41
|
+
private checkOrCreateTestRun;
|
|
42
|
+
/**
|
|
43
|
+
* @returns {Promise<void>}
|
|
44
|
+
* @param testResults
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
private publishResults;
|
|
48
|
+
/**
|
|
49
|
+
* @returns {Promise<void>}
|
|
50
|
+
*/
|
|
51
|
+
publish(): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* @returns {Promise<void>}
|
|
54
|
+
*/
|
|
55
|
+
sendResults(): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* @param {Attachment} attachment
|
|
58
|
+
* @returns {Promise<string>}
|
|
59
|
+
*/
|
|
60
|
+
uploadAttachment(attachment: Attachment): Promise<string>;
|
|
61
|
+
/**
|
|
62
|
+
* @returns {Promise<void>}
|
|
63
|
+
*/
|
|
64
|
+
complete(): Promise<void>;
|
|
65
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RunReporter = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const abstract_reporter_1 = require("./abstract-reporter");
|
|
9
|
+
const models_1 = require("../models");
|
|
10
|
+
const state_1 = require("../state/state");
|
|
11
|
+
const async_mutex_1 = require("async-mutex");
|
|
12
|
+
const run_constants_1 = require("./shared/run-constants");
|
|
13
|
+
/**
|
|
14
|
+
* @class RunReporter
|
|
15
|
+
* @extends AbstractReporter
|
|
16
|
+
*/
|
|
17
|
+
class RunReporter extends abstract_reporter_1.AbstractReporter {
|
|
18
|
+
api;
|
|
19
|
+
withState;
|
|
20
|
+
projectCode;
|
|
21
|
+
batchSize;
|
|
22
|
+
runId;
|
|
23
|
+
firstIndex = 0;
|
|
24
|
+
isTestRunReady = false;
|
|
25
|
+
mutex = new async_mutex_1.Mutex();
|
|
26
|
+
/**
|
|
27
|
+
* @param {LoggerInterface} logger
|
|
28
|
+
* @param {IClient} api
|
|
29
|
+
* @param {boolean} withState
|
|
30
|
+
* @param {string} projectCode
|
|
31
|
+
* @param {number | undefined} batchSize
|
|
32
|
+
*/
|
|
33
|
+
constructor(logger, api, withState,
|
|
34
|
+
/** Not read internally (no dashboard link without a workspace id) — kept for callers/telemetry. */
|
|
35
|
+
projectCode, batchSize, runId) {
|
|
36
|
+
super(logger);
|
|
37
|
+
this.api = api;
|
|
38
|
+
this.withState = withState;
|
|
39
|
+
this.projectCode = projectCode;
|
|
40
|
+
this.batchSize = Math.min(batchSize ?? run_constants_1.DEFAULT_BATCH_SIZE, run_constants_1.MAX_BATCH_SIZE);
|
|
41
|
+
this.runId = runId;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* @returns {Promise<void>}
|
|
45
|
+
*/
|
|
46
|
+
async startTestRun() {
|
|
47
|
+
this.runId = undefined;
|
|
48
|
+
this.isTestRunReady = false;
|
|
49
|
+
this.firstIndex = 0;
|
|
50
|
+
this.results = [];
|
|
51
|
+
await this.checkOrCreateTestRun();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* @param {TestResultType} result
|
|
55
|
+
* @returns {Promise<void>}
|
|
56
|
+
*/
|
|
57
|
+
async addTestResult(result) {
|
|
58
|
+
if (result.execution.status === models_1.TestStatusEnum.failed) {
|
|
59
|
+
this.logger.logDebug(`Test run #${this.runId ?? 'unknown'}`);
|
|
60
|
+
}
|
|
61
|
+
const release = await this.mutex.acquire();
|
|
62
|
+
try {
|
|
63
|
+
await super.addTestResult(result);
|
|
64
|
+
if (!this.isTestRunReady) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const countOfResults = this.batchSize + this.firstIndex;
|
|
68
|
+
if (this.results.length >= countOfResults) {
|
|
69
|
+
const firstIndex = this.firstIndex;
|
|
70
|
+
this.firstIndex = countOfResults;
|
|
71
|
+
await this.publishResults(this.results.slice(firstIndex, countOfResults));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
release();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* @returns {Promise<void>}
|
|
80
|
+
*/
|
|
81
|
+
async checkOrCreateTestRun() {
|
|
82
|
+
const runId = await this.api.createRun();
|
|
83
|
+
this.runId = runId;
|
|
84
|
+
process.env['TIDEN_RUN_ID'] = String(runId);
|
|
85
|
+
this.logger.log(`Test run created: #${runId}`);
|
|
86
|
+
if (this.withState) {
|
|
87
|
+
state_1.StateManager.setRunId(runId);
|
|
88
|
+
}
|
|
89
|
+
this.isTestRunReady = true;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* @returns {Promise<void>}
|
|
93
|
+
* @param testResults
|
|
94
|
+
* @private
|
|
95
|
+
*/
|
|
96
|
+
async publishResults(testResults) {
|
|
97
|
+
if (!this.runId) {
|
|
98
|
+
throw new Error('Run ID is not set');
|
|
99
|
+
}
|
|
100
|
+
await this.api.uploadResults(this.runId, testResults);
|
|
101
|
+
this.logger.logDebug(`Results sent to Tiden: ${testResults.length}`);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* @returns {Promise<void>}
|
|
105
|
+
*/
|
|
106
|
+
async publish() {
|
|
107
|
+
const release = await this.mutex.acquire();
|
|
108
|
+
try {
|
|
109
|
+
await this.sendResults();
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
release();
|
|
113
|
+
}
|
|
114
|
+
await this.complete();
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* @returns {Promise<void>}
|
|
118
|
+
*/
|
|
119
|
+
async sendResults() {
|
|
120
|
+
if (this.results.length === 0) {
|
|
121
|
+
this.logger.log((0, chalk_1.default) `{yellow No results to send to Tiden}`);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const remainingResults = this.results.slice(this.firstIndex);
|
|
125
|
+
if (this.firstIndex < this.results.length) {
|
|
126
|
+
if (remainingResults.length <= run_constants_1.DEFAULT_BATCH_SIZE) {
|
|
127
|
+
await this.publishResults(remainingResults);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
for (let i = 0; i < remainingResults.length; i += run_constants_1.DEFAULT_BATCH_SIZE) {
|
|
131
|
+
await this.publishResults(remainingResults.slice(i, i + run_constants_1.DEFAULT_BATCH_SIZE));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Clear results because we don't need to send them again then we use Cypress reporter
|
|
135
|
+
this.results.length = 0;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* @param {Attachment} attachment
|
|
139
|
+
* @returns {Promise<string>}
|
|
140
|
+
*/
|
|
141
|
+
async uploadAttachment(attachment) {
|
|
142
|
+
return await this.api.uploadAttachment(attachment);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* @returns {Promise<void>}
|
|
146
|
+
*/
|
|
147
|
+
async complete() {
|
|
148
|
+
if (!this.runId) {
|
|
149
|
+
throw new Error('Run ID is not set');
|
|
150
|
+
}
|
|
151
|
+
await this.api.completeRun(this.runId);
|
|
152
|
+
this.logger.log((0, chalk_1.default) `{green Run ${this.runId} completed}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
exports.RunReporter = RunReporter;
|