@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.
Files changed (174) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/LICENSE +201 -0
  3. package/README.md +34 -0
  4. package/dist/client/interface.d.ts +8 -0
  5. package/dist/client/interface.js +2 -0
  6. package/dist/client/reporter-api-models.d.ts +96 -0
  7. package/dist/client/reporter-api-models.js +2 -0
  8. package/dist/client/reporter-api.d.ts +14 -0
  9. package/dist/client/reporter-api.js +25 -0
  10. package/dist/client/services/api-error-handler.d.ts +10 -0
  11. package/dist/client/services/api-error-handler.js +44 -0
  12. package/dist/client/services/attachment-service.d.ts +29 -0
  13. package/dist/client/services/attachment-service.js +268 -0
  14. package/dist/client/services/result-transformer.d.ts +21 -0
  15. package/dist/client/services/result-transformer.js +180 -0
  16. package/dist/client/services/run-service.d.ts +20 -0
  17. package/dist/client/services/run-service.js +68 -0
  18. package/dist/client/tiden-client.d.ts +34 -0
  19. package/dist/client/tiden-client.js +99 -0
  20. package/dist/client/tiden-http.d.ts +11 -0
  21. package/dist/client/tiden-http.js +23 -0
  22. package/dist/config/config-loader-interface.d.ts +4 -0
  23. package/dist/config/config-loader-interface.js +2 -0
  24. package/dist/config/config-loader.d.ts +10 -0
  25. package/dist/config/config-loader.js +60 -0
  26. package/dist/config/config-type.d.ts +2 -0
  27. package/dist/config/config-type.js +2 -0
  28. package/dist/config/config-validation-schema.d.ts +212 -0
  29. package/dist/config/config-validation-schema.js +213 -0
  30. package/dist/config/index.d.ts +4 -0
  31. package/dist/config/index.js +7 -0
  32. package/dist/core/options-resolver.d.ts +19 -0
  33. package/dist/core/options-resolver.js +47 -0
  34. package/dist/core/reporter-factory.d.ts +18 -0
  35. package/dist/core/reporter-factory.js +63 -0
  36. package/dist/core/status-processor.d.ts +17 -0
  37. package/dist/core/status-processor.js +48 -0
  38. package/dist/env/env-enum.d.ts +64 -0
  39. package/dist/env/env-enum.js +75 -0
  40. package/dist/env/env-to-config.d.ts +7 -0
  41. package/dist/env/env-to-config.js +60 -0
  42. package/dist/env/env-type.d.ts +29 -0
  43. package/dist/env/env-type.js +3 -0
  44. package/dist/env/env-validation-schema.d.ts +6 -0
  45. package/dist/env/env-validation-schema.js +113 -0
  46. package/dist/env/index.d.ts +4 -0
  47. package/dist/env/index.js +13 -0
  48. package/dist/formatter/formatter-interface.d.ts +3 -0
  49. package/dist/formatter/formatter-interface.js +2 -0
  50. package/dist/formatter/index.d.ts +4 -0
  51. package/dist/formatter/index.js +9 -0
  52. package/dist/formatter/json-formatter.d.ts +13 -0
  53. package/dist/formatter/json-formatter.js +28 -0
  54. package/dist/formatter/jsonp-formatter.d.ts +13 -0
  55. package/dist/formatter/jsonp-formatter.js +29 -0
  56. package/dist/formatter/report-serializer.d.ts +20 -0
  57. package/dist/formatter/report-serializer.js +92 -0
  58. package/dist/index.d.ts +14 -0
  59. package/dist/index.js +30 -0
  60. package/dist/internal/filter-positive-ids.d.ts +17 -0
  61. package/dist/internal/filter-positive-ids.js +38 -0
  62. package/dist/internal/ids-parser.d.ts +9 -0
  63. package/dist/internal/ids-parser.js +21 -0
  64. package/dist/internal/index.d.ts +8 -0
  65. package/dist/internal/index.js +15 -0
  66. package/dist/internal/step-parser.d.ts +11 -0
  67. package/dist/internal/step-parser.js +28 -0
  68. package/dist/internal/suite-file.d.ts +13 -0
  69. package/dist/internal/suite-file.js +16 -0
  70. package/dist/internal/suite-normalizer.d.ts +6 -0
  71. package/dist/internal/suite-normalizer.js +11 -0
  72. package/dist/internal/title.d.ts +5 -0
  73. package/dist/internal/title.js +15 -0
  74. package/dist/models/attachment.d.ts +8 -0
  75. package/dist/models/attachment.js +2 -0
  76. package/dist/models/config/TidenOptionsType.d.ts +33 -0
  77. package/dist/models/config/TidenOptionsType.js +2 -0
  78. package/dist/models/configuration.d.ts +12 -0
  79. package/dist/models/configuration.js +2 -0
  80. package/dist/models/error.d.ts +7 -0
  81. package/dist/models/error.js +24 -0
  82. package/dist/models/execution-sum.d.ts +6 -0
  83. package/dist/models/execution-sum.js +2 -0
  84. package/dist/models/host-data.d.ts +12 -0
  85. package/dist/models/host-data.js +2 -0
  86. package/dist/models/index.d.ts +11 -0
  87. package/dist/models/index.js +15 -0
  88. package/dist/models/report.d.ts +14 -0
  89. package/dist/models/report.js +2 -0
  90. package/dist/models/short-result.d.ts +7 -0
  91. package/dist/models/short-result.js +2 -0
  92. package/dist/models/stats.d.ts +9 -0
  93. package/dist/models/stats.js +2 -0
  94. package/dist/models/step-data.d.ts +19 -0
  95. package/dist/models/step-data.js +2 -0
  96. package/dist/models/step-execution.d.ts +13 -0
  97. package/dist/models/step-execution.js +23 -0
  98. package/dist/models/test-execution.d.ts +20 -0
  99. package/dist/models/test-execution.js +32 -0
  100. package/dist/models/test-result.d.ts +44 -0
  101. package/dist/models/test-result.js +50 -0
  102. package/dist/models/test-step.d.ts +18 -0
  103. package/dist/models/test-step.js +53 -0
  104. package/dist/options/composeOptions.d.ts +8 -0
  105. package/dist/options/composeOptions.js +12 -0
  106. package/dist/options/index.d.ts +3 -0
  107. package/dist/options/index.js +7 -0
  108. package/dist/options/mode-enum.d.ts +8 -0
  109. package/dist/options/mode-enum.js +12 -0
  110. package/dist/options/options-type.d.ts +38 -0
  111. package/dist/options/options-type.js +3 -0
  112. package/dist/profilers/abstract-profiler.d.ts +5 -0
  113. package/dist/profilers/abstract-profiler.js +6 -0
  114. package/dist/profilers/fetch-interceptor.d.ts +60 -0
  115. package/dist/profilers/fetch-interceptor.js +277 -0
  116. package/dist/profilers/http-interceptor.d.ts +76 -0
  117. package/dist/profilers/http-interceptor.js +252 -0
  118. package/dist/profilers/index.d.ts +5 -0
  119. package/dist/profilers/index.js +11 -0
  120. package/dist/profilers/network-profiler.d.ts +61 -0
  121. package/dist/profilers/network-profiler.js +94 -0
  122. package/dist/reporters/abstract-reporter.d.ts +68 -0
  123. package/dist/reporters/abstract-reporter.js +78 -0
  124. package/dist/reporters/index.d.ts +3 -0
  125. package/dist/reporters/index.js +9 -0
  126. package/dist/reporters/report-reporter.d.ts +50 -0
  127. package/dist/reporters/report-reporter.js +167 -0
  128. package/dist/reporters/run-reporter.d.ts +65 -0
  129. package/dist/reporters/run-reporter.js +155 -0
  130. package/dist/reporters/shared/fallback-coordinator.d.ts +47 -0
  131. package/dist/reporters/shared/fallback-coordinator.js +119 -0
  132. package/dist/reporters/shared/run-constants.d.ts +11 -0
  133. package/dist/reporters/shared/run-constants.js +14 -0
  134. package/dist/state/state.d.ts +16 -0
  135. package/dist/state/state.js +70 -0
  136. package/dist/steps/step.d.ts +16 -0
  137. package/dist/steps/step.js +86 -0
  138. package/dist/tiden.d.ts +48 -0
  139. package/dist/tiden.js +223 -0
  140. package/dist/utils/disabled-exception.d.ts +6 -0
  141. package/dist/utils/disabled-exception.js +10 -0
  142. package/dist/utils/get-package-version.d.ts +5 -0
  143. package/dist/utils/get-package-version.js +25 -0
  144. package/dist/utils/hostData.d.ts +8 -0
  145. package/dist/utils/hostData.js +140 -0
  146. package/dist/utils/is-axios-error.d.ts +6 -0
  147. package/dist/utils/is-axios-error.js +11 -0
  148. package/dist/utils/logger.d.ts +33 -0
  149. package/dist/utils/logger.js +141 -0
  150. package/dist/utils/mimeTypes.d.ts +5 -0
  151. package/dist/utils/mimeTypes.js +50 -0
  152. package/dist/utils/project-mapping-utils.d.ts +17 -0
  153. package/dist/utils/project-mapping-utils.js +29 -0
  154. package/dist/utils/signature.d.ts +11 -0
  155. package/dist/utils/signature.js +34 -0
  156. package/dist/utils/status-mapping-utils.d.ts +14 -0
  157. package/dist/utils/status-mapping-utils.js +45 -0
  158. package/dist/utils/test-status-utils.d.ts +8 -0
  159. package/dist/utils/test-status-utils.js +152 -0
  160. package/dist/utils/tiden-error.d.ts +18 -0
  161. package/dist/utils/tiden-error.js +19 -0
  162. package/dist/utils/token-masker.d.ts +11 -0
  163. package/dist/utils/token-masker.js +26 -0
  164. package/dist/utils/validate-json.d.ts +20 -0
  165. package/dist/utils/validate-json.js +41 -0
  166. package/dist/writer/driver-enum.d.ts +13 -0
  167. package/dist/writer/driver-enum.js +18 -0
  168. package/dist/writer/fs-writer.d.ts +40 -0
  169. package/dist/writer/fs-writer.js +139 -0
  170. package/dist/writer/index.d.ts +3 -0
  171. package/dist/writer/index.js +8 -0
  172. package/dist/writer/writer-interface.d.ts +7 -0
  173. package/dist/writer/writer-interface.js +2 -0
  174. package/package.json +83 -0
