@allurereport/core 3.0.0-beta.8 → 3.0.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.
@@ -1,16 +1,45 @@
1
- import type { BatchOptions, Realtime } from "@allurereport/plugin-api";
1
+ import type { TestError } from "@allurereport/core-api";
2
+ import type { BatchOptions, ExitCode, QualityGateValidationResult, RealtimeEventsDispatcher as RealtimeEventsDispatcherType, RealtimeSubscriber as RealtimeSubscriberType, ResultFile } from "@allurereport/plugin-api";
2
3
  import type { EventEmitter } from "node:events";
4
+ export declare enum RealtimeEvents {
5
+ TestResult = "testResult",
6
+ TestFixtureResult = "testFixtureResult",
7
+ AttachmentFile = "attachmentFile",
8
+ QualityGateResults = "qualityGateResults",
9
+ GlobalAttachment = "globalAttachment",
10
+ GlobalError = "globalError",
11
+ GlobalExitCode = "globalExitCode"
12
+ }
3
13
  export interface AllureStoreEvents {
4
- testResult: [string];
5
- testFixtureResult: [string];
6
- attachmentFile: [string];
14
+ [RealtimeEvents.QualityGateResults]: [QualityGateValidationResult[]];
15
+ [RealtimeEvents.TestResult]: [string];
16
+ [RealtimeEvents.TestFixtureResult]: [string];
17
+ [RealtimeEvents.AttachmentFile]: [string];
18
+ [RealtimeEvents.GlobalAttachment]: [ResultFile];
19
+ [RealtimeEvents.GlobalExitCode]: [ExitCode];
20
+ [RealtimeEvents.GlobalError]: [TestError];
21
+ }
22
+ export declare class RealtimeEventsDispatcher implements RealtimeEventsDispatcherType {
23
+ #private;
24
+ constructor(emitter: EventEmitter<AllureStoreEvents>);
25
+ sendGlobalAttachment(attachment: ResultFile): void;
26
+ sendGlobalExitCode(codes: ExitCode): void;
27
+ sendGlobalError(error: TestError): void;
28
+ sendQualityGateResults(payload: QualityGateValidationResult[]): void;
29
+ sendTestResult(trId: string): void;
30
+ sendTestFixtureResult(tfrId: string): void;
31
+ sendAttachmentFile(afId: string): void;
7
32
  }
