@allurereport/core 3.0.0-beta.17 → 3.0.0-beta.19

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/dist/api.d.ts CHANGED
@@ -12,8 +12,9 @@ export interface FullConfig {
12
12
  output: string;
13
13
  historyPath: string;
14
14
  knownIssuesPath: string;
15
- qualityGate?: QualityGateConfig;
16
15
  defaultLabels?: DefaultLabelsConfig;
16
+ stage?: string;
17
+ environment?: string;
17
18
  environments?: EnvironmentsConfig;
18
19
  variables?: ReportVariables;
19
20
  reportFiles: ReportFiles;
@@ -22,6 +23,7 @@ export interface FullConfig {
22
23
  appendHistory?: boolean;
23
24
  known?: KnownTestFailure[];
24
25
  realTime?: any;
26
+ qualityGate?: QualityGateConfig;
25
27
  allureService?: {
26
28
  url?: string;
27
29
  project?: string;
package/dist/config.js CHANGED
@@ -43,12 +43,12 @@ export const validateConfig = (config) => {
43
43
  "output",
44
44
  "historyPath",
45
45
  "knownIssuesPath",
46
- "qualityGate",
47
46
  "plugins",
48
47
  "defaultLabels",
49
48
  "variables",
50
49
  "environments",
51
50
  "appendHistory",
51
+ "qualityGate",
52
52
  "allureService",
53
53
  ];
54
54
  const unsupportedFields = Object.keys(config).filter((key) => !supportedFields.includes(key));
@@ -92,6 +92,7 @@ export const resolveConfig = async (config, override = {}) => {
92
92
  appendHistory,
93
93
  reportFiles: new FileSystemReportFiles(output),
94
94
  plugins: pluginInstances,
95
+ defaultLabels: config.defaultLabels ?? {},
95
96
  qualityGate: config.qualityGate,
96
97
  allureService: config.allureService,
97
98
  };
package/dist/history.js CHANGED
@@ -16,15 +16,13 @@ const createHistoryItems = (testResults) => {
16
16
  stop,
17
17
  duration,
18
18
  labels,
19
+ url: "",
19
20
  historyId: historyId,
20
21
  reportLinks: [],
21
22
  };
22
23
  })
23
24
  .reduce((acc, item) => {
24
- acc[item.historyId] = {
25
- ...item,
26
- url: "",
27
- };
25
+ acc[item.historyId] = item;
28
26
  return acc;
29
27
  }, {});
30
28
  };
package/dist/index.d.ts CHANGED
@@ -11,4 +11,4 @@ export * from "./known.js";
11
11
  export { resolveConfig, readConfig, getPluginInstance } from "./config.js";
12
12
  export * from "./report.js";
13
13
  export * from "./plugin.js";
14
- export * from "./qualityGate.js";
14
+ export { QualityGateState, qualityGateDefaultRules, maxFailuresRule, minTestsCountRule, successRateRule, convertQualityGateResultsToTestErrors, stringifyQualityGateResults, } from "./qualityGate/index.js";
package/dist/index.js CHANGED
@@ -10,4 +10,4 @@ export * from "./known.js";
10
10
  export { resolveConfig, readConfig, getPluginInstance } from "./config.js";
11
11
  export * from "./report.js";
12
12
  export * from "./plugin.js";