@@ -0,0 +1,47 @@
1
+ import { InternalReporterInterface } from '../abstract-reporter';
2
+ import { LoggerInterface } from '../../utils/logger';
3
+ export interface FallbackCoordinatorCallbacks {
4
+ onUpstreamFailure?: () => void;
5
+ onFallbackFailure?: () => void;
6
+ onFallbackActivated?: () => void;
7
+ onDisabled?: () => void;
8
+ }
9
+ /**
10
+ * Encapsulates the upstream → fallback → disabled cascade used across all
11
+ * `TidenReporter` lifecycle methods. Keeps both reporters' state (useFallback
12
+ * / disabled) in one place instead of spreading try/catch blocks everywhere.
13
+ */
14
+ export declare class FallbackCoordinator {
15
+ private readonly logger;
16
+ private readonly upstream;
17
+ private readonly fallback;
18
+ private readonly callbacks;
19
+ private useFallback;
20
+ private disabled;
21
+ private onDisabledFired;
22
+ constructor(logger: LoggerInterface, upstream: InternalReporterInterface | undefined, fallback: InternalReporterInterface | undefined, callbacks?: FallbackCoordinatorCallbacks);
23
+ isDisabled(): boolean;
24
+ isUsingFallback(): boolean;
25
+ setDisabled(value: boolean): void;
26
+ setUseFallback(value: boolean): void;
27
+ getUpstream(): InternalReporterInterface | undefined;
28
+ getFallback(): InternalReporterInterface | undefined;
29
+ /**
30
+ * Clear the disabled / useFallback flags so the coordinator can be reused
31
+ * for a fresh test run. Does not re-arm the `onDisabled` callback — it
32
+ * only fires once per coordinator lifetime regardless of resets.
33
+ */
34
+ reset(): void;
35
+ /**
36
+ * Run `op` on the currently active reporter. On upstream failure, switch to
37
+ * the fallback (copying accumulated results over once) and retry. On
38
+ * fallback failure, disable the coordinator.
39
+ *
40
+ * Returns the operation's result, or `undefined` if the coordinator is
41
+ * disabled or the operation produced no value.
42
+ */
43
+ run<T>(op: (reporter: InternalReporterInterface) => Promise<T>, opName: string): Promise<T | undefined>;
44
+ private disable;
45
+ private activateFallback;
46
+ private runOnFallback;
47
+ }
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FallbackCoordinator = void 0;
4
+ /**
5
+ * Encapsulates the upstream → fallback → disabled cascade used across all
6
+ * `TidenReporter` lifecycle methods. Keeps both reporters' state (useFallback
7
+ * / disabled) in one place instead of spreading try/catch blocks everywhere.
8
+ */
9
+ class FallbackCoordinator {
10
+ logger;
11
+ upstream;
12
+ fallback;
13
+ callbacks;
14
+ useFallback = false;
15
+ disabled = false;
16
+ onDisabledFired = false;
17
+ constructor(logger, upstream, fallback, callbacks = {}) {
18
+ this.logger = logger;
19
+ this.upstream = upstream;
20
+ this.fallback = fallback;
21
+ this.callbacks = callbacks;
22
+ }
23
+ isDisabled() {
24
+ return this.disabled;
25
+ }
26
+ isUsingFallback() {
27
+ return this.useFallback;
28
+ }
29
+ setDisabled(value) {
30
+ this.disabled = value;
31
+ }
32
+ setUseFallback(value) {
33
+ this.useFallback = value;
34
+ }
35
+ getUpstream() {
36
+ return this.upstream;
37
+ }
38
+ getFallback() {
39
+ return this.fallback;
40
+ }
41
+ /**
42
+ * Clear the disabled / useFallback flags so the coordinator can be reused
43
+ * for a fresh test run. Does not re-arm the `onDisabled` callback — it
44
+ * only fires once per coordinator lifetime regardless of resets.
45
+ */
46
+ reset() {
47
+ this.disabled = false;
48
+ this.useFallback = false;
49
+ }
50
+ /**
51
+ * Run `op` on the currently active reporter. On upstream failure, switch to
52
+ * the fallback (copying accumulated results over once) and retry. On
53
+ * fallback failure, disable the coordinator.
54
+ *
55
+ * Returns the operation's result, or `undefined` if the coordinator is
56
+ * disabled or the operation produced no value.
57
+ */
58
+ async run(op, opName) {
59
+ if (this.disabled)
60
+ return undefined;
61
+ if (this.useFallback) {
62
+ return this.runOnFallback(op, opName);
63
+ }
64
+ if (!this.upstream) {
65
+ // No upstream configured — route directly to fallback without
66
+ // copying results (there are none to copy).
67
+ if (!this.fallback)
68
+ return undefined;
69
+ this.useFallback = true;
70
+ return this.runOnFallback(op, opName);
71
+ }
72
+ try {
73
+ return await op(this.upstream);
74
+ }
75
+ catch (error) {
76
+ this.logger.logError(`Unable to ${opName} in the upstream reporter:`, error);
77
+ this.callbacks.onUpstreamFailure?.();
78
+ if (!this.fallback) {
79
+ this.disable();
80
+ return undefined;
81
+ }
82
+ this.activateFallback();
83
+ return this.runOnFallback(op, opName);
84
+ }
85
+ }
86
+ disable() {
87
+ if (this.disabled)
88
+ return;
89
+ this.disabled = true;
90
+ if (!this.onDisabledFired) {
91
+ this.onDisabledFired = true;
92
+ this.callbacks.onDisabled?.();
93
+ }
94
+ }
95
+ activateFallback() {
96
+ if (this.useFallback)
97
+ return;
98
+ const results = this.upstream?.getTestResults() ?? [];
99
+ this.fallback?.setTestResults(results);
100
+ this.useFallback = true;
101
+ this.callbacks.onFallbackActivated?.();
102
+ }
103
+ async runOnFallback(op, opName) {
104
+ if (!this.fallback) {
105
+ this.disable();
106
+ return undefined;
107
+ }
108
+ try {
109
+ return await op(this.fallback);
110
+ }
111
+ catch (error) {
112
+ this.logger.logError(`Unable to ${opName} in the fallback reporter:`, error);
113
+ this.callbacks.onFallbackFailure?.();
114
+ this.disable();
115
+ return undefined;
116
+ }
117
+ }
118
+ }
119
+ exports.FallbackCoordinator = FallbackCoordinator;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Default number of test results per upload batch.
3
+ * Used by RunReporter when no explicit batch size is configured.
4
+ */
5
+ export declare const DEFAULT_BATCH_SIZE = 200;
6
+ /**
7
+ * Upper bound on the configurable batch size — protects against
8
+ * unreasonably large `tiden.batch.size` values overwhelming the
9
+ * results:report endpoint in a single request.
10
+ */
11
+ export declare const MAX_BATCH_SIZE = 2000;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_BATCH_SIZE = exports.DEFAULT_BATCH_SIZE = void 0;
4
+ /**
5
+ * Default number of test results per upload batch.
6
+ * Used by RunReporter when no explicit batch size is configured.
7
+ */
8
+ exports.DEFAULT_BATCH_SIZE = 200;
9
+ /**
10
+ * Upper bound on the configurable batch size — protects against
11
+ * unreasonably large `tiden.batch.size` values overwhelming the
12
+ * results:report endpoint in a single request.
13
+ */
14
+ exports.MAX_BATCH_SIZE = 2000;
@@ -0,0 +1,16 @@
1
+ import { ModeEnum } from '../options';
2
+ export interface StateModel {
3
+ RunId: number | undefined;
4
+ Mode: ModeEnum | undefined;
5
+ IsModeChanged: boolean | undefined;
6
+ }
7
+ export declare class StateManager {
8
+ static statePath: string;
9
+ static getState(): StateModel;
10
+ static setRunId(runId: number): void;
11
+ static setMode(mode: ModeEnum): void;
12
+ static setIsModeChanged(isModeChanged: boolean): void;
13
+ static setState(state: StateModel): void;
14
+ static clearState(): void;
15
+ static isStateExists(): boolean;
16
+ }
@@ -0,0 +1,70 @@
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.StateManager = void 0;
7
+ const fs_1 = require("fs");
8
+ const path_1 = __importDefault(require("path"));
9
+ // eslint-disable-next-line @typescript-eslint/no-extraneous-class
10
+ class StateManager {
11
+ static statePath = path_1.default.resolve(__dirname, 'reporterState.json');
12
+ static getState() {
13
+ let state = {
14
+ RunId: undefined,
15
+ Mode: undefined,
16
+ IsModeChanged: undefined,
17
+ };
18
+ if (!this.isStateExists()) {
19
+ return state;
20
+ }
21
+ try {
22
+ const data = (0, fs_1.readFileSync)(this.statePath, 'utf8');
23
+ state = JSON.parse(data);
24
+ }
25
+ catch (err) {
26
+ console.error('Error reading state file:', err);
27
+ }
28
+ return state;
29
+ }
30
+ static setRunId(runId) {
31
+ const state = this.getState();
32
+ state.RunId = runId;
33
+ this.setState(state);
34
+ }
35
+ static setMode(mode) {
36
+ const state = this.getState();
37
+ state.Mode = mode;
38
+ state.IsModeChanged = true;
39
+ this.setState(state);
40
+ }
41
+ static setIsModeChanged(isModeChanged) {
42
+ const state = this.getState();
43
+ state.IsModeChanged = isModeChanged;
44
+ this.setState(state);
45
+ }
46
+ static setState(state) {
47
+ try {
48
+ const data = JSON.stringify(state);
49
+ (0, fs_1.writeFileSync)(this.statePath, data);
50
+ }
51
+ catch (err) {
52
+ console.error('Error writing state file:', err);
53
+ }
54
+ }
55
+ static clearState() {
56
+ if (!this.isStateExists()) {
57
+ return;
58
+ }
59
+ try {
60
+ (0, fs_1.unlinkSync)(this.statePath);
61
+ }
62
+ catch (err) {
63
+ console.error('Error clearing state file:', err);
64
+ }
65
+ }
66
+ static isStateExists() {
67
+ return (0, fs_1.existsSync)(this.statePath);
68
+ }
69
+ }
70
+ exports.StateManager = StateManager;
@@ -0,0 +1,16 @@
1
+ import { Attachment, TestStepType } from '../models';
2
+ export type StepFunction<T = unknown> = (this: TidenStep, step: TidenStep) => T | Promise<T>;
3
+ export declare class TidenStep {
4
+ name: string;
5
+ attachments: Attachment[];
6
+ steps: TestStepType[];
7
+ constructor(name: string);
8
+ attach(attach: {
9
+ name?: string;
10
+ type?: string;
11
+ content?: string;
12
+ paths?: string[] | string;
13
+ }): void;
14
+ step(name: string, body: StepFunction): Promise<void>;
15
+ run(body: StepFunction, messageEmitter: (step: TestStepType) => Promise<void>): Promise<void>;
16
+ }
@@ -0,0 +1,86 @@
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.TidenStep = void 0;
7
+ const uuid_1 = require("uuid");
8
+ const path_1 = __importDefault(require("path"));
9
+ const models_1 = require("../models");
10
+ class TidenStep {
11
+ name = '';
12
+ attachments = [];
13
+ steps = [];
14
+ constructor(name) {
15
+ this.name = name;
16
+ }
17
+ attach(attach) {
18
+ if (attach.paths) {
19
+ const files = Array.isArray(attach.paths) ? attach.paths : [attach.paths];
20
+ for (const file of files) {
21
+ const attachmentName = path_1.default.basename(file);
22
+ const contentType = 'application/octet-stream';
23
+ this.attachments.push({
24
+ id: (0, uuid_1.v4)(),
25
+ file_name: attachmentName,
26
+ mime_type: contentType,
27
+ content: '',
28
+ file_path: file,
29
+ size: 0,
30
+ });
31
+ }
32
+ return;
33
+ }
34
+ if (attach.content) {
35
+ const attachmentName = attach.name ?? 'attachment';
36
+ const contentType = attach.type ?? 'application/octet-stream';
37
+ this.attachments.push({
38
+ id: (0, uuid_1.v4)(),
39
+ file_name: attachmentName,
40
+ mime_type: contentType,
41
+ content: attach.content,
42
+ file_path: null,
43
+ size: attach.content.length,
44
+ });
45
+ }
46
+ }
47
+ async step(name, body) {
48
+ const childStep = new TidenStep(name);
49
+ // eslint-disable-next-line @typescript-eslint/require-await
50
+ await childStep.run(body, async (step) => {
51
+ this.steps.push(step);
52
+ });
53
+ }
54
+ async run(body, messageEmitter) {
55
+ const startMs = Date.now();
56
+ const step = new models_1.TestStepType();
57
+ step.data = {
58
+ action: this.name,
59
+ expected_result: null,
60
+ data: null,
61
+ };
62
+ // Per Tiden API spec: start_time / end_time are Unix epoch seconds (with
63
+ // fractional ms); duration is milliseconds.
64
+ const buildExecution = (status, endMs) => ({
65
+ start_time: startMs / 1000,
66
+ end_time: endMs / 1000,
67
+ status,
68
+ duration: endMs - startMs,
69
+ });
70
+ try {
71
+ await body.call(this, this);
72
+ step.execution = buildExecution(models_1.StepStatusEnum.passed, Date.now());
73
+ step.attachments = this.attachments;
74
+ step.steps = this.steps;
75
+ await messageEmitter(step);
76
+ }
77
+ catch (error) {
78
+ step.execution = buildExecution(models_1.StepStatusEnum.failed, Date.now());
79
+ step.attachments = this.attachments;
80
+ step.steps = this.steps;
81
+ await messageEmitter(step);
82
+ throw error;
83
+ }
84
+ }
85
+ }
86
+ exports.TidenStep = TidenStep;
@@ -0,0 +1,48 @@
1
+ import { OptionsType } from './options';
2
+ import { TestResultType, Attachment } from './models';
3
+ export interface ReporterInterface {
4
+ addTestResult(result: TestResultType): Promise<void>;
5
+ publish(): Promise<void>;
6
+ startTestRun(): void;
7
+ startTestRunAsync(): Promise<void>;
8
+ isCaptureLogs(): boolean;
9
+ getResults(): TestResultType[];
10
+ sendResults(): Promise<void>;
11
+ complete(): Promise<void>;
12
+ uploadAttachment(attachment: Attachment): Promise<string>;
13
+ }
14
+ /**
15
+ * @class TidenReporter
16
+ *
17
+ * Thin orchestrator: delegates to OptionsResolver, ReporterFactory,
18
+ * StatusProcessor, and FallbackCoordinator. Public API is preserved.
19
+ */
20
+ export declare class TidenReporter implements ReporterInterface {
21
+ private static instance;
22
+ private readonly logger;
23
+ private readonly options;
24
+ private readonly withState;
25
+ private readonly captureLogs;
26
+ private readonly statusProcessor;
27
+ private readonly fallback;
28
+ private startTestRunOperation?;
29
+ /**
30
+ * @param {OptionsType} options
31
+ */
32
+ private constructor();
33
+ private buildLogger;
34
+ private buildReporters;
35
+ private persistInitialState;
36
+ static getInstance(options: OptionsType): TidenReporter;
37
+ getStatusMapping(): Record<string, string> | undefined;
38
+ uploadAttachment(attachment: Attachment): Promise<string>;
39
+ getResults(): TestResultType[];
40
+ setTestResults(results: TestResultType[]): void;
41
+ addTestResult(result: TestResultType): Promise<void>;
42
+ startTestRun(): void;
43
+ startTestRunAsync(): Promise<void>;
44
+ sendResults(): Promise<void>;
45
+ publish(): Promise<void>;
46
+ complete(): Promise<void>;
47
+ isCaptureLogs(): boolean;
48
+ }
package/dist/tiden.js ADDED
@@ -0,0 +1,223 @@
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.TidenReporter = void 0;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const options_1 = require("./options");
9
+ const models_1 = require("./models");
10
+ const disabled_exception_1 = require("./utils/disabled-exception");
11
+ const logger_1 = require("./utils/logger");
12
+ const hostData_1 = require("./utils/hostData");
13
+ const token_masker_1 = require("./utils/token-masker");
14
+ const state_1 = require("./state/state");
15
+ const options_resolver_1 = require("./core/options-resolver");
16
+ const reporter_factory_1 = require("./core/reporter-factory");
17
+ const status_processor_1 = require("./core/status-processor");
18
+ const fallback_coordinator_1 = require("./reporters/shared/fallback-coordinator");
19
+ /**
20
+ * @type {Record<TestStatusEnum, (test: TestResultType) => string>}
21
+ */
22
+ const resultLogMap = {
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}}`,
29
+ };
30
+ /**
31
+ * @class TidenReporter
32
+ *
33
+ * Thin orchestrator: delegates to OptionsResolver, ReporterFactory,
34
+ * StatusProcessor, and FallbackCoordinator. Public API is preserved.
35
+ */
36
+ class TidenReporter {
37
+ static instance;
38
+ logger;
39
+ options;
40
+ withState;
41
+ captureLogs;
42
+ statusProcessor;
43
+ fallback;
44
+ startTestRunOperation;
45
+ /**
46
+ * @param {OptionsType} options
47
+ */
48
+ constructor(options) {
49
+ const resolved = new options_resolver_1.OptionsResolver().resolve(options);
50
+ this.options = resolved.composed;
51
+ this.withState = resolved.withState;
52
+ this.captureLogs = resolved.composed.captureLogs;
53
+ this.logger = this.buildLogger(resolved);
54
+ this.logger.logDebug(`Config: ${JSON.stringify((0, token_masker_1.sanitizeOptionsForLog)(resolved.composed))}`);
55
+ const hostData = (0, hostData_1.getHostInfo)(options.frameworkPackage, options.reporterName);
56
+ this.logger.logDebug(`Host data: ${JSON.stringify(hostData)}`);
57
+ const factory = new reporter_factory_1.ReporterFactory(this.logger, hostData);
58
+ const { upstream, fallback, disabled, useFallbackFromStart } = this.buildReporters(factory, resolved);
59
+ this.statusProcessor = new status_processor_1.StatusProcessor(this.logger, resolved.composed.statusMapping, resolved.composed.tiden?.statusFilter);
60
+ this.fallback = new fallback_coordinator_1.FallbackCoordinator(this.logger, upstream, fallback, {
61
+ onFallbackActivated: () => {
62
+ if (this.withState) {
63
+ state_1.StateManager.setMode(resolved.composed.fallback);
64
+ }
65
+ },
66
+ onDisabled: () => {
67
+ if (this.withState) {
68
+ state_1.StateManager.setMode(options_1.ModeEnum.off);
69
+ }
70
+ },
71
+ });
72
+ if (disabled) {
73
+ this.fallback.setDisabled(true);
74
+ }
75
+ if (useFallbackFromStart) {
76
+ this.fallback.setUseFallback(true);
77
+ }
78
+ this.persistInitialState(resolved, disabled, useFallbackFromStart);
79
+ }
80
+ buildLogger(resolved) {
81
+ const opts = { debug: resolved.composed.debug };
82
+ if (resolved.composed.logging?.console !== undefined) {
83
+ opts.consoleLogging = resolved.composed.logging.console;
84
+ }
85
+ if (resolved.composed.logging?.file !== undefined) {
86
+ opts.fileLogging = resolved.composed.logging.file;
87
+ }
88
+ return new logger_1.Logger(opts);
89
+ }
90
+ buildReporters(factory, resolved) {
91
+ let upstream;
92
+ let fallbackReporter;
93
+ let disabled = false;
94
+ let upstreamFailed = false;
95
+ try {
96
+ upstream = factory.create(resolved.effectiveMode, resolved.composed, this.withState);
97
+ }
98
+ catch (error) {
99
+ if (error instanceof disabled_exception_1.DisabledException) {
100
+ disabled = true;
101
+ }
102
+ else {
103
+ this.logger.logError('Unable to create upstream reporter:', error);
104
+ if (resolved.composed.fallback === undefined) {
105
+ disabled = true;
106
+ return { upstream, fallback: fallbackReporter, disabled, useFallbackFromStart: false };
107
+ }
108
+ upstreamFailed = true;
109
+ }
110
+ }
111
+ try {
112
+ fallbackReporter = factory.create(resolved.effectiveFallback, resolved.composed, this.withState);
113
+ }
114
+ catch (error) {
115
+ if (error instanceof disabled_exception_1.DisabledException) {
116
+ if (upstreamFailed)
117
+ disabled = true;
118
+ }
119
+ else {
120
+ this.logger.logError('Unable to create fallback reporter:', error);
121
+ if (upstreamFailed && upstream === undefined)
122
+ disabled = true;
123
+ }
124
+ }
125
+ const useFallbackFromStart = upstreamFailed && fallbackReporter !== undefined;
126
+ return { upstream, fallback: fallbackReporter, disabled, useFallbackFromStart };
127
+ }
128
+ persistInitialState(resolved, disabled, useFallbackFromStart) {
129
+ if (!this.withState)
130
+ return;
131
+ if (state_1.StateManager.isStateExists())
132
+ return;
133
+ const state = {
134
+ RunId: undefined,
135
+ Mode: useFallbackFromStart
136
+ ? resolved.composed.fallback
137
+ : resolved.composed.mode,
138
+ IsModeChanged: undefined,
139
+ };
140
+ if (disabled) {
141
+ state.Mode = options_1.ModeEnum.off;
142
+ }
143
+ state_1.StateManager.setState(state);
144
+ }
145
+ static getInstance(options) {
146
+ if (!TidenReporter.instance) {
147
+ TidenReporter.instance = new TidenReporter(options);
148
+ }
149
+ return TidenReporter.instance;
150
+ }
151
+ getStatusMapping() {
152
+ return this.options.statusMapping;
153
+ }
154
+ async uploadAttachment(attachment) {
155
+ const result = await this.fallback.run((r) => r.uploadAttachment(attachment), 'upload attachment');
156
+ return result ?? '';
157
+ }
158
+ getResults() {
159
+ if (this.fallback.isDisabled())
160
+ return [];
161
+ const active = this.fallback.isUsingFallback()
162
+ ? this.fallback.getFallback()
163
+ : this.fallback.getUpstream();
164
+ return active?.getTestResults() ?? [];
165
+ }
166
+ setTestResults(results) {
167
+ if (this.fallback.isDisabled())
168
+ return;
169
+ const active = this.fallback.isUsingFallback()
170
+ ? this.fallback.getFallback()
171
+ : this.fallback.getUpstream();
172
+ active?.setTestResults(results);
173
+ }
174
+ async addTestResult(result) {
175
+ if (this.fallback.isDisabled())
176
+ return;
177
+ const processed = this.statusProcessor.process(result);
178
+ if (!processed)
179
+ return;
180
+ await this.startTestRunOperation;
181
+ this.logger.log(resultLogMap[processed.execution.status](processed));
182
+ await this.fallback.run((r) => r.addTestResult(processed), 'add the result');
183
+ }
184
+ startTestRun() {
185
+ if (this.withState)
186
+ state_1.StateManager.clearState();
187
+ this.fallback.reset();
188
+ this.logger.logDebug('Starting test run');
189
+ const runOp = this.fallback.run(async (r) => {
190
+ await r.startTestRun();
191
+ }, 'start test run');
192
+ this.startTestRunOperation = runOp.then(() => undefined);
193
+ }
194
+ async startTestRunAsync() {
195
+ this.startTestRun();
196
+ await this.startTestRunOperation;
197
+ }
198
+ async sendResults() {
199
+ if (this.fallback.isDisabled())
200
+ return;
201
+ await this.fallback.run((r) => r.sendResults(), 'send the results');
202
+ }
203
+ async publish() {
204
+ if (!this.fallback.isDisabled()) {
205
+ await this.startTestRunOperation;
206
+ this.logger.logDebug('Publishing test run results');
207
+ await this.fallback.run((r) => r.publish(), 'publish the run results');
208
+ }
209
+ if (this.withState)
210
+ state_1.StateManager.clearState();
211
+ }
212
+ async complete() {
213
+ if (this.withState)
214
+ state_1.StateManager.clearState();
215
+ if (this.fallback.isDisabled())
216
+ return;
217
+ await this.fallback.run((r) => r.complete(), 'complete the run');
218
+ }
219
+ isCaptureLogs() {
220
+ return this.captureLogs ?? false;
221
+ }
222
+ }
223
+ exports.TidenReporter = TidenReporter;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @class DisabledException
3
+ * @extends Error
4
+ */
5
+ export declare class DisabledException extends Error {
6
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DisabledException = void 0;
4
+ /**
5
+ * @class DisabledException
6
+ * @extends Error
7
+ */
8
+ class DisabledException extends Error {
9
+ }
10
+ exports.DisabledException = DisabledException;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @param {string} name
3
+ * @returns {undefined | string}
4
+ */
5
+ export declare const getPackageVersion: (name: string) => string | undefined;