8
- export declare class Events implements Realtime {
33
+ export declare class RealtimeSubscriber implements RealtimeSubscriberType {
9
34
  #private;
10
35
  constructor(emitter: EventEmitter<AllureStoreEvents>);
11
- onTestResults: (listener: (trIds: string[]) => Promise<void>, options?: BatchOptions) => void;
12
- onTestFixtureResults: (listener: (tfrIds: string[]) => Promise<void>, options?: BatchOptions) => void;
13
- onAttachmentFiles(listener: (afIds: string[]) => Promise<void>, options?: BatchOptions): void;
14
- onAll(listener: () => Promise<void>, options?: BatchOptions): void;
36
+ onGlobalAttachment(listener: (attachment: ResultFile) => Promise<void>): () => void;
37
+ onGlobalExitCode(listener: (payload: ExitCode) => Promise<void>): () => void;
38
+ onGlobalError(listener: (error: TestError) => Promise<void>): () => void;
39
+ onQualityGateResults(listener: (payload: QualityGateValidationResult[]) => Promise<void>): () => void;
40
+ onTestResults(listener: (trIds: string[]) => Promise<void>, options?: BatchOptions): () => void;
41
+ onTestFixtureResults(listener: (tfrIds: string[]) => Promise<void>, options?: BatchOptions): () => void;
42
+ onAttachmentFiles(listener: (afIds: string[]) => Promise<void>, options?: BatchOptions): () => void;
43
+ onAll(listener: () => Promise<void>, options?: BatchOptions): () => void;
15
44
  offAll(): void;
16
45
  }
@@ -9,51 +9,127 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _Events_instances, _Events_emitter, _Events_handlers, _Events_createHandler;
12
+ var _RealtimeEventsDispatcher_emitter, _RealtimeSubscriber_instances, _RealtimeSubscriber_emitter, _RealtimeSubscriber_handlers, _RealtimeSubscriber_createBatchHandler;
13
13
  import console from "node:console";
14
14
  import { setTimeout } from "node:timers/promises";
15
- export class Events {
15
+ export var RealtimeEvents;
16
+ (function (RealtimeEvents) {
17
+ RealtimeEvents["TestResult"] = "testResult";
18
+ RealtimeEvents["TestFixtureResult"] = "testFixtureResult";
19
+ RealtimeEvents["AttachmentFile"] = "attachmentFile";
20
+ RealtimeEvents["QualityGateResults"] = "qualityGateResults";
21
+ RealtimeEvents["GlobalAttachment"] = "globalAttachment";
22
+ RealtimeEvents["GlobalError"] = "globalError";
23
+ RealtimeEvents["GlobalExitCode"] = "globalExitCode";
24
+ })(RealtimeEvents || (RealtimeEvents = {}));
25
+ export class RealtimeEventsDispatcher {
16
26
  constructor(emitter) {
17
- _Events_instances.add(this);
18
- _Events_emitter.set(this, void 0);
19
- _Events_handlers.set(this, []);
20
- this.onTestResults = (listener, options = {}) => {
21
- const { maxTimeout = 100 } = options;
22
- const handler = __classPrivateFieldGet(this, _Events_instances, "m", _Events_createHandler).call(this, maxTimeout, listener);
23
- __classPrivateFieldGet(this, _Events_emitter, "f").on("testResult", handler);
27
+ _RealtimeEventsDispatcher_emitter.set(this, void 0);
28
+ __classPrivateFieldSet(this, _RealtimeEventsDispatcher_emitter, emitter, "f");
29
+ }
30
+ sendGlobalAttachment(attachment) {
31
+ __classPrivateFieldGet(this, _RealtimeEventsDispatcher_emitter, "f").emit(RealtimeEvents.GlobalAttachment, attachment);
32
+ }
33
+ sendGlobalExitCode(codes) {
34
+ __classPrivateFieldGet(this, _RealtimeEventsDispatcher_emitter, "f").emit(RealtimeEvents.GlobalExitCode, codes);
35
+ }
36
+ sendGlobalError(error) {
37
+ __classPrivateFieldGet(this, _RealtimeEventsDispatcher_emitter, "f").emit(RealtimeEvents.GlobalError, error);
38
+ }
39
+ sendQualityGateResults(payload) {
40
+ __classPrivateFieldGet(this, _RealtimeEventsDispatcher_emitter, "f").emit(RealtimeEvents.QualityGateResults, payload ?? []);
41
+ }
42
+ sendTestResult(trId) {
43
+ __classPrivateFieldGet(this, _RealtimeEventsDispatcher_emitter, "f").emit(RealtimeEvents.TestResult, trId);
44
+ }
45
+ sendTestFixtureResult(tfrId) {
46
+ __classPrivateFieldGet(this, _RealtimeEventsDispatcher_emitter, "f").emit(RealtimeEvents.TestFixtureResult, tfrId);
47
+ }
48
+ sendAttachmentFile(afId) {
49
+ __classPrivateFieldGet(this, _RealtimeEventsDispatcher_emitter, "f").emit(RealtimeEvents.AttachmentFile, afId);
50
+ }
51
+ }
52
+ _RealtimeEventsDispatcher_emitter = new WeakMap();
53
+ export class RealtimeSubscriber {
54
+ constructor(emitter) {
55
+ _RealtimeSubscriber_instances.add(this);
56
+ _RealtimeSubscriber_emitter.set(this, void 0);
57
+ _RealtimeSubscriber_handlers.set(this, []);
58
+ __classPrivateFieldSet(this, _RealtimeSubscriber_emitter, emitter, "f");
59
+ }
60
+ onGlobalAttachment(listener) {
61
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").on(RealtimeEvents.GlobalAttachment, listener);
62
+ return () => {
63
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").off(RealtimeEvents.GlobalAttachment, listener);
64
+ };
65
+ }
66
+ onGlobalExitCode(listener) {
67
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").on(RealtimeEvents.GlobalExitCode, listener);
68
+ return () => {
69
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").off(RealtimeEvents.GlobalExitCode, listener);
70
+ };
71
+ }
72
+ onGlobalError(listener) {
73
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").on(RealtimeEvents.GlobalError, listener);
74
+ return () => {
75
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").off(RealtimeEvents.GlobalError, listener);
76
+ };
77
+ }
78
+ onQualityGateResults(listener) {
79
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").on(RealtimeEvents.QualityGateResults, listener);
80
+ return () => {
81
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").off(RealtimeEvents.QualityGateResults, listener);
82
+ };
83
+ }
84
+ onTestResults(listener, options = {}) {
85
+ const { maxTimeout = 100 } = options;
86
+ const handler = __classPrivateFieldGet(this, _RealtimeSubscriber_instances, "m", _RealtimeSubscriber_createBatchHandler).call(this, maxTimeout, listener);
87
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").on(RealtimeEvents.TestResult, handler);
88
+ return () => {
89
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").off(RealtimeEvents.TestResult, handler);
24
90
  };
25
- this.onTestFixtureResults = (listener, options = {}) => {
26
- const { maxTimeout = 100 } = options;
27
- const handler = __classPrivateFieldGet(this, _Events_instances, "m", _Events_createHandler).call(this, maxTimeout, listener);
28
- __classPrivateFieldGet(this, _Events_emitter, "f").on("testFixtureResult", handler);
91
+ }
92
+ onTestFixtureResults(listener, options = {}) {
93
+ const { maxTimeout = 100 } = options;
94
+ const handler = __classPrivateFieldGet(this, _RealtimeSubscriber_instances, "m", _RealtimeSubscriber_createBatchHandler).call(this, maxTimeout, listener);
95
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").on(RealtimeEvents.TestFixtureResult, handler);
96
+ return () => {
97
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").off(RealtimeEvents.TestFixtureResult, handler);
29
98
  };
30
- __classPrivateFieldSet(this, _Events_emitter, emitter, "f");
31
99
  }
32
100
  onAttachmentFiles(listener, options = {}) {
33
101
  const { maxTimeout = 100 } = options;
34
- const handler = __classPrivateFieldGet(this, _Events_instances, "m", _Events_createHandler).call(this, maxTimeout, listener);
35
- __classPrivateFieldGet(this, _Events_emitter, "f").on("attachmentFile", handler);
102
+ const handler = __classPrivateFieldGet(this, _RealtimeSubscriber_instances, "m", _RealtimeSubscriber_createBatchHandler).call(this, maxTimeout, listener);
103
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").on(RealtimeEvents.AttachmentFile, handler);
104
+ return () => {
105
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").off(RealtimeEvents.AttachmentFile, handler);
106
+ };
36
107
  }
37
108
  onAll(listener, options = {}) {
38
109
  const { maxTimeout = 100 } = options;
39
- const handler = __classPrivateFieldGet(this, _Events_instances, "m", _Events_createHandler).call(this, maxTimeout, listener);
40
- __classPrivateFieldGet(this, _Events_emitter, "f").on("testResult", handler);
41
- __classPrivateFieldGet(this, _Events_emitter, "f").on("testFixtureResult", handler);
42
- __classPrivateFieldGet(this, _Events_emitter, "f").on("attachmentFile", handler);
110
+ const handler = __classPrivateFieldGet(this, _RealtimeSubscriber_instances, "m", _RealtimeSubscriber_createBatchHandler).call(this, maxTimeout, listener);
111
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").on(RealtimeEvents.TestResult, handler);
112
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").on(RealtimeEvents.TestFixtureResult, handler);
113
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").on(RealtimeEvents.AttachmentFile, handler);
114
+ return () => {
115
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").off(RealtimeEvents.TestResult, handler);
116
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").off(RealtimeEvents.TestFixtureResult, handler);
117
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").off(RealtimeEvents.AttachmentFile, handler);
118
+ };
43
119
  }
44
120
  offAll() {
45
- __classPrivateFieldGet(this, _Events_emitter, "f").removeAllListeners();
46
- for (const handler of __classPrivateFieldGet(this, _Events_handlers, "f")) {
121
+ __classPrivateFieldGet(this, _RealtimeSubscriber_emitter, "f").removeAllListeners();
122
+ for (const handler of __classPrivateFieldGet(this, _RealtimeSubscriber_handlers, "f")) {
47
123
  handler.ac?.abort();
48
124
  }
49
- __classPrivateFieldSet(this, _Events_handlers, [], "f");
125
+ __classPrivateFieldSet(this, _RealtimeSubscriber_handlers, [], "f");
50
126
  }
51
127
  }
52
- _Events_emitter = new WeakMap(), _Events_handlers = new WeakMap(), _Events_instances = new WeakSet(), _Events_createHandler = function _Events_createHandler(maxTimeout, listener) {
128
+ _RealtimeSubscriber_emitter = new WeakMap(), _RealtimeSubscriber_handlers = new WeakMap(), _RealtimeSubscriber_instances = new WeakSet(), _RealtimeSubscriber_createBatchHandler = function _RealtimeSubscriber_createBatchHandler(maxTimeout, listener) {
53
129
  const handler = {
54
130
  buffer: [],
55
131
  };
56
- __classPrivateFieldGet(this, _Events_handlers, "f").push(handler);
132
+ __classPrivateFieldGet(this, _RealtimeSubscriber_handlers, "f").push(handler);
57
133
  return (trId) => {
58
134
  handler.buffer.push(trId);
59
135
  if (handler.timeout) {
@@ -0,0 +1,2 @@
1
+ import type { HistoryTestResult, TestResult } from "@allurereport/core-api";
2
+ export declare const isFlaky: (tr: TestResult, history: HistoryTestResult[]) => boolean;
@@ -0,0 +1,12 @@
1
+ const MAX_LAST_HISTORY_SIZE = 5;
2
+ const badStatuses = ["failed", "broken"];
3
+ const isAllureClassicFlaky = (tr, history) => {
4
+ if (history.length === 0 || !badStatuses.includes(tr.status)) {
5
+ return false;
6
+ }
7
+ const limitedLastHistory = history.slice(0, MAX_LAST_HISTORY_SIZE);
8
+ const limitedLastHistoryStatuses = limitedLastHistory.map((h) => h.status);
9
+ return (limitedLastHistoryStatuses.includes("passed") &&
10
+ limitedLastHistoryStatuses.indexOf("passed") < limitedLastHistoryStatuses.lastIndexOf("failed"));
11
+ };
12
+ export const isFlaky = (tr, history) => tr.flaky || isAllureClassicFlaky(tr, history);
@@ -0,0 +1,6 @@
1
+ import type { TestResult, TestStatusTransition } from "@allurereport/core-api";
2
+ type TrWithStatus = Pick<TestResult, "status">;
3
+ export declare const isNew: (history?: TrWithStatus[]) => boolean;
4
+ export declare const getLastSignificantStatus: (history?: TrWithStatus[]) => string | undefined;
5
+ export declare const getStatusTransition: (tr: TrWithStatus, history?: TrWithStatus[]) => TestStatusTransition | undefined;
6
+ export {};
@@ -0,0 +1,23 @@
1
+ const NON_SIGNIFICANT_HISTORY_STATUSES = ["unknown", "skipped"];
2
+ export const isNew = (history = []) => history.length === 0;
3
+ const hasSignificantStatus = (htr) => !NON_SIGNIFICANT_HISTORY_STATUSES.includes(htr.status);
4
+ export const getLastSignificantStatus = (history = []) => {
5
+ const significantHtr = history.find(hasSignificantStatus);
6
+ return significantHtr?.status;
7
+ };
8
+ export const getStatusTransition = (tr, history = []) => {
9
+ if (isNew(history)) {
10
+ return "new";
11
+ }
12
+ const lastStatus = getLastSignificantStatus(history);
13
+ if (lastStatus !== tr.status) {
14
+ switch (tr.status) {
15
+ case "passed":
16
+ return "fixed";
17
+ case "failed":
18
+ return "regressed";
19
+ case "broken":
20
+ return "malfunctioned";
21
+ }
22
+ }
23
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/core",
3
- "version": "3.0.0-beta.8",
3
+ "version": "3.0.0",
4
4
  "description": "Collection of generic Allure utilities used across the entire project",
5
5
  "keywords": [
6
6
  "allure"
@@ -25,30 +25,46 @@
25
25
  "test": "vitest run"
26
26
  },
27
27
  "dependencies": {
28
- "@allurereport/core-api": "3.0.0-beta.8",
29
- "@allurereport/plugin-api": "3.0.0-beta.8",
30
- "@allurereport/plugin-awesome": "3.0.0-beta.8",
31
- "@allurereport/plugin-classic": "3.0.0-beta.8",
32
- "@allurereport/plugin-csv": "3.0.0-beta.8",
33
- "@allurereport/plugin-log": "3.0.0-beta.8",
34
- "@allurereport/plugin-progress": "3.0.0-beta.8",
35
- "@allurereport/plugin-slack": "3.0.0-beta.8",
36
- "@allurereport/plugin-testplan": "3.0.0-beta.8",
37
- "@allurereport/reader": "3.0.0-beta.8",
38
- "@allurereport/reader-api": "3.0.0-beta.8",
39
- "markdown-it": "^14.1.0"
28
+ "@allurereport/ci": "3.0.0",
29
+ "@allurereport/core-api": "3.0.0",
30
+ "@allurereport/plugin-allure2": "3.0.0",
31
+ "@allurereport/plugin-api": "3.0.0",
32
+ "@allurereport/plugin-awesome": "3.0.0",
33
+ "@allurereport/plugin-classic": "3.0.0",
34
+ "@allurereport/plugin-csv": "3.0.0",
35
+ "@allurereport/plugin-dashboard": "3.0.0",
36
+ "@allurereport/plugin-jira": "3.0.0",
37
+ "@allurereport/plugin-log": "3.0.0",
38
+ "@allurereport/plugin-progress": "3.0.0",
39
+ "@allurereport/plugin-slack": "3.0.0",
40
+ "@allurereport/plugin-testplan": "3.0.0",
41
+ "@allurereport/reader": "3.0.0",
42
+ "@allurereport/reader-api": "3.0.0",
43
+ "@allurereport/service": "3.0.0",
44
+ "@allurereport/summary": "3.0.0",
45
+ "handlebars": "^4.7.8",
46
+ "markdown-it": "^14.1.0",
47
+ "node-stream-zip": "^1.15.0",
48
+ "p-limit": "^7.2.0",
49
+ "progress": "^2.0.3",
50
+ "yaml": "^2.8.1",
51
+ "yoctocolors": "^2.1.1",
52
+ "zip-stream": "^7.0.2"
40
53
  },
41
54
  "devDependencies": {
42
55
  "@stylistic/eslint-plugin": "^2.6.1",
43
56
  "@types/eslint": "^8.56.11",
57
+ "@types/handlebars": "^4.1.0",
44
58
  "@types/markdown-it": "^14.1.2",
45
59
  "@types/node": "^20.17.9",
60
+ "@types/progress": "^2",
61
+ "@types/zip-stream": "^7.0.0",
46
62
  "@typescript-eslint/eslint-plugin": "^8.0.0",
47
63
  "@typescript-eslint/parser": "^8.0.0",
48
- "@vitest/runner": "^2.1.8",
49
- "@vitest/snapshot": "^2.1.8",
50
- "allure-js-commons": "^3.0.9",
51
- "allure-vitest": "^3.0.9",
64
+ "@vitest/runner": "^2.1.9",
65
+ "@vitest/snapshot": "^2.1.9",
66
+ "allure-js-commons": "^3.3.3",
67
+ "allure-vitest": "^3.3.3",
52
68
  "eslint": "^8.57.0",
53
69
  "eslint-config-prettier": "^9.1.0",
54
70
  "eslint-plugin-import": "^2.29.1",
@@ -59,6 +75,6 @@
59
75
  "rimraf": "^6.0.1",
60
76
  "tslib": "^2.7.0",
61
77
  "typescript": "^5.6.3",
62
- "vitest": "^2.1.8"
78
+ "vitest": "^2.1.9"
63
79
  }
64
80
  }
@@ -1,25 +0,0 @@
1
- import type { AllureStore, QualityGateConfig, QualityGateRulesMeta, QualityGateValidationResult, QualityGateValidator } from "@allurereport/plugin-api";
2
- export declare abstract class AbstractQualityGateValidator implements QualityGateValidator {
3
- readonly limit: number;
4
- readonly meta?: QualityGateRulesMeta | undefined;
5
- constructor(limit: number, meta?: QualityGateRulesMeta | undefined);
6
- getTestResultsFilteredByMeta(store: AllureStore): Promise<import("@allurereport/core-api").TestResult[]>;
7
- abstract validate(store: AllureStore): Promise<QualityGateValidationResult>;
8
- }
9
- export declare class MaxFailuresValidator extends AbstractQualityGateValidator {
10
- validate(store: AllureStore): Promise<QualityGateValidationResult>;
11
- }
12
- export declare class MinTestsCountValidator extends AbstractQualityGateValidator {
13
- validate(store: AllureStore): Promise<QualityGateValidationResult>;
14
- }
15
- export declare class SuccessRateValidator extends AbstractQualityGateValidator {
16
- validate(store: AllureStore): Promise<QualityGateValidationResult>;
17
- }
18
- export declare class QualityGate {
19
- #private;
20
- readonly config?: QualityGateConfig | undefined;
21
- result: QualityGateValidationResult[];
22
- constructor(config?: QualityGateConfig | undefined);
23
- get exitCode(): 0 | 1;
24
- validate: (store: AllureStore) => Promise<void>;
25
- }
@@ -1,116 +0,0 @@
1
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
- };
6
- var _QualityGate_instances, _QualityGate_mappedValidators_get, _QualityGate_createRulesValidator;
7
- import { filterSuccessful, filterUnsuccessful } from "@allurereport/core-api";
8
- export class AbstractQualityGateValidator {
9
- constructor(limit, meta) {
10
- this.limit = limit;
11
- this.meta = meta;
12
- }
13
- async getTestResultsFilteredByMeta(store) {
14
- const allTrs = await store.allTestResults();
15
- if (!this.meta) {
16
- return allTrs;
17
- }
18
- return allTrs.filter((tr) => {
19
- switch (this.meta?.type) {
20
- case "label":
21
- return tr.labels.some((label) => label.name === this.meta.name && label.value === this.meta.value);
22
- case "parameter":
23
- return tr.parameters.some((parameter) => parameter.name === this.meta.name && parameter.value === this.meta.value);
24
- default:
25
- return tr;
26
- }
27
- });
28
- }
29
- }
30
- export class MaxFailuresValidator extends AbstractQualityGateValidator {
31
- async validate(store) {
32
- const trs = (await this.getTestResultsFilteredByMeta(store)).filter((tr) => !tr.hidden).filter(filterUnsuccessful);
33
- return {
34
- success: trs.length <= this.limit,
35
- rule: "maxFailures",
36
- meta: this.meta,
37
- expected: this.limit,
38
- actual: trs.length,
39
- };
40
- }
41
- }
42
- export class MinTestsCountValidator extends AbstractQualityGateValidator {
43
- async validate(store) {
44
- const trs = (await this.getTestResultsFilteredByMeta(store)).filter((tr) => !tr.hidden);
45
- return {
46
- success: trs.length >= this.limit,
47
- rule: "minTestsCount",
48
- meta: this.meta,
49
- expected: this.limit,
50
- actual: trs.length,
51
- };
52
- }
53
- }
54
- export class SuccessRateValidator extends AbstractQualityGateValidator {
55
- async validate(store) {
56
- const knownIssues = await store.allKnownIssues();
57
- const trs = (await this.getTestResultsFilteredByMeta(store)).filter((tr) => !tr.hidden);
58
- const knownIssuesHistoryIds = knownIssues.map((ki) => ki.historyId);
59
- const unknown = trs.filter((tr) => !tr.historyId || !knownIssuesHistoryIds.includes(tr.historyId));
60
- const passed = unknown.filter(filterSuccessful);
61
- const rate = passed.length === 0 ? 0 : passed.length / unknown.length;
62
- return {
63
- success: rate >= this.limit,
64
- rule: "successRate",
65
- meta: this.meta,
66
- expected: this.limit,
67
- actual: rate,
68
- };
69
- }
70
- }
71
- export class QualityGate {
72
- constructor(config) {
73
- _QualityGate_instances.add(this);
74
- this.config = config;
75
- this.result = [];
76
- _QualityGate_createRulesValidator.set(this, (rules, meta) => {
77
- const validators = [];
78
- Object.keys(rules).forEach((rule) => {
79
- const Validator = __classPrivateFieldGet(this, _QualityGate_instances, "a", _QualityGate_mappedValidators_get)[rule];
80
- if (!Validator) {
81
- return;
82
- }
83
- const validator = new Validator(rules[rule], meta);
84
- validators.push(validator);
85
- });
86
- return validators;
87
- });
88
- this.validate = async (store) => {
89
- const { rules, enforce = [] } = this.config ?? {};
90
- const validators = [];
91
- const result = [];
92
- if (rules) {
93
- validators.push(...__classPrivateFieldGet(this, _QualityGate_createRulesValidator, "f").call(this, rules));
94
- }
95
- enforce.forEach((enforceConfig) => {
96
- const { rules: enforceRules, ...meta } = enforceConfig;
97
- validators.push(...__classPrivateFieldGet(this, _QualityGate_createRulesValidator, "f").call(this, enforceRules, meta));
98
- });
99
- for (const validator of validators) {
100
- result.push(await validator.validate(store));
101
- }
102
- this.result = result;
103
- };
104
- }
105
- get exitCode() {
106
- return this.result.some((res) => !res.success) ? 1 : 0;
107
- }
108
- }
109
- _QualityGate_createRulesValidator = new WeakMap(), _QualityGate_instances = new WeakSet(), _QualityGate_mappedValidators_get = function _QualityGate_mappedValidators_get() {
110
- return {
111
- maxFailures: MaxFailuresValidator,
112
- minTestsCount: MinTestsCountValidator,
113
- successRate: SuccessRateValidator,
114
- ...this.config?.validators,
115
- };
116
- };