13
- export * from "./qualityGate.js";
13
+ export { QualityGateState, qualityGateDefaultRules, maxFailuresRule, minTestsCountRule, successRateRule, convertQualityGateResultsToTestErrors, stringifyQualityGateResults, } from "./qualityGate/index.js";
@@ -0,0 +1,2 @@
1
+ export * from "./qualityGate.js";
2
+ export * from "./rules.js";
@@ -0,0 +1,2 @@
1
+ export * from "./qualityGate.js";
2
+ export * from "./rules.js";
@@ -0,0 +1,21 @@
1
+ import type { KnownTestFailure, TestError, TestResult } from "@allurereport/core-api";
2
+ import type { QualityGateConfig, QualityGateValidationResult } from "@allurereport/plugin-api";
3
+ export declare const stringifyQualityGateResults: (results: QualityGateValidationResult[]) => string;
4
+ export declare const convertQualityGateResultsToTestErrors: (results: QualityGateValidationResult[]) => TestError[];
5
+ export declare class QualityGateState {
6
+ #private;
7
+ setResult(rule: string, value: any): void;
8
+ getResult(rule: string): any;
9
+ }
10
+ export declare class QualityGate {
11
+ private readonly config;
12
+ constructor(config: QualityGateConfig);
13
+ validate(payload: {
14
+ state?: QualityGateState;
15
+ trs: TestResult[];
16
+ knownIssues: KnownTestFailure[];
17
+ }): Promise<{
18
+ fastFailed: boolean;
19
+ results: QualityGateValidationResult[];
20
+ }>;
21
+ }
@@ -0,0 +1,96 @@
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 _QualityGateState_state;
7
+ import { gray, red } from "yoctocolors";
8
+ import { qualityGateDefaultRules } from "./rules.js";
9
+ export const stringifyQualityGateResults = (results) => {
10
+ if (results.length === 0) {
11
+ return "";
12
+ }
13
+ const lines = [red("Quality Gate failed with following issues:")];
14
+ const maxMessageLength = Math.max(...results.map((r) => r.message.length));
15
+ lines.push("");
16
+ results.forEach((result) => {
17
+ lines.push(` ${red("⨯")} ${result.message.padEnd(maxMessageLength, " ")} ${gray(result.rule)}`);
18
+ });
19
+ lines.push("");
20
+ lines.push(red(`${results.length} quality gate rules have been failed.`));
21
+ return lines.join("\n");
22
+ };
23
+ export const convertQualityGateResultsToTestErrors = (results) => {
24
+ return results.map((result) => ({
25
+ message: `Quality Gate (${result.rule}): ${result.message}`,
26
+ actual: result.actual,
27
+ expected: result.expected,
28
+ }));
29
+ };
30
+ export class QualityGateState {
31
+ constructor() {
32
+ _QualityGateState_state.set(this, {});
33
+ }
34
+ setResult(rule, value) {
35
+ __classPrivateFieldGet(this, _QualityGateState_state, "f")[rule] = value;
36
+ }
37
+ getResult(rule) {
38
+ return __classPrivateFieldGet(this, _QualityGateState_state, "f")[rule];
39
+ }
40
+ }
41
+ _QualityGateState_state = new WeakMap();
42
+ export class QualityGate {
43
+ constructor(config) {
44
+ this.config = config;
45
+ }
46
+ async validate(payload) {
47
+ const { state, trs, knownIssues } = payload;
48
+ const { rules, use = [...qualityGateDefaultRules] } = this.config;
49
+ const results = [];
50
+ let fastFailed = false;
51
+ if (!rules?.length) {
52
+ return {
53
+ fastFailed: false,
54
+ results,
55
+ };
56
+ }
57
+ for (const ruleset of rules) {
58
+ if (fastFailed) {
59
+ break;
60
+ }
61
+ for (const [key, value] of Object.entries(ruleset)) {
62
+ if (key === "filter" || key === "id" || key === "fastFail") {
63
+ continue;
64
+ }
65
+ const rule = use.filter((r) => r.rule === key).pop();
66
+ if (!rule) {
67
+ throw new Error(`Rule ${key} is not provided. Make sure you have provided it in the "use" field of the quality gate config!`);
68
+ }
69
+ const ruleId = ruleset.id ? [ruleset.id, rule.rule].join("/") : rule.rule;
70
+ const result = await rule.validate({
71
+ expected: value,
72
+ trs,
73
+ knownIssues,
74
+ state: state?.getResult?.(ruleId),
75
+ });
76
+ state?.setResult(ruleId, result.actual);
77
+ if (result.success) {
78
+ continue;
79
+ }
80
+ results.push({
81
+ ...result,
82
+ rule: ruleset.id ? [ruleset.id, rule.rule].join("/") : rule.rule,
83
+ message: rule.message(result),
84
+ });
85
+ if (ruleset.fastFail) {
86
+ fastFailed = true;
87
+ break;
88
+ }
89
+ }
90
+ }
91
+ return {
92
+ fastFailed,
93
+ results,
94
+ };
95
+ }
96
+ }
@@ -0,0 +1,5 @@
1
+ import { type QualityGateRule } from "@allurereport/plugin-api";
2
+ export declare const maxFailuresRule: QualityGateRule<number>;
3
+ export declare const minTestsCountRule: QualityGateRule<number>;
4
+ export declare const successRateRule: QualityGateRule<number>;
5
+ export declare const qualityGateDefaultRules: QualityGateRule<number>[];
@@ -0,0 +1,45 @@
1
+ import { filterSuccessful, filterUnsuccessful } from "@allurereport/core-api";
2
+ import { bold } from "yoctocolors";
3
+ export const maxFailuresRule = {
4
+ rule: "maxFailures",
5
+ message: ({ actual, expected }) => `The number of failed tests ${bold(String(actual))} exceeds the allowed threshold value ${bold(String(expected))}`,
6
+ validate: async ({ trs, knownIssues, expected, state = 0 }) => {
7
+ const knownIssuesHistoryIds = knownIssues.map(({ historyId }) => historyId);
8
+ const unknown = trs.filter((tr) => !tr.historyId || !knownIssuesHistoryIds.includes(tr.historyId));
9
+ const failedTrs = unknown.filter(filterUnsuccessful);
10
+ const actual = failedTrs.length + state;
11
+ return {
12
+ success: actual <= expected,
13
+ actual,
14
+ expected,
15
+ };
16
+ },
17
+ };
18
+ export const minTestsCountRule = {
19
+ rule: "minTestsCount",
20
+ message: ({ actual, expected }) => `The total number of tests ${bold(String(actual))} is less than the expected threshold value ${bold(String(expected))}`,
21
+ validate: async ({ trs, expected, state = 0 }) => {
22
+ const actual = trs.length + state;
23
+ return {
24
+ success: actual >= expected,
25
+ actual,
26
+ expected,
27
+ };
28
+ },
29
+ };
30
+ export const successRateRule = {
31
+ rule: "successRate",
32
+ message: ({ actual, expected }) => `Success rate ${bold(String(actual))} is less, than expected ${bold(String(expected))}`,
33
+ validate: async ({ trs, knownIssues, expected }) => {
34
+ const knownIssuesHistoryIds = knownIssues.map(({ historyId }) => historyId);
35
+ const unknown = trs.filter((tr) => !tr.historyId || !knownIssuesHistoryIds.includes(tr.historyId));
36
+ const passedTrs = unknown.filter(filterSuccessful);
37
+ const rate = passedTrs.length === 0 ? 0 : passedTrs.length / unknown.length;
38
+ return {
39
+ success: rate >= expected,
40
+ actual: rate,
41
+ expected,
42
+ };
43
+ },
44
+ };
45
+ export const qualityGateDefaultRules = [maxFailuresRule, minTestsCountRule, successRateRule];
package/dist/report.d.ts CHANGED
@@ -1,18 +1,31 @@
1
- import type { ResultFile } from "@allurereport/plugin-api";
1
+ import type { KnownTestFailure, TestResult } from "@allurereport/core-api";
2
+ import { type ResultFile } from "@allurereport/plugin-api";
2
3
  import type { FullConfig } from "./api.js";
4
+ import { type QualityGateState } from "./qualityGate/index.js";
3
5
  import { DefaultAllureStore } from "./store/store.js";
6
+ import { RealtimeEventsDispatcher, RealtimeSubscriber } from "./utils/event.js";
4
7
  export declare class AllureReport {
5
8
  #private;
6
9
  readonly reportUuid: string;
7
10
  reportUrl?: string;
8
11
  constructor(opts: FullConfig);
12
+ get hasQualityGate(): boolean;
9
13
  get store(): DefaultAllureStore;
10
- get exitCode(): 0 | 1;
11
- get validationResults(): import("@allurereport/plugin-api").QualityGateValidationResult[];
14
+ get realtimeSubscriber(): RealtimeSubscriber;
15
+ get realtimeDispatcher(): RealtimeEventsDispatcher;
12
16
  readDirectory: (resultsDir: string) => Promise<void>;
13
17
  readFile: (resultsFile: string) => Promise<void>;
14
18
  readResult: (data: ResultFile) => Promise<void>;
19
+ validate: (params: {
20
+ trs: TestResult[];
21
+ knownIssues: KnownTestFailure[];
22
+ state?: QualityGateState;
23
+ }) => Promise<{
24
+ fastFailed: boolean;
25
+ results: import("@allurereport/plugin-api").QualityGateValidationResult[];
26
+ }>;
15
27
  start: () => Promise<void>;
28
+ dumpState: () => Promise<void>;
29
+ restoreState: (stages: string[]) => Promise<void>;
16
30
  done: () => Promise<void>;
17
- validate: () => Promise<void>;
18
31
  }