@allurereport/core 3.14.3 → 3.15.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/dist/api.d.ts +2 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +25 -4
- package/dist/known.d.ts +5 -1
- package/dist/known.js +70 -16
- package/dist/qualityGate/qualityGate.d.ts +4 -1
- package/dist/qualityGate/qualityGate.js +33 -9
- package/dist/qualityGate/rules.d.ts +11 -3
- package/dist/qualityGate/rules.js +37 -17
- package/dist/report.js +68 -43
- package/dist/store/convert.js +1 -1
- package/dist/store/retrySubstore.d.ts +1 -0
- package/dist/store/retrySubstore.js +3 -1
- package/dist/store/store.d.ts +5 -2
- package/dist/store/store.js +46 -29
- package/package.json +22 -20
package/dist/api.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface PluginInstance {
|
|
|
7
7
|
plugin: Plugin;
|
|
8
8
|
options: Record<string, any>;
|
|
9
9
|
}
|
|
10
|
-
type FullConfigRequiredFromConfig = Required<Pick<Config, "name" | "output" | "open"
|
|
10
|
+
type FullConfigRequiredFromConfig = Required<Pick<Config, "name" | "output" | "open">>;
|
|
11
11
|
export interface FullConfig extends Omit<Config, "name" | "output" | "open" | "allureService" | "knownIssuesPath" | "plugins" | "port">, FullConfigRequiredFromConfig {
|
|
12
12
|
port: Config["port"] | undefined;
|
|
13
13
|
allowedEnvironments?: Config["allowedEnvironments"];
|
|
@@ -15,6 +15,7 @@ export interface FullConfig extends Omit<Config, "name" | "output" | "open" | "a
|
|
|
15
15
|
readers?: ResultsReader[];
|
|
16
16
|
plugins?: PluginInstance[];
|
|
17
17
|
known?: KnownTestFailure[];
|
|
18
|
+
knownIssuesPath?: Config["knownIssuesPath"];
|
|
18
19
|
realTime?: any;
|
|
19
20
|
qualityGate?: Config["qualityGate"];
|
|
20
21
|
allureService?: ResolvedAllureServiceConfig;
|
package/dist/config.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export declare const validateConfig: (config: Config) => {
|
|
|
25
25
|
export declare const loadYamlConfig: (configPath: string) => Promise<Config>;
|
|
26
26
|
export declare const loadJsonConfig: (configPath: string) => Promise<Config>;
|
|
27
27
|
export declare const loadJsConfig: (configPath: string) => Promise<Config>;
|
|
28
|
+
export declare const loadTsConfig: (configPath: string) => Promise<Config>;
|
|
28
29
|
export declare const resolveConfig: (config: Config, override?: ConfigOverride) => Promise<FullConfig>;
|
|
29
30
|
export declare const readConfig: (cwd?: string, configPath?: string, override?: ConfigOverride) => Promise<FullConfig>;
|
|
30
31
|
export declare const readRawConfig: (cwd?: string, configPath?: string) => Promise<Config>;
|
package/dist/config.js
CHANGED
|
@@ -2,8 +2,9 @@ import { readFile, stat } from "node:fs/promises";
|
|
|
2
2
|
import { extname, resolve } from "node:path";
|
|
3
3
|
import * as process from "node:process";
|
|
4
4
|
import { validateEnvironmentName } from "@allurereport/core-api";
|
|
5
|
+
import { createJiti } from "jiti";
|
|
5
6
|
import { parse } from "yaml";
|
|
6
|
-
import { readKnownIssues } from "./known.js";
|
|
7
|
+
import { DEFAULT_KNOWN_ISSUES_PATH, hasKnownIssueRules, readKnownIssues, resolveExactIssuesFilePath } from "./known.js";
|
|
7
8
|
import { FileSystemReportFiles } from "./plugin.js";
|
|
8
9
|
import { environmentIdentityById, environmentIdentityByName, validateAllowedEnvironmentIds, normalizeEnvironmentDescriptorMap, validateAllowedEnvironmentId, } from "./utils/environment.js";
|
|
9
10
|
import { importWrapper } from "./utils/module.js";
|
|
@@ -13,6 +14,9 @@ const CONFIG_FILENAMES = [
|
|
|
13
14
|
"allurerc.js",
|
|
14
15
|
"allurerc.mjs",
|
|
15
16
|
"allurerc.cjs",
|
|
17
|
+
"allurerc.ts",
|
|
18
|
+
"allurerc.mts",
|
|
19
|
+
"allurerc.cts",
|
|
16
20
|
"allurerc.json",
|
|
17
21
|
"allurerc.yaml",
|
|
18
22
|
"allurerc.yml",
|
|
@@ -80,7 +84,7 @@ export const findConfig = async (cwd, configPath) => {
|
|
|
80
84
|
return resolved;
|
|
81
85
|
}
|
|
82
86
|
}
|
|
83
|
-
catch
|
|
87
|
+
catch {
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
};
|
|
@@ -94,6 +98,7 @@ export const validateConfig = (config) => {
|
|
|
94
98
|
"historyPath",
|
|
95
99
|
"historyLimit",
|
|
96
100
|
"knownIssuesPath",
|
|
101
|
+
"knownIssues",
|
|
97
102
|
"plugins",
|
|
98
103
|
"defaultLabels",
|
|
99
104
|
"variables",
|
|
@@ -141,6 +146,10 @@ export const loadJsonConfig = async (configPath) => {
|
|
|
141
146
|
export const loadJsConfig = async (configPath) => {
|
|
142
147
|
return (await import(normalizeImportPath(configPath))).default;
|
|
143
148
|
};
|
|
149
|
+
export const loadTsConfig = async (configPath) => {
|
|
150
|
+
const jiti = createJiti(import.meta.url);
|
|
151
|
+
return await jiti.import(resolve(configPath), { default: true });
|
|
152
|
+
};
|
|
144
153
|
const resolveConfigEnvironments = (config) => {
|
|
145
154
|
const errors = [];
|
|
146
155
|
const { ids: allowedEnvironments, idsSet: allowedEnvironmentIds, errors: allowedEnvironmentErrors, } = validateAllowedEnvironmentIds(config.allowedEnvironments, "config.allowedEnvironments");
|
|
@@ -192,9 +201,11 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
192
201
|
const historyPath = override.historyPath ?? config.historyPath;
|
|
193
202
|
const historyLimit = override.historyLimit ?? config.historyLimit;
|
|
194
203
|
const appendHistory = config.appendHistory ?? true;
|
|
195
|
-
const
|
|
204
|
+
const configuredKnownIssuesPath = override.knownIssuesPath ?? config.knownIssuesPath;
|
|
205
|
+
const knownIssuesPathInput = configuredKnownIssuesPath ?? (hasKnownIssueRules(config.knownIssues) ? DEFAULT_KNOWN_ISSUES_PATH : undefined);
|
|
206
|
+
const knownIssuesPath = await resolveExactIssuesFilePath(knownIssuesPathInput, "known issues");
|
|
196
207
|
const output = resolve(override.output ?? config.output ?? "./allure-report");
|
|
197
|
-
const known = await readKnownIssues(knownIssuesPath);
|
|
208
|
+
const known = knownIssuesPath ? await readKnownIssues(knownIssuesPath) : undefined;
|
|
198
209
|
const variables = config.variables ?? {};
|
|
199
210
|
let pluginInstances = [];
|
|
200
211
|
const hasPluginsOverride = override.plugins !== undefined;
|
|
@@ -225,6 +236,7 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
225
236
|
hideLabels,
|
|
226
237
|
knownIssuesPath,
|
|
227
238
|
known,
|
|
239
|
+
knownIssues: config.knownIssues,
|
|
228
240
|
environment,
|
|
229
241
|
allowedEnvironments,
|
|
230
242
|
variables,
|
|
@@ -265,6 +277,11 @@ export const readConfig = async (cwd = process.cwd(), configPath, override) => {
|
|
|
265
277
|
case ".mjs":
|
|
266
278
|
config = await loadJsConfig(cfg);
|
|
267
279
|
break;
|
|
280
|
+
case ".ts":
|
|
281
|
+
case ".cts":
|
|
282
|
+
case ".mts":
|
|
283
|
+
config = await loadTsConfig(cfg);
|
|
284
|
+
break;
|
|
268
285
|
default:
|
|
269
286
|
config = DEFAULT_CONFIG;
|
|
270
287
|
}
|
|
@@ -283,6 +300,10 @@ export const readRawConfig = async (cwd = process.cwd(), configPath) => {
|
|
|
283
300
|
case ".cjs":
|
|
284
301
|
case ".mjs":
|
|
285
302
|
return loadJsConfig(cfg);
|
|
303
|
+
case ".ts":
|
|
304
|
+
case ".cts":
|
|
305
|
+
case ".mts":
|
|
306
|
+
return loadTsConfig(cfg);
|
|
286
307
|
default:
|
|
287
308
|
return DEFAULT_CONFIG;
|
|
288
309
|
}
|
package/dist/known.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type { KnownTestFailure } from "@allurereport/core-api";
|
|
1
|
+
import type { KnownIssuesConfig, KnownTestFailure, TestResult } from "@allurereport/core-api";
|
|
2
2
|
import type { AllureStore } from "@allurereport/plugin-api";
|
|
3
|
+
export declare const DEFAULT_KNOWN_ISSUES_PATH = "known-issues.json";
|
|
4
|
+
export declare const hasKnownIssueRules: (knownIssues?: KnownIssuesConfig) => boolean;
|
|
5
|
+
export declare const getKnownIssueByRules: (testResult: TestResult, knownIssues: KnownIssuesConfig | undefined, environmentId?: string) => KnownTestFailure | undefined;
|
|
6
|
+
export declare const resolveExactIssuesFilePath: (pathOrDir: string | undefined, label: string) => Promise<string | undefined>;
|
|
3
7
|
export declare const readKnownIssues: (knownIssuePath: string) => Promise<KnownTestFailure[]>;
|
|
4
8
|
export declare const writeKnownIssues: (store: AllureStore, knownIssuesPath?: string) => Promise<void>;
|
package/dist/known.js
CHANGED
|
@@ -1,9 +1,66 @@
|
|
|
1
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
-
import { resolve } from "node:path";
|
|
1
|
+
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, extname, resolve } from "node:path";
|
|
3
3
|
import { isFileNotFoundError } from "./utils/misc.js";
|
|
4
|
-
const
|
|
4
|
+
export const DEFAULT_KNOWN_ISSUES_PATH = "known-issues.json";
|
|
5
|
+
export const hasKnownIssueRules = (knownIssues) => (knownIssues?.rules?.length ?? 0) > 0;
|
|
6
|
+
const messageMatches = (rule, testResult) => {
|
|
7
|
+
if (!rule.messageRegexp) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
const message = testResult.error?.message;
|
|
11
|
+
return typeof message === "string" && new RegExp(rule.messageRegexp).test(message);
|
|
12
|
+
};
|
|
13
|
+
const testCaseIdMatches = (rule, testResult) => {
|
|
14
|
+
const { id, allureId, externalId } = testResult.testCase ?? {};
|
|
15
|
+
return !rule.testCaseId || [id, allureId, externalId].includes(rule.testCaseId);
|
|
16
|
+
};
|
|
17
|
+
const retryHashMatches = (rule, testResult) => {
|
|
18
|
+
return !rule.retryHash || rule.retryHash === testResult.retryHash;
|
|
19
|
+
};
|
|
20
|
+
const environmentMatches = (rule, testResult) => {
|
|
21
|
+
return !rule.environmentId || rule.environmentId === testResult.environment;
|
|
22
|
+
};
|
|
23
|
+
export const getKnownIssueByRules = (testResult, knownIssues, environmentId) => {
|
|
24
|
+
if (!testResult.historyId || !hasKnownIssueRules(knownIssues)) {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
const matchedRule = knownIssues.rules.find((rule) => [messageMatches, testCaseIdMatches, environmentMatches, retryHashMatches].every((matcher) => matcher(rule, testResult)));
|
|
28
|
+
if (!matchedRule) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
historyId: testResult.historyId,
|
|
33
|
+
reason: matchedRule.decision.reason,
|
|
34
|
+
links: matchedRule.decision.links,
|
|
35
|
+
error: testResult.error,
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export const resolveExactIssuesFilePath = async (pathOrDir, label) => {
|
|
39
|
+
if (!pathOrDir) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
const path = resolve(pathOrDir);
|
|
43
|
+
if (extname(path).toLowerCase() !== ".json") {
|
|
44
|
+
throw new Error(`Invalid ${label} path ${JSON.stringify(pathOrDir)}: expected exact .json file path`);
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const pathStats = await stat(path);
|
|
48
|
+
if (pathStats.isDirectory()) {
|
|
49
|
+
throw new Error(`Invalid ${label} path ${JSON.stringify(pathOrDir)}: expected file, got directory`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
if (!isFileNotFoundError(e)) {
|
|
54
|
+
throw e;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return path;
|
|
58
|
+
};
|
|
5
59
|
export const readKnownIssues = async (knownIssuePath) => {
|
|
6
|
-
const path =
|
|
60
|
+
const path = await resolveExactIssuesFilePath(knownIssuePath, "known issues");
|
|
61
|
+
if (!path) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
7
64
|
try {
|
|
8
65
|
const content = await readFile(path, { encoding: "utf-8" });
|
|
9
66
|
return JSON.parse(content);
|
|
@@ -15,18 +72,15 @@ export const readKnownIssues = async (knownIssuePath) => {
|
|
|
15
72
|
throw e;
|
|
16
73
|
}
|
|
17
74
|
};
|
|
18
|
-
|
|
19
|
-
|
|
75
|
+
const writeKnownIssueRecords = async (knownIssues, knownIssuesPath) => {
|
|
76
|
+
const path = await resolveExactIssuesFilePath(knownIssuesPath, "known issues");
|
|
77
|
+
if (!path) {
|
|
20
78
|
return;
|
|
21
79
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
issues: links.filter((l) => l.type === "issue"),
|
|
29
|
-
comment: "automatically generated from failure by allure known-issue command",
|
|
30
|
-
}));
|
|
31
|
-
await writeFile(knownIssuesPath, JSON.stringify(knownIssues));
|
|
80
|
+
await mkdir(dirname(path), { recursive: true });
|
|
81
|
+
await writeFile(path, `${JSON.stringify(knownIssues)}\n`, "utf-8");
|
|
82
|
+
};
|
|
83
|
+
export const writeKnownIssues = async (store, knownIssuesPath) => {
|
|
84
|
+
const knownIssues = await store.allKnownIssues();
|
|
85
|
+
await writeKnownIssueRecords(knownIssues, knownIssuesPath);
|
|
32
86
|
};
|
|
@@ -4,8 +4,11 @@ export declare const stringifyQualityGateResults: (results: QualityGateValidatio
|
|
|
4
4
|
export declare const convertQualityGateResultsToTestErrors: (results: QualityGateValidationResult[]) => TestError[];
|
|
5
5
|
export declare class QualityGateState {
|
|
6
6
|
#private;
|
|
7
|
-
setResult(rule: string, value: any): void;
|
|
7
|
+
setResult(rule: string, value: any, testResults?: string[]): void;
|
|
8
8
|
getResult(rule: string): any;
|
|
9
|
+
getTestResults(rule: string): string[];
|
|
10
|
+
markTestResultsProcessed(testResults: TestResult[]): void;
|
|
11
|
+
isTestResultProcessed(trId: string): boolean;
|
|
9
12
|
}
|
|
10
13
|
export declare class QualityGate {
|
|
11
14
|
private readonly config;
|
|
@@ -3,7 +3,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
3
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
4
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
5
|
};
|
|
6
|
-
var _QualityGateState_state;
|
|
6
|
+
var _QualityGateState_state, _QualityGateState_processedTestResultIds;
|
|
7
7
|
import { gray, red } from "yoctocolors";
|
|
8
8
|
import { qualityGateDefaultRules } from "./rules.js";
|
|
9
9
|
export const stringifyQualityGateResults = (results) => {
|
|
@@ -30,21 +30,43 @@ export const convertQualityGateResultsToTestErrors = (results) => {
|
|
|
30
30
|
export class QualityGateState {
|
|
31
31
|
constructor() {
|
|
32
32
|
_QualityGateState_state.set(this, {});
|
|
33
|
+
_QualityGateState_processedTestResultIds.set(this, new Set());
|
|
33
34
|
}
|
|
34
|
-
setResult(rule, value) {
|
|
35
|
-
__classPrivateFieldGet(this, _QualityGateState_state, "f")[rule]
|
|
35
|
+
setResult(rule, value, testResults = []) {
|
|
36
|
+
const previousTestResults = __classPrivateFieldGet(this, _QualityGateState_state, "f")[rule]?.testResults ?? [];
|
|
37
|
+
__classPrivateFieldGet(this, _QualityGateState_state, "f")[rule] = {
|
|
38
|
+
result: value,
|
|
39
|
+
testResults: [...new Set([...previousTestResults, ...testResults])],
|
|
40
|
+
};
|
|
36
41
|
}
|
|
37
42
|
getResult(rule) {
|
|
38
|
-
return __classPrivateFieldGet(this, _QualityGateState_state, "f")[rule];
|
|
43
|
+
return __classPrivateFieldGet(this, _QualityGateState_state, "f")[rule]?.result;
|
|
44
|
+
}
|
|
45
|
+
getTestResults(rule) {
|
|
46
|
+
return [...(__classPrivateFieldGet(this, _QualityGateState_state, "f")[rule]?.testResults ?? [])];
|
|
47
|
+
}
|
|
48
|
+
markTestResultsProcessed(testResults) {
|
|
49
|
+
testResults.forEach(({ id }) => __classPrivateFieldGet(this, _QualityGateState_processedTestResultIds, "f").add(id));
|
|
50
|
+
}
|
|
51
|
+
isTestResultProcessed(trId) {
|
|
52
|
+
return __classPrivateFieldGet(this, _QualityGateState_processedTestResultIds, "f").has(trId);
|
|
39
53
|
}
|
|
40
54
|
}
|
|
41
|
-
_QualityGateState_state = new WeakMap();
|
|
55
|
+
_QualityGateState_state = new WeakMap(), _QualityGateState_processedTestResultIds = new WeakMap();
|
|
42
56
|
export class QualityGate {
|
|
43
57
|
constructor(config) {
|
|
44
58
|
this.config = config;
|
|
45
59
|
}
|
|
46
60
|
async validate(payload) {
|
|
47
61
|
const { state, trs, knownIssues, environment } = payload;
|
|
62
|
+
const trsToValidateById = new Map();
|
|
63
|
+
for (const tr of trs) {
|
|
64
|
+
if (tr.isRetry || state?.isTestResultProcessed(tr.id)) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
trsToValidateById.set(tr.id, tr);
|
|
68
|
+
}
|
|
69
|
+
const trsToValidate = trsToValidateById.values().toArray();
|
|
48
70
|
const { rules, use = [...qualityGateDefaultRules] } = this.config;
|
|
49
71
|
const results = [];
|
|
50
72
|
let fastFailed = false;
|
|
@@ -58,6 +80,7 @@ export class QualityGate {
|
|
|
58
80
|
if (fastFailed) {
|
|
59
81
|
break;
|
|
60
82
|
}
|
|
83
|
+
const filteredTrs = ruleset.filter ? trsToValidate.filter(ruleset.filter) : trsToValidate;
|
|
61
84
|
for (const [key, expected] of Object.entries(ruleset)) {
|
|
62
85
|
if (key === "filter" || key === "id" || key === "fastFail") {
|
|
63
86
|
continue;
|
|
@@ -66,13 +89,12 @@ export class QualityGate {
|
|
|
66
89
|
if (!rule) {
|
|
67
90
|
throw new Error(`Rule ${key} is not provided. Make sure you have provided it in the "use" field of the quality gate config!`);
|
|
68
91
|
}
|
|
69
|
-
const trsToValidate = ruleset.filter ? trs.filter(ruleset.filter) : trs;
|
|
70
92
|
const ruleId = ruleset.id ? [ruleset.id, rule.rule].join("/") : rule.rule;
|
|
71
93
|
const result = await rule.validate({
|
|
72
|
-
trs:
|
|
94
|
+
trs: filteredTrs,
|
|
73
95
|
state: {
|
|
74
96
|
getResult: () => state?.getResult?.(ruleId),
|
|
75
|
-
setResult: (value) => state?.setResult?.(ruleId, value),
|
|
97
|
+
setResult: (value, testResults) => state?.setResult?.(ruleId, value, testResults),
|
|
76
98
|
},
|
|
77
99
|
expected,
|
|
78
100
|
knownIssues,
|
|
@@ -84,12 +106,13 @@ export class QualityGate {
|
|
|
84
106
|
results.push({
|
|
85
107
|
...result,
|
|
86
108
|
expected,
|
|
87
|
-
rule:
|
|
109
|
+
rule: ruleId,
|
|
88
110
|
message: rule.message({
|
|
89
111
|
actual: result.actual,
|
|
90
112
|
expected,
|
|
91
113
|
}),
|
|
92
114
|
environment,
|
|
115
|
+
testResults: [...new Set([...(state?.getTestResults(ruleId) ?? []), ...result.testResults])],
|
|
93
116
|
});
|
|
94
117
|
if (ruleset.fastFail) {
|
|
95
118
|
fastFailed = true;
|
|
@@ -97,6 +120,7 @@ export class QualityGate {
|
|
|
97
120
|
}
|
|
98
121
|
}
|
|
99
122
|
}
|
|
123
|
+
state?.markTestResultsProcessed(trsToValidate);
|
|
100
124
|
return {
|
|
101
125
|
fastFailed,
|
|
102
126
|
results,
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { type QualityGateRule } from "@allurereport/plugin-api";
|
|
2
2
|
export declare const maxFailuresRule: QualityGateRule<number>;
|
|
3
3
|
export declare const minTestsCountRule: QualityGateRule<number>;
|
|
4
|
-
export declare const successRateRule: QualityGateRule<number
|
|
4
|
+
export declare const successRateRule: QualityGateRule<number, {
|
|
5
|
+
totalCount: number;
|
|
6
|
+
unknownCount: number;
|
|
7
|
+
passedCount: number;
|
|
8
|
+
}>;
|
|
5
9
|
export declare const maxDurationRule: QualityGateRule<number>;
|
|
6
|
-
export declare const allTestsContainEnvRule: QualityGateRule<string>;
|
|
10
|
+
export declare const allTestsContainEnvRule: QualityGateRule<string, number>;
|
|
7
11
|
export declare const environmentsTestedRule: QualityGateRule<string[]>;
|
|
8
|
-
export declare const qualityGateDefaultRules: (QualityGateRule<number> | QualityGateRule<
|
|
12
|
+
export declare const qualityGateDefaultRules: (QualityGateRule<number> | QualityGateRule<number, {
|
|
13
|
+
totalCount: number;
|
|
14
|
+
unknownCount: number;
|
|
15
|
+
passedCount: number;
|
|
16
|
+
}> | QualityGateRule<string, number> | QualityGateRule<string[]>)[];
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import { filterSuccessful,
|
|
1
|
+
import { filterSuccessful, filterUnsuccessful } from "@allurereport/core-api";
|
|
2
2
|
import { bold } from "yoctocolors";
|
|
3
3
|
export const maxFailuresRule = {
|
|
4
4
|
rule: "maxFailures",
|
|
5
5
|
message: ({ actual, expected }) => `The number of failed tests ${bold(String(actual))} exceeds the allowed threshold value ${bold(String(expected))}`,
|
|
6
|
-
validate: async ({ trs,
|
|
7
|
-
const
|
|
8
|
-
const unknown =
|
|
6
|
+
validate: async ({ trs, expected, state }) => {
|
|
7
|
+
const previous = state.getResult() ?? 0;
|
|
8
|
+
const unknown = trs.filter((tr) => !tr.known);
|
|
9
9
|
const failedTrs = unknown.filter(filterUnsuccessful);
|
|
10
|
-
const
|
|
11
|
-
|
|
10
|
+
const testResults = failedTrs.map((tr) => tr.id);
|
|
11
|
+
const actual = previous + failedTrs.length;
|
|
12
|
+
state.setResult(actual, testResults);
|
|
12
13
|
return {
|
|
13
14
|
success: actual <= expected,
|
|
14
15
|
actual,
|
|
16
|
+
testResults,
|
|
15
17
|
};
|
|
16
18
|
},
|
|
17
19
|
};
|
|
@@ -20,47 +22,64 @@ export const minTestsCountRule = {
|
|
|
20
22
|
message: ({ actual, expected }) => `The total number of tests ${bold(String(actual))} is less than the expected threshold value ${bold(String(expected))}`,
|
|
21
23
|
validate: async ({ trs, expected, state }) => {
|
|
22
24
|
const actual = trs.length + (state.getResult() ?? 0);
|
|
23
|
-
state.setResult(actual);
|
|
25
|
+
state.setResult(actual, []);
|
|
24
26
|
return {
|
|
25
27
|
success: actual >= expected,
|
|
26
28
|
actual,
|
|
29
|
+
testResults: [],
|
|
27
30
|
};
|
|
28
31
|
},
|
|
29
32
|
};
|
|
30
33
|
export const successRateRule = {
|
|
31
34
|
rule: "successRate",
|
|
32
35
|
message: ({ actual, expected }) => `Success rate ${bold(String(actual))} is less, than expected ${bold(String(expected))}`,
|
|
33
|
-
validate: async ({ trs,
|
|
34
|
-
const
|
|
35
|
-
const unknown =
|
|
36
|
+
validate: async ({ trs, expected, state }) => {
|
|
37
|
+
const previous = state.getResult() ?? { totalCount: 0, unknownCount: 0, passedCount: 0 };
|
|
38
|
+
const unknown = trs.filter((tr) => !tr.known);
|
|
36
39
|
const passedTrs = unknown.filter(filterSuccessful);
|
|
37
|
-
const
|
|
40
|
+
const notPassedTrs = unknown.filter((tr) => !filterSuccessful(tr));
|
|
41
|
+
const totalCount = previous.totalCount + trs.length;
|
|
42
|
+
const unknownCount = previous.unknownCount + unknown.length;
|
|
43
|
+
const passedCount = previous.passedCount + passedTrs.length;
|
|
44
|
+
const testResults = notPassedTrs.map((tr) => tr.id);
|
|
45
|
+
const rate = totalCount === 0 ? 0 : unknownCount === 0 ? 1 : passedCount / unknownCount;
|
|
46
|
+
state.setResult({ totalCount, unknownCount, passedCount }, testResults);
|
|
38
47
|
return {
|
|
39
48
|
success: rate >= expected,
|
|
40
49
|
actual: rate,
|
|
50
|
+
testResults,
|
|
41
51
|
};
|
|
42
52
|
},
|
|
43
53
|
};
|
|
44
54
|
export const maxDurationRule = {
|
|
45
55
|
rule: "maxDuration",
|
|
46
56
|
message: ({ actual, expected }) => `Maximum duration of some tests exceed the defined limit; actual ${bold(String(actual))}, expected ${bold(String(expected))}`,
|
|
47
|
-
validate: async ({ trs, expected }) => {
|
|
48
|
-
const
|
|
57
|
+
validate: async ({ trs, expected, state }) => {
|
|
58
|
+
const previous = state.getResult() ?? 0;
|
|
59
|
+
const actual = Math.max(previous, ...trs.map((tr) => tr.duration ?? 0));
|
|
60
|
+
const tooLongTrs = trs.filter((tr) => (tr.duration ?? 0) > expected);
|
|
61
|
+
const testResults = tooLongTrs.map((tr) => tr.id);
|
|
62
|
+
state.setResult(actual, testResults);
|
|
49
63
|
return {
|
|
50
64
|
success: actual <= expected,
|
|
51
65
|
actual,
|
|
66
|
+
testResults,
|
|
52
67
|
};
|
|
53
68
|
},
|
|
54
69
|
};
|
|
55
70
|
export const allTestsContainEnvRule = {
|
|
56
71
|
rule: "allTestsContainEnv",
|
|
57
|
-
message: ({ actual, expected }) => `Not all tests contain the required
|
|
58
|
-
validate: async ({ trs, expected }) => {
|
|
72
|
+
message: ({ actual, expected }) => `Not all tests contain the required "${bold(expected)}" environment, ${bold(actual)} tests have different or missing environment`,
|
|
73
|
+
validate: async ({ trs, expected, state }) => {
|
|
74
|
+
const previous = state.getResult() ?? 0;
|
|
59
75
|
const testsWithoutEnv = trs.filter((tr) => (tr.environment ?? "") !== expected);
|
|
60
|
-
const
|
|
76
|
+
const testResults = testsWithoutEnv.map((tr) => tr.id);
|
|
77
|
+
const actual = testsWithoutEnv.length + previous;
|
|
78
|
+
state.setResult(actual, testResults);
|
|
61
79
|
return {
|
|
62
80
|
success: actual === 0,
|
|
63
81
|
actual,
|
|
82
|
+
testResults,
|
|
64
83
|
};
|
|
65
84
|
},
|
|
66
85
|
};
|
|
@@ -71,11 +90,12 @@ export const environmentsTestedRule = {
|
|
|
71
90
|
const previouslyTested = new Set(state.getResult() ?? []);
|
|
72
91
|
const batchTested = trs.map((tr) => tr.environment).filter((env) => env != null && env !== "");
|
|
73
92
|
const testedEnvs = new Set([...previouslyTested, ...batchTested]);
|
|
74
|
-
state.setResult([...testedEnvs]);
|
|
93
|
+
state.setResult([...testedEnvs], []);
|
|
75
94
|
const missing = expected.filter((env) => !testedEnvs.has(env));
|
|
76
95
|
return {
|
|
77
96
|
success: missing.length === 0,
|
|
78
97
|
actual: missing,
|
|
98
|
+
testResults: [],
|
|
79
99
|
};
|
|
80
100
|
},
|
|
81
101
|
};
|
package/dist/report.js
CHANGED
|
@@ -9,7 +9,7 @@ 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 _AllureReport_instances, _AllureReport_ci, _AllureReport_store, _AllureReport_readers, _AllureReport_plugins, _AllureReport_reportFiles, _AllureReport_realtimeChannel, _AllureReport_realtimeUpdateScheduler, _AllureReport_realTime, _AllureReport_hideLabels, _AllureReport_output, _AllureReport_history, _AllureReport_allureServiceClient, _AllureReport_qualityGate, _AllureReport_dump, _AllureReport_categories, _AllureReport_environments, _AllureReport_globalAttachments, _AllureReport_dumpTempDirs, _AllureReport_state, _AllureReport_executionStage, _AllureReport_historyDataPoint, _AllureReport_summaryPath, _AllureReport_summariesByPluginId, _AllureReport_publishedRemoteHrefs, _AllureReport_published, _AllureReport_endGeneratePerfSpan, _AllureReport_publish, _AllureReport_runRealtimeUpdate, _AllureReport_getReportsToPublish, _AllureReport_cleanupFailedRemoteReport, _AllureReport_logPublishError, _AllureReport_applyPublishLinksToSummaries, _AllureReport_cloneSummariesByPluginId, _AllureReport_writeSummaryFiles, _AllureReport_generateRootSummary, _AllureReport_finishGeneratePerfSpan, _AllureReport_finishPerfMetrics, _AllureReport_eachPlugin, _AllureReport_getPluginState;
|
|
12
|
+
var _AllureReport_instances, _AllureReport_ci, _AllureReport_store, _AllureReport_readers, _AllureReport_plugins, _AllureReport_reportFiles, _AllureReport_realtimeChannel, _AllureReport_realtimeUpdateScheduler, _AllureReport_realTime, _AllureReport_hideLabels, _AllureReport_output, _AllureReport_history, _AllureReport_appendHistory, _AllureReport_allureServiceClient, _AllureReport_qualityGate, _AllureReport_dump, _AllureReport_categories, _AllureReport_environments, _AllureReport_globalAttachments, _AllureReport_knownIssuesPath, _AllureReport_dumpTempDirs, _AllureReport_state, _AllureReport_executionStage, _AllureReport_historyDataPoint, _AllureReport_summaryPath, _AllureReport_testResultsRegistryPath, _AllureReport_summariesByPluginId, _AllureReport_publishedRemoteHrefs, _AllureReport_published, _AllureReport_endGeneratePerfSpan, _AllureReport_publish, _AllureReport_runRealtimeUpdate, _AllureReport_restoreStateDumps, _AllureReport_getReportsToPublish, _AllureReport_cleanupFailedRemoteReport, _AllureReport_logPublishError, _AllureReport_applyPublishLinksToSummaries, _AllureReport_cloneSummariesByPluginId, _AllureReport_writeSummaryFiles, _AllureReport_writeTestResultRegistry, _AllureReport_generateRootSummary, _AllureReport_finishGeneratePerfSpan, _AllureReport_finishPerfMetrics, _AllureReport_eachPlugin, _AllureReport_getPluginState;
|
|
13
13
|
import console from "node:console";
|
|
14
14
|
import { randomUUID } from "node:crypto";
|
|
15
15
|
import { once } from "node:events";
|
|
@@ -19,8 +19,9 @@ import { tmpdir } from "node:os";
|
|
|
19
19
|
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
20
20
|
import { promisify } from "node:util";
|
|
21
21
|
import { detect } from "@allurereport/ci";
|
|
22
|
+
import { createProgressLogger } from "@allurereport/cli-commons";
|
|
22
23
|
import { normalizeCategoriesConfig } from "@allurereport/core-api";
|
|
23
|
-
import { AllureStoreDumpFiles, } from "@allurereport/plugin-api";
|
|
24
|
+
import { AllureStoreDumpFiles, createTestResultRegistry, } from "@allurereport/plugin-api";
|
|
24
25
|
import { allure1, allure2, attachments, cucumberjson, junitXml, readXcResultBundle } from "@allurereport/reader";
|
|
25
26
|
import { PathResultFile } from "@allurereport/reader-api";
|
|
26
27
|
import { AllureRemoteHistory, AllureServiceClient, AllureTestOpsClient, KnownError, UnknownError, } from "@allurereport/service";
|
|
@@ -30,6 +31,7 @@ import ZipReadStream from "node-stream-zip";
|
|
|
30
31
|
import pLimit from "p-limit";
|
|
31
32
|
import ZipWriteStream from "zip-stream";
|
|
32
33
|
import { AllureLocalHistory, createHistory } from "./history.js";
|
|
34
|
+
import { writeKnownIssues } from "./known.js";
|
|
33
35
|
import { DefaultPluginState, PluginFiles } from "./plugin.js";
|
|
34
36
|
import { QualityGate } from "./qualityGate/index.js";
|
|
35
37
|
import { DefaultAllureStore } from "./store/store.js";
|
|
@@ -42,6 +44,7 @@ const { version } = JSON.parse(readFileSync(new URL("../package.json", import.me
|
|
|
42
44
|
const INIT_REQUIRED_ERROR_MESSAGE = "report is not initialised. Call the start() method first.";
|
|
43
45
|
const DEFAULT_READ_CONCURRENCY = 64;
|
|
44
46
|
const MAX_READ_CONCURRENCY = 256;
|
|
47
|
+
const TEST_RESULTS_REGISTRY_FILENAME = "test-results.json";
|
|
45
48
|
const readConcurrency = () => {
|
|
46
49
|
const parsed = Number.parseInt(process.env.ALLURE_READ_CONCURRENCY ?? "", 10);
|
|
47
50
|
if (!Number.isFinite(parsed)) {
|
|
@@ -80,17 +83,20 @@ export class AllureReport {
|
|
|
80
83
|
_AllureReport_hideLabels.set(this, void 0);
|
|
81
84
|
_AllureReport_output.set(this, void 0);
|
|
82
85
|
_AllureReport_history.set(this, void 0);
|
|
86
|
+
_AllureReport_appendHistory.set(this, void 0);
|
|
83
87
|
_AllureReport_allureServiceClient.set(this, void 0);
|
|
84
88
|
_AllureReport_qualityGate.set(this, void 0);
|
|
85
89
|
_AllureReport_dump.set(this, void 0);
|
|
86
90
|
_AllureReport_categories.set(this, void 0);
|
|
87
91
|
_AllureReport_environments.set(this, void 0);
|
|
88
92
|
_AllureReport_globalAttachments.set(this, void 0);
|
|
93
|
+
_AllureReport_knownIssuesPath.set(this, void 0);
|
|
89
94
|
_AllureReport_dumpTempDirs.set(this, []);
|
|
90
95
|
_AllureReport_state.set(this, void 0);
|
|
91
96
|
_AllureReport_executionStage.set(this, "init");
|
|
92
97
|
_AllureReport_historyDataPoint.set(this, void 0);
|
|
93
98
|
_AllureReport_summaryPath.set(this, void 0);
|
|
99
|
+
_AllureReport_testResultsRegistryPath.set(this, void 0);
|
|
94
100
|
_AllureReport_summariesByPluginId.set(this, new Map());
|
|
95
101
|
_AllureReport_publishedRemoteHrefs.set(this, new Set());
|
|
96
102
|
_AllureReport_published.set(this, false);
|
|
@@ -109,6 +115,7 @@ export class AllureReport {
|
|
|
109
115
|
historyPoint = createHistory(this.reportUuid, this.reportName, allTcs, allTrs, this.reportUrl);
|
|
110
116
|
__classPrivateFieldSet(this, _AllureReport_historyDataPoint, historyPoint, "f");
|
|
111
117
|
}
|
|
118
|
+
await __classPrivateFieldGet(this, _AllureReport_writeTestResultRegistry, "f").call(this);
|
|
112
119
|
await __classPrivateFieldGet(this, _AllureReport_writeSummaryFiles, "f").call(this);
|
|
113
120
|
await __classPrivateFieldGet(this, _AllureReport_generateRootSummary, "f").call(this);
|
|
114
121
|
if (__classPrivateFieldGet(this, _AllureReport_realTime, "f") || !__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f")) {
|
|
@@ -124,33 +131,20 @@ export class AllureReport {
|
|
|
124
131
|
const linksByPluginId = {};
|
|
125
132
|
const summariesSnapshot = __classPrivateFieldGet(this, _AllureReport_cloneSummariesByPluginId, "f").call(this);
|
|
126
133
|
const uploadProgressMessage = reportsToPublish.length === 1 ? `Publishing "${reportsToPublish[0].pluginId}" report` : "Publishing reports";
|
|
127
|
-
const totalFilesToUpload = reportsToPublish.reduce((acc, report) => acc + Object.keys(report.files).length, 0)
|
|
128
|
-
|
|
134
|
+
const totalFilesToUpload = reportsToPublish.reduce((acc, report) => acc + Object.keys(report.files).length, 0) +
|
|
135
|
+
(__classPrivateFieldGet(this, _AllureReport_testResultsRegistryPath, "f") ? 1 : 0);
|
|
129
136
|
let summariesMutated = false;
|
|
130
137
|
let reportCreated = false;
|
|
131
138
|
let publishErrorMessage = "Report upload has failed, the report won't be published";
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
139
|
+
const progressLogger = createProgressLogger({
|
|
140
|
+
total: totalFilesToUpload,
|
|
141
|
+
message: uploadProgressMessage,
|
|
142
|
+
unitLabel: "files uploaded",
|
|
143
|
+
prefix: "[AllureReport]",
|
|
144
|
+
});
|
|
135
145
|
const endPublishPerfSpan = startPerfSpan(PERF_METRIC_NAMES.publishUploadTotal);
|
|
136
|
-
const logUploadProgress =
|
|
137
|
-
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
if (!force && uploadedFiles < nextProgressLogAt && uploadedFiles !== totalFilesToUpload) {
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
if (!force && uploadedFiles === lastProgressLog) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
console.info(`[AllureReport]: ${uploadProgressMessage}: ${uploadedFiles}/${totalFilesToUpload} files uploaded`);
|
|
147
|
-
lastProgressLog = uploadedFiles;
|
|
148
|
-
nextProgressLogAt = Math.min(totalFilesToUpload, uploadedFiles + progressStep);
|
|
149
|
-
};
|
|
150
|
-
const incrementUploadProgress = (delta = 1) => {
|
|
151
|
-
uploadedFiles = Math.min(totalFilesToUpload, uploadedFiles + delta);
|
|
152
|
-
logUploadProgress();
|
|
153
|
-
};
|
|
146
|
+
const logUploadProgress = progressLogger.log;
|
|
147
|
+
const incrementUploadProgress = progressLogger.increment;
|
|
154
148
|
try {
|
|
155
149
|
logUploadProgress(true);
|
|
156
150
|
await client.createReport({
|
|
@@ -172,6 +166,14 @@ export class AllureReport {
|
|
|
172
166
|
linksByPluginId[report.pluginId] = uploadResult.indexHref;
|
|
173
167
|
}
|
|
174
168
|
}
|
|
169
|
+
if (__classPrivateFieldGet(this, _AllureReport_testResultsRegistryPath, "f")) {
|
|
170
|
+
publishErrorMessage = "Test results registry upload has failed, the report won't be published";
|
|
171
|
+
await client.uploadReport({
|
|
172
|
+
reportUuid: this.reportUuid,
|
|
173
|
+
files: { [TEST_RESULTS_REGISTRY_FILENAME]: __classPrivateFieldGet(this, _AllureReport_testResultsRegistryPath, "f") },
|
|
174
|
+
onProgress: incrementUploadProgress,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
175
177
|
const changedPluginIds = __classPrivateFieldGet(this, _AllureReport_applyPublishLinksToSummaries, "f").call(this, linksByPluginId);
|
|
176
178
|
summariesMutated = changedPluginIds.size > 0;
|
|
177
179
|
if (changedPluginIds.size > 0) {
|
|
@@ -225,6 +227,7 @@ export class AllureReport {
|
|
|
225
227
|
__classPrivateFieldGet(this, _AllureReport_logPublishError, "f").call(this, publishErrorMessage, err);
|
|
226
228
|
}
|
|
227
229
|
finally {
|
|
230
|
+
progressLogger.cancel?.();
|
|
228
231
|
endPublishPerfSpan();
|
|
229
232
|
}
|
|
230
233
|
});
|
|
@@ -238,7 +241,7 @@ export class AllureReport {
|
|
|
238
241
|
}
|
|
239
242
|
try {
|
|
240
243
|
const entries = (await readdir(resultsDirPath, { withFileTypes: true }))
|
|
241
|
-
.filter((dirent) => dirent.isFile())
|
|
244
|
+
.filter((dirent) => dirent.isFile() && !dirent.name.endsWith(".tmp"))
|
|
242
245
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
243
246
|
const limit = pLimit(readConcurrency());
|
|
244
247
|
await Promise.all(entries.map((dirent) => limit(async () => {
|
|
@@ -280,6 +283,11 @@ export class AllureReport {
|
|
|
280
283
|
};
|
|
281
284
|
this.validate = async (params) => {
|
|
282
285
|
const { trs, knownIssues, state, environment } = params;
|
|
286
|
+
const currentKnownIssues = await __classPrivateFieldGet(this, _AllureReport_store, "f").allKnownIssues();
|
|
287
|
+
const effectiveKnownIssues = new Map();
|
|
288
|
+
[...knownIssues, ...currentKnownIssues].forEach((issue) => {
|
|
289
|
+
effectiveKnownIssues.set(issue.historyId, issue);
|
|
290
|
+
});
|
|
283
291
|
const qualityGateEnvironment = environment === undefined
|
|
284
292
|
? undefined
|
|
285
293
|
: (environmentIdentityById(__classPrivateFieldGet(this, _AllureReport_environments, "f"), environment)?.name ??
|
|
@@ -287,7 +295,7 @@ export class AllureReport {
|
|
|
287
295
|
environment);
|
|
288
296
|
return __classPrivateFieldGet(this, _AllureReport_qualityGate, "f").validate({
|
|
289
297
|
trs: trs.filter(Boolean),
|
|
290
|
-
knownIssues,
|
|
298
|
+
knownIssues: [...effectiveKnownIssues.values()],
|
|
291
299
|
state,
|
|
292
300
|
environment: qualityGateEnvironment,
|
|
293
301
|
});
|
|
@@ -384,7 +392,7 @@ export class AllureReport {
|
|
|
384
392
|
const addJsonDumpEntry = async (entryName, value) => {
|
|
385
393
|
await addRequiredDumpEntry(Buffer.from(JSON.stringify(value)), entryName);
|
|
386
394
|
};
|
|
387
|
-
const dumpJsonEntries = ({ testResults, testCases, fixtures, attachments, environments, reportVariables, checkResults = {}, globalAttachmentIds = [], globalErrors = [], indexAttachmentByTestResult = {}, indexTestResultByHistoryId = {}, indexTestResultByTestCase = {}, indexAttachmentByFixture = {}, indexFixturesByTestResult = {},
|
|
395
|
+
const dumpJsonEntries = ({ testResults, testCases, fixtures, attachments, environments, reportVariables, checkResults = {}, globalAttachmentIds = [], globalErrors = [], indexAttachmentByTestResult = {}, indexTestResultByHistoryId = {}, indexTestResultByTestCase = {}, indexAttachmentByFixture = {}, indexFixturesByTestResult = {}, knownIssues = {}, qualityGateResults = [], testResultIdsIngestOrder = [], }) => [
|
|
388
396
|
[AllureStoreDumpFiles.TestResults, testResults],
|
|
389
397
|
[AllureStoreDumpFiles.TestCases, testCases],
|
|
390
398
|
[AllureStoreDumpFiles.Fixtures, fixtures],
|
|
@@ -392,6 +400,7 @@ export class AllureReport {
|
|
|
392
400
|
[AllureStoreDumpFiles.CheckResults, checkResults],
|
|
393
401
|
[AllureStoreDumpFiles.Environments, environments],
|
|
394
402
|
[AllureStoreDumpFiles.ReportVariables, reportVariables],
|
|
403
|
+
[AllureStoreDumpFiles.KnownIssues, knownIssues],
|
|
395
404
|
[AllureStoreDumpFiles.GlobalAttachments, globalAttachmentIds],
|
|
396
405
|
[AllureStoreDumpFiles.GlobalErrors, globalErrors],
|
|
397
406
|
[AllureStoreDumpFiles.IndexAttachmentsByTestResults, indexAttachmentByTestResult],
|
|
@@ -399,7 +408,6 @@ export class AllureReport {
|
|
|
399
408
|
[AllureStoreDumpFiles.IndexTestResultsByTestCase, indexTestResultByTestCase],
|
|
400
409
|
[AllureStoreDumpFiles.IndexAttachmentsByFixture, indexAttachmentByFixture],
|
|
401
410
|
[AllureStoreDumpFiles.IndexFixturesByTestResult, indexFixturesByTestResult],
|
|
402
|
-
[AllureStoreDumpFiles.IndexKnownByHistoryId, indexKnownByHistoryId],
|
|
403
411
|
[AllureStoreDumpFiles.QualityGateResults, qualityGateResults],
|
|
404
412
|
[AllureStoreDumpFiles.TestResultIngestOrder, testResultIdsIngestOrder],
|
|
405
413
|
];
|
|
@@ -467,7 +475,11 @@ export class AllureReport {
|
|
|
467
475
|
}
|
|
468
476
|
await rename(dumpTempPath, dumpPath);
|
|
469
477
|
};
|
|
470
|
-
this.restoreState = async (dumps) =>
|
|
478
|
+
this.restoreState = async (dumps) => {
|
|
479
|
+
__classPrivateFieldGet(this, _AllureReport_store, "f").resetIngestOrder();
|
|
480
|
+
await __classPrivateFieldGet(this, _AllureReport_restoreStateDumps, "f").call(this, dumps);
|
|
481
|
+
};
|
|
482
|
+
_AllureReport_restoreStateDumps.set(this, async (dumps) => measurePerf(PERF_METRIC_NAMES.restoreStateTotal, async () => {
|
|
471
483
|
for (const dump of dumps) {
|
|
472
484
|
await measurePerf(PERF_METRIC_NAMES.restoreStateDump, async () => {
|
|
473
485
|
if (!existsSync(dump)) {
|
|
@@ -504,7 +516,7 @@ export class AllureReport {
|
|
|
504
516
|
await writeFile(nestedDumpPath, await dumpArchive.entryData(entryName));
|
|
505
517
|
nestedDumpPaths.push(nestedDumpPath);
|
|
506
518
|
}
|
|
507
|
-
await this.
|
|
519
|
+
await __classPrivateFieldGet(this, _AllureReport_restoreStateDumps, "f").call(this, nestedDumpPaths);
|
|
508
520
|
return;
|
|
509
521
|
}
|
|
510
522
|
}
|
|
@@ -522,7 +534,7 @@ export class AllureReport {
|
|
|
522
534
|
const indexTestResultsByTestCaseEntry = await requiredEntryData(AllureStoreDumpFiles.IndexTestResultsByTestCase);
|
|
523
535
|
const indexAttachmentsByFixtureEntry = await requiredEntryData(AllureStoreDumpFiles.IndexAttachmentsByFixture);
|
|
524
536
|
const indexFixturesByTestResultEntry = await requiredEntryData(AllureStoreDumpFiles.IndexFixturesByTestResult);
|
|
525
|
-
const
|
|
537
|
+
const knownIssuesEntry = await requiredEntryData(AllureStoreDumpFiles.KnownIssues);
|
|
526
538
|
const qualityGateResultsEntry = await requiredEntryData(AllureStoreDumpFiles.QualityGateResults);
|
|
527
539
|
const testResultIngestOrderEntry = await optionalEntryData(AllureStoreDumpFiles.TestResultIngestOrder);
|
|
528
540
|
const attachmentsLinks = JSON.parse(attachmentsEntry.toString("utf8"));
|
|
@@ -535,6 +547,7 @@ export class AllureReport {
|
|
|
535
547
|
case AllureStoreDumpFiles.Fixtures:
|
|
536
548
|
case AllureStoreDumpFiles.Environments:
|
|
537
549
|
case AllureStoreDumpFiles.ReportVariables:
|
|
550
|
+
case AllureStoreDumpFiles.KnownIssues:
|
|
538
551
|
case AllureStoreDumpFiles.GlobalAttachments:
|
|
539
552
|
case AllureStoreDumpFiles.GlobalErrors:
|
|
540
553
|
case AllureStoreDumpFiles.IndexAttachmentsByTestResults:
|
|
@@ -542,7 +555,6 @@ export class AllureReport {
|
|
|
542
555
|
case AllureStoreDumpFiles.IndexTestResultsByTestCase:
|
|
543
556
|
case AllureStoreDumpFiles.IndexAttachmentsByFixture:
|
|
544
557
|
case AllureStoreDumpFiles.IndexFixturesByTestResult:
|
|
545
|
-
case AllureStoreDumpFiles.IndexKnownByHistoryId:
|
|
546
558
|
case AllureStoreDumpFiles.QualityGateResults:
|
|
547
559
|
case AllureStoreDumpFiles.TestResultIngestOrder:
|
|
548
560
|
return acc;
|
|
@@ -570,7 +582,7 @@ export class AllureReport {
|
|
|
570
582
|
indexTestResultByTestCase: JSON.parse(indexTestResultsByTestCaseEntry.toString("utf8")),
|
|
571
583
|
indexAttachmentByFixture: JSON.parse(indexAttachmentsByFixtureEntry.toString("utf8")),
|
|
572
584
|
indexFixturesByTestResult: JSON.parse(indexFixturesByTestResultEntry.toString("utf8")),
|
|
573
|
-
|
|
585
|
+
knownIssues: JSON.parse(knownIssuesEntry.toString("utf8")),
|
|
574
586
|
qualityGateResults: JSON.parse(qualityGateResultsEntry.toString("utf8")),
|
|
575
587
|
testResultIdsIngestOrder: testResultIngestOrderEntry
|
|
576
588
|
? JSON.parse(testResultIngestOrderEntry.toString("utf8"))
|
|
@@ -624,7 +636,7 @@ export class AllureReport {
|
|
|
624
636
|
}
|
|
625
637
|
});
|
|
626
638
|
}
|
|
627
|
-
});
|
|
639
|
+
}));
|
|
628
640
|
_AllureReport_getReportsToPublish.set(this, async () => {
|
|
629
641
|
const reports = [];
|
|
630
642
|
for (const { enabled, id, options } of __classPrivateFieldGet(this, _AllureReport_plugins, "f")) {
|
|
@@ -691,6 +703,11 @@ export class AllureReport {
|
|
|
691
703
|
await context.reportFiles.addFile("summary.json", Buffer.from(JSON.stringify(summary)));
|
|
692
704
|
});
|
|
693
705
|
});
|
|
706
|
+
_AllureReport_writeTestResultRegistry.set(this, async () => {
|
|
707
|
+
const testResults = await __classPrivateFieldGet(this, _AllureReport_store, "f").allTestResults({ includeRetries: false });
|
|
708
|
+
const registry = createTestResultRegistry(testResults);
|
|
709
|
+
__classPrivateFieldSet(this, _AllureReport_testResultsRegistryPath, await __classPrivateFieldGet(this, _AllureReport_reportFiles, "f").addFile(TEST_RESULTS_REGISTRY_FILENAME, Buffer.from(JSON.stringify(registry))), "f");
|
|
710
|
+
});
|
|
694
711
|
_AllureReport_generateRootSummary.set(this, async () => {
|
|
695
712
|
const summaries = [...__classPrivateFieldGet(this, _AllureReport_summariesByPluginId, "f").values()].map(clonePluginSummary);
|
|
696
713
|
if (summaries.length > 1) {
|
|
@@ -751,16 +768,21 @@ export class AllureReport {
|
|
|
751
768
|
outputDirFiles = await readdir(__classPrivateFieldGet(this, _AllureReport_output, "f"));
|
|
752
769
|
}
|
|
753
770
|
catch { }
|
|
771
|
+
if (__classPrivateFieldGet(this, _AllureReport_knownIssuesPath, "f")) {
|
|
772
|
+
await writeKnownIssues(__classPrivateFieldGet(this, _AllureReport_store, "f"), __classPrivateFieldGet(this, _AllureReport_knownIssuesPath, "f"));
|
|
773
|
+
}
|
|
754
774
|
if (outputDirFiles.length === 0) {
|
|
755
775
|
return;
|
|
756
776
|
}
|
|
757
|
-
const
|
|
758
|
-
const
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
if (reportStats.isDirectory() && outputDirectoryEntries.length === 1) {
|
|
777
|
+
const outputEntries = await Promise.all(outputDirFiles.map(async (file) => ({ file, stats: await lstat(join(__classPrivateFieldGet(this, _AllureReport_output, "f"), file)) })));
|
|
778
|
+
const outputDirectoryEntries = outputEntries.filter(({ stats }) => stats.isDirectory());
|
|
779
|
+
if (outputDirectoryEntries.length === 1) {
|
|
780
|
+
const reportPath = join(__classPrivateFieldGet(this, _AllureReport_output, "f"), outputDirectoryEntries[0].file);
|
|
762
781
|
const reportContent = await readdir(reportPath);
|
|
763
782
|
for (const entry of reportContent) {
|
|
783
|
+
if (entry === TEST_RESULTS_REGISTRY_FILENAME) {
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
764
786
|
const currentFilePath = join(reportPath, entry);
|
|
765
787
|
const newFilePath = resolve(dirname(currentFilePath), "..", entry);
|
|
766
788
|
await rename(currentFilePath, newFilePath);
|
|
@@ -773,7 +795,7 @@ export class AllureReport {
|
|
|
773
795
|
}
|
|
774
796
|
catch { }
|
|
775
797
|
}
|
|
776
|
-
if (__classPrivateFieldGet(this, _AllureReport_history, "f")) {
|
|
798
|
+
if (__classPrivateFieldGet(this, _AllureReport_history, "f") && __classPrivateFieldGet(this, _AllureReport_appendHistory, "f")) {
|
|
777
799
|
try {
|
|
778
800
|
await __classPrivateFieldGet(this, _AllureReport_store, "f").appendHistory(__classPrivateFieldGet(this, _AllureReport_historyDataPoint, "f"));
|
|
779
801
|
}
|
|
@@ -870,7 +892,7 @@ export class AllureReport {
|
|
|
870
892
|
}
|
|
871
893
|
}
|
|
872
894
|
});
|
|
873
|
-
const { name, readers = [allure1, allure2, cucumberjson, junitXml, attachments], plugins = [], known, reportFiles, realTime, historyPath, historyLimit, defaultLabels = {}, variables = {}, environment, allowedEnvironments, environments, output, hideLabels, qualityGate, dump, categories, allureService, globalAttachments, } = opts;
|
|
895
|
+
const { name, readers = [allure1, allure2, cucumberjson, junitXml, attachments], plugins = [], known, knownIssues, knownIssuesPath, reportFiles, realTime, historyPath, historyLimit, appendHistory, defaultLabels = {}, variables = {}, environment, allowedEnvironments, environments, output, hideLabels, qualityGate, dump, categories, allureService, globalAttachments, } = opts;
|
|
874
896
|
const allureServiceAccessToken = allureService?.accessToken;
|
|
875
897
|
if (allureServiceAccessToken) {
|
|
876
898
|
const allureServiceClientConfig = {
|
|
@@ -894,6 +916,8 @@ export class AllureReport {
|
|
|
894
916
|
__classPrivateFieldSet(this, _AllureReport_hideLabels, hideLabels, "f");
|
|
895
917
|
__classPrivateFieldSet(this, _AllureReport_environments, environments ?? {}, "f");
|
|
896
918
|
__classPrivateFieldSet(this, _AllureReport_globalAttachments, globalAttachments, "f");
|
|
919
|
+
__classPrivateFieldSet(this, _AllureReport_appendHistory, appendHistory ?? true, "f");
|
|
920
|
+
__classPrivateFieldSet(this, _AllureReport_knownIssuesPath, knownIssuesPath, "f");
|
|
897
921
|
if (qualityGate) {
|
|
898
922
|
__classPrivateFieldSet(this, _AllureReport_qualityGate, new QualityGate(qualityGate), "f");
|
|
899
923
|
}
|
|
@@ -918,6 +942,7 @@ export class AllureReport {
|
|
|
918
942
|
environmentsConfig: environments,
|
|
919
943
|
history: __classPrivateFieldGet(this, _AllureReport_history, "f"),
|
|
920
944
|
known,
|
|
945
|
+
knownIssuesConfig: knownIssues,
|
|
921
946
|
defaultLabels,
|
|
922
947
|
environment,
|
|
923
948
|
allowedEnvironments,
|
|
@@ -940,6 +965,6 @@ export class AllureReport {
|
|
|
940
965
|
return __classPrivateFieldGet(this, _AllureReport_realtimeChannel, "f").dispatcher;
|
|
941
966
|
}
|
|
942
967
|
}
|
|
943
|
-
_AllureReport_ci = new WeakMap(), _AllureReport_store = new WeakMap(), _AllureReport_readers = new WeakMap(), _AllureReport_plugins = new WeakMap(), _AllureReport_reportFiles = new WeakMap(), _AllureReport_realtimeChannel = new WeakMap(), _AllureReport_realtimeUpdateScheduler = new WeakMap(), _AllureReport_realTime = new WeakMap(), _AllureReport_hideLabels = new WeakMap(), _AllureReport_output = new WeakMap(), _AllureReport_history = new WeakMap(), _AllureReport_allureServiceClient = new WeakMap(), _AllureReport_qualityGate = new WeakMap(), _AllureReport_dump = new WeakMap(), _AllureReport_categories = new WeakMap(), _AllureReport_environments = new WeakMap(), _AllureReport_globalAttachments = new WeakMap(), _AllureReport_dumpTempDirs = new WeakMap(), _AllureReport_state = new WeakMap(), _AllureReport_executionStage = new WeakMap(), _AllureReport_historyDataPoint = new WeakMap(), _AllureReport_summaryPath = new WeakMap(), _AllureReport_summariesByPluginId = new WeakMap(), _AllureReport_publishedRemoteHrefs = new WeakMap(), _AllureReport_published = new WeakMap(), _AllureReport_endGeneratePerfSpan = new WeakMap(), _AllureReport_publish = new WeakMap(), _AllureReport_runRealtimeUpdate = new WeakMap(), _AllureReport_getReportsToPublish = new WeakMap(), _AllureReport_cleanupFailedRemoteReport = new WeakMap(), _AllureReport_logPublishError = new WeakMap(), _AllureReport_applyPublishLinksToSummaries = new WeakMap(), _AllureReport_cloneSummariesByPluginId = new WeakMap(), _AllureReport_writeSummaryFiles = new WeakMap(), _AllureReport_generateRootSummary = new WeakMap(), _AllureReport_finishGeneratePerfSpan = new WeakMap(), _AllureReport_finishPerfMetrics = new WeakMap(), _AllureReport_eachPlugin = new WeakMap(), _AllureReport_instances = new WeakSet(), _AllureReport_getPluginState = function _AllureReport_getPluginState(init, id) {
|
|
968
|
+
_AllureReport_ci = new WeakMap(), _AllureReport_store = new WeakMap(), _AllureReport_readers = new WeakMap(), _AllureReport_plugins = new WeakMap(), _AllureReport_reportFiles = new WeakMap(), _AllureReport_realtimeChannel = new WeakMap(), _AllureReport_realtimeUpdateScheduler = new WeakMap(), _AllureReport_realTime = new WeakMap(), _AllureReport_hideLabels = new WeakMap(), _AllureReport_output = new WeakMap(), _AllureReport_history = new WeakMap(), _AllureReport_appendHistory = new WeakMap(), _AllureReport_allureServiceClient = new WeakMap(), _AllureReport_qualityGate = new WeakMap(), _AllureReport_dump = new WeakMap(), _AllureReport_categories = new WeakMap(), _AllureReport_environments = new WeakMap(), _AllureReport_globalAttachments = new WeakMap(), _AllureReport_knownIssuesPath = new WeakMap(), _AllureReport_dumpTempDirs = new WeakMap(), _AllureReport_state = new WeakMap(), _AllureReport_executionStage = new WeakMap(), _AllureReport_historyDataPoint = new WeakMap(), _AllureReport_summaryPath = new WeakMap(), _AllureReport_testResultsRegistryPath = new WeakMap(), _AllureReport_summariesByPluginId = new WeakMap(), _AllureReport_publishedRemoteHrefs = new WeakMap(), _AllureReport_published = new WeakMap(), _AllureReport_endGeneratePerfSpan = new WeakMap(), _AllureReport_publish = new WeakMap(), _AllureReport_runRealtimeUpdate = new WeakMap(), _AllureReport_restoreStateDumps = new WeakMap(), _AllureReport_getReportsToPublish = new WeakMap(), _AllureReport_cleanupFailedRemoteReport = new WeakMap(), _AllureReport_logPublishError = new WeakMap(), _AllureReport_applyPublishLinksToSummaries = new WeakMap(), _AllureReport_cloneSummariesByPluginId = new WeakMap(), _AllureReport_writeSummaryFiles = new WeakMap(), _AllureReport_writeTestResultRegistry = new WeakMap(), _AllureReport_generateRootSummary = new WeakMap(), _AllureReport_finishGeneratePerfSpan = new WeakMap(), _AllureReport_finishPerfMetrics = new WeakMap(), _AllureReport_eachPlugin = new WeakMap(), _AllureReport_instances = new WeakSet(), _AllureReport_getPluginState = function _AllureReport_getPluginState(init, id) {
|
|
944
969
|
return init ? new DefaultPluginState({}) : __classPrivateFieldGet(this, _AllureReport_state, "f")?.[id];
|
|
945
970
|
};
|
package/dist/store/convert.js
CHANGED
|
@@ -236,7 +236,7 @@ const convertLink = (link) => ({
|
|
|
236
236
|
type: link.type,
|
|
237
237
|
});
|
|
238
238
|
const calculateTestId = (raw) => {
|
|
239
|
-
const maybeAllureId = raw.labels?.find((label) => label.name === "ALLURE_ID" || label.name === "AS_ID")?.value;
|
|
239
|
+
const maybeAllureId = raw.labels?.find((label) => (label.name === "ALLURE_ID" || label.name === "AS_ID") && label.value !== "-1")?.value;
|
|
240
240
|
if (maybeAllureId) {
|
|
241
241
|
return [md5(`ALLURE_ID=${maybeAllureId}`), maybeAllureId];
|
|
242
242
|
}
|
|
@@ -4,6 +4,7 @@ export declare const calculateRetryHash: (testCaseId: string | undefined, parame
|
|
|
4
4
|
export declare class RetrySubstore {
|
|
5
5
|
#private;
|
|
6
6
|
recordIngestOrder(testResultId: string): void;
|
|
7
|
+
resetIngestOrder(): void;
|
|
7
8
|
restoreIngestOrder(restoredIds: string[] | undefined, hasTestResult: (testResultId: string) => boolean): void;
|
|
8
9
|
ingestOrderIdsForDump(): string[];
|
|
9
10
|
upsert(testResult: TestResult): void;
|
|
@@ -31,8 +31,10 @@ export class RetrySubstore {
|
|
|
31
31
|
}
|
|
32
32
|
__classPrivateFieldGet(this, _RetrySubstore_testResultIngestIndexById, "f").set(testResultId, __classPrivateFieldGet(this, _RetrySubstore_testResultIngestIndexById, "f").size);
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
resetIngestOrder() {
|
|
35
35
|
__classPrivateFieldGet(this, _RetrySubstore_testResultIngestIndexById, "f").clear();
|
|
36
|
+
}
|
|
37
|
+
restoreIngestOrder(restoredIds, hasTestResult) {
|
|
36
38
|
for (const id of restoredIds ?? []) {
|
|
37
39
|
if (!hasTestResult(id) || __classPrivateFieldGet(this, _RetrySubstore_testResultIngestIndexById, "f").has(id)) {
|
|
38
40
|
continue;
|
package/dist/store/store.d.ts
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import { type AllureCheckResult, type AllureHistory, type AttachmentLink, type DefaultLabelsConfig, type EnvironmentIdentity, type EnvironmentsConfig, type GlobalAttachmentLink, type HistoryDataPoint, type HistoryTestResult, type KnownTestFailure, type ReportVariables, type Statistic, type TestCase, type TestEnvGroup, type TestError, type TestFixtureResult, type TestResult } from "@allurereport/core-api";
|
|
1
|
+
import { type AllureCheckResult, type AllureHistory, type AttachmentLink, type DefaultLabelsConfig, type EnvironmentIdentity, type EnvironmentsConfig, type GlobalAttachmentLink, type HistoryDataPoint, type HistoryTestResult, type KnownIssuesConfig, type KnownTestFailure, type ReportVariables, type Statistic, type TestCase, type TestEnvGroup, type TestError, type TestFixtureResult, type TestResult } from "@allurereport/core-api";
|
|
2
2
|
import { type AllureStore, type AllureStoreDump, type ExitCode, type PluginGlobalError, type QualityGateValidationResult, type RealtimeEventsDispatcher, type RealtimeSubscriber, type ResultFile, type TestResultFilter } from "@allurereport/plugin-api";
|
|
3
3
|
import type { RawFixtureResult, RawGlobals, RawMetadata, RawTestResult, ReaderContext, ResultsVisitor } from "@allurereport/reader-api";
|
|
4
4
|
export declare const mapToObject: <K extends string | number | symbol, T = any>(map: Map<K, T>) => Record<K, T>;
|
|
5
5
|
export declare const updateMapWithRecord: <K extends string | number | symbol, T = any>(map: Map<K, T>, record: Record<K, T>) => Map<K, T>;
|
|
6
6
|
export declare class DefaultAllureStore implements AllureStore, ResultsVisitor {
|
|
7
7
|
#private;
|
|
8
|
+
readonly known: Map<string, KnownTestFailure>;
|
|
8
9
|
readonly indexTestResultByTestCase: Map<string, TestResult[]>;
|
|
9
10
|
readonly indexTestResultByEnvironmentId: Map<string, TestResult[]>;
|
|
10
11
|
readonly indexTestResultByHistoryId: Map<string, TestResult[]>;
|
|
11
12
|
readonly indexAttachmentByTestResult: Map<string, AttachmentLink[]>;
|
|
12
13
|
readonly indexAttachmentByFixture: Map<string, AttachmentLink[]>;
|
|
13
14
|
readonly indexFixturesByTestResult: Map<string, TestFixtureResult[]>;
|
|
14
|
-
readonly indexKnownByHistoryId: Map<string, KnownTestFailure[]>;
|
|
15
15
|
constructor(params?: {
|
|
16
16
|
history?: AllureHistory;
|
|
17
17
|
known?: KnownTestFailure[];
|
|
18
|
+
knownIssuesConfig?: KnownIssuesConfig;
|
|
18
19
|
realtimeDispatcher?: RealtimeEventsDispatcher;
|
|
19
20
|
realtimeSubscriber?: RealtimeSubscriber;
|
|
20
21
|
defaultLabels?: DefaultLabelsConfig;
|
|
@@ -68,6 +69,7 @@ export declare class DefaultAllureStore implements AllureStore, ResultsVisitor {
|
|
|
68
69
|
attachmentsByTrId(trId: string): Promise<AttachmentLink[]>;
|
|
69
70
|
retriesByTr(tr?: TestResult): Promise<TestResult[]>;
|
|
70
71
|
retriesByTrId(trId: string): Promise<TestResult[]>;
|
|
72
|
+
resetIngestOrder(): void;
|
|
71
73
|
historyByTr(tr: TestResult): Promise<HistoryTestResult[] | undefined>;
|
|
72
74
|
historyByTrId(trId: string): Promise<HistoryTestResult[] | undefined>;
|
|
73
75
|
fixturesByTrId(trId: string): Promise<TestFixtureResult[]>;
|
|
@@ -78,6 +80,7 @@ export declare class DefaultAllureStore implements AllureStore, ResultsVisitor {
|
|
|
78
80
|
retriesByTrId: Map<string, TestResult[]>;
|
|
79
81
|
}>;
|
|
80
82
|
failedTestResults(): Promise<TestResult[]>;
|
|
83
|
+
blockingFailedTestResults(): Promise<TestResult[]>;
|
|
81
84
|
unknownFailedTestResults(): Promise<TestResult[]>;
|
|
82
85
|
testResultsByLabel(labelName: string): Promise<{
|
|
83
86
|
_: TestResult[];
|
package/dist/store/store.js
CHANGED
|
@@ -9,10 +9,11 @@ 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 _DefaultAllureStore_instances, _DefaultAllureStore_testResults, _DefaultAllureStore_environmentDisplayNames, _DefaultAllureStore_environmentNameToId, _DefaultAllureStore_attachments, _DefaultAllureStore_attachmentContents, _DefaultAllureStore_testCases, _DefaultAllureStore_metadata, _DefaultAllureStore_history,
|
|
12
|
+
var _DefaultAllureStore_instances, _DefaultAllureStore_testResults, _DefaultAllureStore_environmentDisplayNames, _DefaultAllureStore_environmentNameToId, _DefaultAllureStore_attachments, _DefaultAllureStore_attachmentContents, _DefaultAllureStore_testCases, _DefaultAllureStore_metadata, _DefaultAllureStore_history, _DefaultAllureStore_knownIssuesConfig, _DefaultAllureStore_fixtures, _DefaultAllureStore_defaultLabels, _DefaultAllureStore_environment, _DefaultAllureStore_environmentsConfig, _DefaultAllureStore_reportVariables, _DefaultAllureStore_realtimeDispatcher, _DefaultAllureStore_realtimeSubscriber, _DefaultAllureStore_allowedEnvironmentIds, _DefaultAllureStore_retrySubstore, _DefaultAllureStore_testResultIdsByEnvironmentId, _DefaultAllureStore_cachedEnvironmentEntries, _DefaultAllureStore_globalAttachmentIds, _DefaultAllureStore_globalAttachmentIdsByEnv, _DefaultAllureStore_globalErrors, _DefaultAllureStore_globalErrorsByEnv, _DefaultAllureStore_globalExitCode, _DefaultAllureStore_checkResultsById, _DefaultAllureStore_qualityGateResults, _DefaultAllureStore_historyPoints, _DefaultAllureStore_environments, _DefaultAllureStore_historyIdMatches, _DefaultAllureStore_mergeEnvironmentIdentity, _DefaultAllureStore_environmentIdForLookup, _DefaultAllureStore_addEnvironments, _DefaultAllureStore_environmentIdByName, _DefaultAllureStore_setTestResultEnvironmentId, _DefaultAllureStore_assertAllowedEnvironmentId, _DefaultAllureStore_assertAllowedStoredEnvironment, _DefaultAllureStore_environmentIdByTestResult, _DefaultAllureStore_assignRetryHash, _DefaultAllureStore_setKnownIssue, _DefaultAllureStore_classifyKnownIssue, _DefaultAllureStore_rebuildRetrySubstore, _DefaultAllureStore_resolveGlobalEnvironmentIdentity, _DefaultAllureStore_globalAttachmentId, _DefaultAllureStore_indexGlobalError, _DefaultAllureStore_addGlobalError, _DefaultAllureStore_indexGlobalAttachment, _DefaultAllureStore_addGlobalAttachment, _DefaultAllureStore_restoreAttachmentContent, _DefaultAllureStore_relinkRestoredAttachmentSteps, _DefaultAllureStore_retriesByTr, _DefaultAllureStore_historyByTr;
|
|
13
13
|
import { extname } from "node:path";
|
|
14
14
|
import { DEFAULT_ENVIRONMENT, DEFAULT_ENVIRONMENT_IDENTITY, compareBy, createDictionary, getHistoryIdCandidates, getWorstStatus, normalizeHistoryDataPoint, ordinal, reverse, selectHistoryTestResults, validateEnvironmentId, validateEnvironmentName, } from "@allurereport/core-api";
|
|
15
15
|
import { md5, } from "@allurereport/plugin-api";
|
|
16
|
+
import { getKnownIssueByRules } from "../known.js";
|
|
16
17
|
import { environmentIdentityById, normalizeEnvironmentDescriptorMap, resolveEnvironmentIdentity, resolveStoredEnvironmentIdentity, validateAllowedEnvironmentId, } from "../utils/environment.js";
|
|
17
18
|
import { isFlaky } from "../utils/flaky.js";
|
|
18
19
|
import { getStatusTransition } from "../utils/new.js";
|
|
@@ -63,7 +64,8 @@ export class DefaultAllureStore {
|
|
|
63
64
|
_DefaultAllureStore_testCases.set(this, void 0);
|
|
64
65
|
_DefaultAllureStore_metadata.set(this, void 0);
|
|
65
66
|
_DefaultAllureStore_history.set(this, void 0);
|
|
66
|
-
|
|
67
|
+
_DefaultAllureStore_knownIssuesConfig.set(this, void 0);
|
|
68
|
+
this.known = new Map();
|
|
67
69
|
_DefaultAllureStore_fixtures.set(this, void 0);
|
|
68
70
|
_DefaultAllureStore_defaultLabels.set(this, {});
|
|
69
71
|
_DefaultAllureStore_environment.set(this, void 0);
|
|
@@ -81,7 +83,6 @@ export class DefaultAllureStore {
|
|
|
81
83
|
this.indexAttachmentByTestResult = new Map();
|
|
82
84
|
this.indexAttachmentByFixture = new Map();
|
|
83
85
|
this.indexFixturesByTestResult = new Map();
|
|
84
|
-
this.indexKnownByHistoryId = new Map();
|
|
85
86
|
_DefaultAllureStore_globalAttachmentIds.set(this, []);
|
|
86
87
|
_DefaultAllureStore_globalAttachmentIdsByEnv.set(this, new Map());
|
|
87
88
|
_DefaultAllureStore_globalErrors.set(this, []);
|
|
@@ -91,7 +92,7 @@ export class DefaultAllureStore {
|
|
|
91
92
|
_DefaultAllureStore_qualityGateResults.set(this, []);
|
|
92
93
|
_DefaultAllureStore_historyPoints.set(this, []);
|
|
93
94
|
_DefaultAllureStore_environments.set(this, []);
|
|
94
|
-
const { history, known = [], realtimeDispatcher, realtimeSubscriber, defaultLabels = {}, environment, allowedEnvironments, environmentsConfig = {}, reportVariables = {}, } = params ?? {};
|
|
95
|
+
const { history, known = [], knownIssuesConfig, realtimeDispatcher, realtimeSubscriber, defaultLabels = {}, environment, allowedEnvironments, environmentsConfig = {}, reportVariables = {}, } = params ?? {};
|
|
95
96
|
const errors = [];
|
|
96
97
|
const { normalized: normalizedEnvironmentsConfig, identities, errors: configErrors, } = normalizeEnvironmentDescriptorMap(environmentsConfig, "environmentsConfig");
|
|
97
98
|
errors.push(...configErrors);
|
|
@@ -116,8 +117,8 @@ export class DefaultAllureStore {
|
|
|
116
117
|
__classPrivateFieldSet(this, _DefaultAllureStore_metadata, new Map(), "f");
|
|
117
118
|
__classPrivateFieldSet(this, _DefaultAllureStore_fixtures, new Map(), "f");
|
|
118
119
|
__classPrivateFieldSet(this, _DefaultAllureStore_history, history, "f");
|
|
119
|
-
__classPrivateFieldSet(this,
|
|
120
|
-
|
|
120
|
+
__classPrivateFieldSet(this, _DefaultAllureStore_knownIssuesConfig, knownIssuesConfig, "f");
|
|
121
|
+
known.forEach((ktf) => this.known.set(ktf.historyId, ktf));
|
|
121
122
|
__classPrivateFieldSet(this, _DefaultAllureStore_realtimeDispatcher, realtimeDispatcher, "f");
|
|
122
123
|
__classPrivateFieldSet(this, _DefaultAllureStore_realtimeSubscriber, realtimeSubscriber, "f");
|
|
123
124
|
__classPrivateFieldSet(this, _DefaultAllureStore_defaultLabels, defaultLabels, "f");
|
|
@@ -329,6 +330,7 @@ export class DefaultAllureStore {
|
|
|
329
330
|
testResult.transition = getStatusTransition(testResult, trHistory);
|
|
330
331
|
testResult.flaky = isFlaky(testResult, trHistory);
|
|
331
332
|
}
|
|
333
|
+
testResult.known = __classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_classifyKnownIssue).call(this, testResult, environmentIdentity.id);
|
|
332
334
|
__classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").set(testResult.id, testResult);
|
|
333
335
|
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_setTestResultEnvironmentId).call(this, testResult, environmentIdentity.id);
|
|
334
336
|
__classPrivateFieldGet(this, _DefaultAllureStore_retrySubstore, "f").recordIngestOrder(testResult.id);
|
|
@@ -511,7 +513,7 @@ export class DefaultAllureStore {
|
|
|
511
513
|
}, []);
|
|
512
514
|
}
|
|
513
515
|
async allKnownIssues() {
|
|
514
|
-
return
|
|
516
|
+
return [...this.known.values()].flat();
|
|
515
517
|
}
|
|
516
518
|
async allNewTestResults(filter, history) {
|
|
517
519
|
if (!__classPrivateFieldGet(this, _DefaultAllureStore_history, "f") && !history) {
|
|
@@ -580,6 +582,9 @@ export class DefaultAllureStore {
|
|
|
580
582
|
const tr = __classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").get(trId);
|
|
581
583
|
return __classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_retriesByTr).call(this, tr);
|
|
582
584
|
}
|
|
585
|
+
resetIngestOrder() {
|
|
586
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_retrySubstore, "f").resetIngestOrder();
|
|
587
|
+
}
|
|
583
588
|
async historyByTr(tr) {
|
|
584
589
|
return __classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_historyByTr).call(this, tr);
|
|
585
590
|
}
|
|
@@ -624,16 +629,12 @@ export class DefaultAllureStore {
|
|
|
624
629
|
}
|
|
625
630
|
return failedTrs;
|
|
626
631
|
}
|
|
627
|
-
async
|
|
632
|
+
async blockingFailedTestResults() {
|
|
628
633
|
const failedTestResults = await this.failedTestResults();
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
return failedTestResults.filter((tr) => {
|
|
634
|
-
const historyIdCandidates = getHistoryIdCandidates(tr);
|
|
635
|
-
return (historyIdCandidates.length > 0 && historyIdCandidates.every((historyId) => !knownHistoryIds.has(historyId)));
|
|
636
|
-
});
|
|
634
|
+
return failedTestResults.filter((tr) => !tr.known);
|
|
635
|
+
}
|
|
636
|
+
async unknownFailedTestResults() {
|
|
637
|
+
return this.blockingFailedTestResults();
|
|
637
638
|
}
|
|
638
639
|
async testResultsByLabel(labelName) {
|
|
639
640
|
const results = createDictionary();
|
|
@@ -793,7 +794,7 @@ export class DefaultAllureStore {
|
|
|
793
794
|
indexTestResultByTestCase: {},
|
|
794
795
|
indexAttachmentByFixture: {},
|
|
795
796
|
indexFixturesByTestResult: {},
|
|
796
|
-
|
|
797
|
+
knownIssues: {},
|
|
797
798
|
qualityGateResults: __classPrivateFieldGet(this, _DefaultAllureStore_qualityGateResults, "f"),
|
|
798
799
|
testResultIdsIngestOrder: __classPrivateFieldGet(this, _DefaultAllureStore_retrySubstore, "f").ingestOrderIdsForDump(),
|
|
799
800
|
};
|
|
@@ -812,13 +813,13 @@ export class DefaultAllureStore {
|
|
|
812
813
|
this.indexFixturesByTestResult.forEach((fixtures, trId) => {
|
|
813
814
|
storeDump.indexFixturesByTestResult[trId] = fixtures.map((f) => f.id);
|
|
814
815
|
});
|
|
815
|
-
this.
|
|
816
|
-
storeDump.
|
|
816
|
+
this.known.forEach((known, historyId) => {
|
|
817
|
+
storeDump.knownIssues[historyId] = known;
|
|
817
818
|
});
|
|
818
819
|
return storeDump;
|
|
819
820
|
}
|
|
820
821
|
async restoreState(stateDump, attachmentsContents = {}) {
|
|
821
|
-
const { testResults, attachments, testCases, fixtures, reportVariables, environments, globalAttachmentIds = [], globalErrors = [], checkResults, indexAttachmentByTestResult = {}, indexTestResultByHistoryId = {}, indexTestResultByTestCase = {}, indexAttachmentByFixture = {}, indexFixturesByTestResult = {},
|
|
822
|
+
const { testResults, attachments, testCases, fixtures, reportVariables, environments, globalAttachmentIds = [], globalErrors = [], checkResults, indexAttachmentByTestResult = {}, indexTestResultByHistoryId = {}, indexTestResultByTestCase = {}, indexAttachmentByFixture = {}, indexFixturesByTestResult = {}, knownIssues = {}, qualityGateResults = [], testResultIdsIngestOrder = [], } = stateDump;
|
|
822
823
|
const storedEnvironmentAliases = environments.flatMap((environmentValue) => {
|
|
823
824
|
if (typeof environmentValue === "string") {
|
|
824
825
|
return [{ id: environmentValue, name: environmentValue }];
|
|
@@ -868,6 +869,7 @@ export class DefaultAllureStore {
|
|
|
868
869
|
envNameToId.set(id, id);
|
|
869
870
|
}
|
|
870
871
|
Object.values(testResults).forEach((testResult) => {
|
|
872
|
+
testResult.known ?? (testResult.known = false);
|
|
871
873
|
__classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").set(testResult.id, testResult);
|
|
872
874
|
const storedEnvKey = typeof testResult.environment === "string" ? testResult.environment : undefined;
|
|
873
875
|
const envId = (storedEnvKey ? envNameToId.get(storedEnvKey) : undefined) ?? __classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_environmentIdByTestResult).call(this, testResult);
|
|
@@ -883,6 +885,7 @@ export class DefaultAllureStore {
|
|
|
883
885
|
updateMapWithRecord(__classPrivateFieldGet(this, _DefaultAllureStore_attachments, "f"), attachments);
|
|
884
886
|
updateMapWithRecord(__classPrivateFieldGet(this, _DefaultAllureStore_testCases, "f"), testCases);
|
|
885
887
|
updateMapWithRecord(__classPrivateFieldGet(this, _DefaultAllureStore_fixtures, "f"), fixtures);
|
|
888
|
+
updateMapWithRecord(this.known, knownIssues);
|
|
886
889
|
Object.entries(attachmentsContents).forEach(([id, content]) => {
|
|
887
890
|
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_restoreAttachmentContent).call(this, id, content);
|
|
888
891
|
});
|
|
@@ -971,15 +974,10 @@ export class DefaultAllureStore {
|
|
|
971
974
|
}
|
|
972
975
|
existingFixtures.push(...fxs);
|
|
973
976
|
});
|
|
974
|
-
Object.entries(indexKnownByHistoryId).forEach(([historyId, knownFailures]) => {
|
|
975
|
-
const existingKnown = this.indexKnownByHistoryId.get(historyId);
|
|
976
|
-
if (!existingKnown) {
|
|
977
|
-
this.indexKnownByHistoryId.set(historyId, knownFailures);
|
|
978
|
-
return;
|
|
979
|
-
}
|
|
980
|
-
existingKnown.push(...knownFailures);
|
|
981
|
-
});
|
|
982
977
|
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_rebuildRetrySubstore).call(this);
|
|
978
|
+
for (const testResult of __classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").values()) {
|
|
979
|
+
testResult.known = __classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_classifyKnownIssue).call(this, testResult, __classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_environmentIdByTestResult).call(this, testResult));
|
|
980
|
+
}
|
|
983
981
|
qualityGateResults.forEach((result, index) => {
|
|
984
982
|
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_assertAllowedStoredEnvironment).call(this, {
|
|
985
983
|
environment: result.environment,
|
|
@@ -991,7 +989,9 @@ export class DefaultAllureStore {
|
|
|
991
989
|
});
|
|
992
990
|
}
|
|
993
991
|
}
|
|
994
|
-
_DefaultAllureStore_testResults = new WeakMap(), _DefaultAllureStore_environmentDisplayNames = new WeakMap(), _DefaultAllureStore_environmentNameToId = new WeakMap(), _DefaultAllureStore_attachments = new WeakMap(), _DefaultAllureStore_attachmentContents = new WeakMap(), _DefaultAllureStore_testCases = new WeakMap(), _DefaultAllureStore_metadata = new WeakMap(), _DefaultAllureStore_history = new WeakMap(),
|
|
992
|
+
_DefaultAllureStore_testResults = new WeakMap(), _DefaultAllureStore_environmentDisplayNames = new WeakMap(), _DefaultAllureStore_environmentNameToId = new WeakMap(), _DefaultAllureStore_attachments = new WeakMap(), _DefaultAllureStore_attachmentContents = new WeakMap(), _DefaultAllureStore_testCases = new WeakMap(), _DefaultAllureStore_metadata = new WeakMap(), _DefaultAllureStore_history = new WeakMap(), _DefaultAllureStore_knownIssuesConfig = new WeakMap(), _DefaultAllureStore_fixtures = new WeakMap(), _DefaultAllureStore_defaultLabels = new WeakMap(), _DefaultAllureStore_environment = new WeakMap(), _DefaultAllureStore_environmentsConfig = new WeakMap(), _DefaultAllureStore_reportVariables = new WeakMap(), _DefaultAllureStore_realtimeDispatcher = new WeakMap(), _DefaultAllureStore_realtimeSubscriber = new WeakMap(), _DefaultAllureStore_allowedEnvironmentIds = new WeakMap(), _DefaultAllureStore_retrySubstore = new WeakMap(), _DefaultAllureStore_testResultIdsByEnvironmentId = new WeakMap(), _DefaultAllureStore_cachedEnvironmentEntries = new WeakMap(), _DefaultAllureStore_globalAttachmentIds = new WeakMap(), _DefaultAllureStore_globalAttachmentIdsByEnv = new WeakMap(), _DefaultAllureStore_globalErrors = new WeakMap(), _DefaultAllureStore_globalErrorsByEnv = new WeakMap(), _DefaultAllureStore_globalExitCode = new WeakMap(), _DefaultAllureStore_checkResultsById = new WeakMap(), _DefaultAllureStore_qualityGateResults = new WeakMap(), _DefaultAllureStore_historyPoints = new WeakMap(), _DefaultAllureStore_environments = new WeakMap(), _DefaultAllureStore_instances = new WeakSet(), _DefaultAllureStore_historyIdMatches = function _DefaultAllureStore_historyIdMatches(historyIdCandidates, indexByHistoryId) {
|
|
993
|
+
return historyIdCandidates.find((historyId) => indexByHistoryId.has(historyId));
|
|
994
|
+
}, _DefaultAllureStore_mergeEnvironmentIdentity = function _DefaultAllureStore_mergeEnvironmentIdentity(existingEnvironment, incomingEnvironment) {
|
|
995
995
|
const configuredEnvironment = environmentIdentityById(__classPrivateFieldGet(this, _DefaultAllureStore_environmentsConfig, "f"), incomingEnvironment.id);
|
|
996
996
|
if (configuredEnvironment) {
|
|
997
997
|
return configuredEnvironment;
|
|
@@ -1093,6 +1093,23 @@ _DefaultAllureStore_testResults = new WeakMap(), _DefaultAllureStore_environment
|
|
|
1093
1093
|
const environmentId = options?.environmentId ?? __classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_environmentIdByTestResult).call(this, testResult);
|
|
1094
1094
|
const parametersHash = options?.parametersHash ?? calculateParametersHash(testResult.parameters);
|
|
1095
1095
|
testResult.retryHash = calculateRetryHash(testResult.testCase?.id, parametersHash, environmentId);
|
|
1096
|
+
}, _DefaultAllureStore_setKnownIssue = function _DefaultAllureStore_setKnownIssue(knownIssue) {
|
|
1097
|
+
this.known.set(knownIssue.historyId, knownIssue);
|
|
1098
|
+
}, _DefaultAllureStore_classifyKnownIssue = function _DefaultAllureStore_classifyKnownIssue(testResult, environmentId) {
|
|
1099
|
+
if (testResult.status !== "failed" && testResult.status !== "broken") {
|
|
1100
|
+
return false;
|
|
1101
|
+
}
|
|
1102
|
+
const historyIdCandidates = getHistoryIdCandidates(testResult);
|
|
1103
|
+
if (historyIdCandidates.length === 0) {
|
|
1104
|
+
return false;
|
|
1105
|
+
}
|
|
1106
|
+
const ruleKnownIssue = getKnownIssueByRules(testResult, __classPrivateFieldGet(this, _DefaultAllureStore_knownIssuesConfig, "f"), environmentId);
|
|
1107
|
+
if (ruleKnownIssue) {
|
|
1108
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_setKnownIssue).call(this, ruleKnownIssue);
|
|
1109
|
+
return true;
|
|
1110
|
+
}
|
|
1111
|
+
const knownHistoryId = __classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_historyIdMatches).call(this, historyIdCandidates, this.known);
|
|
1112
|
+
return !!knownHistoryId;
|
|
1096
1113
|
}, _DefaultAllureStore_rebuildRetrySubstore = function _DefaultAllureStore_rebuildRetrySubstore() {
|
|
1097
1114
|
__classPrivateFieldGet(this, _DefaultAllureStore_retrySubstore, "f").reset();
|
|
1098
1115
|
for (const [, testResult] of __classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f")) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.15.0",
|
|
4
4
|
"description": "Collection of generic Allure utilities used across the entire project",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure"
|
|
@@ -25,27 +25,29 @@
|
|
|
25
25
|
"lint:fix": "oxlint --import-plugin --fix src test features stories"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@allurereport/ci": "3.
|
|
29
|
-
"@allurereport/
|
|
30
|
-
"@allurereport/
|
|
31
|
-
"@allurereport/plugin-
|
|
32
|
-
"@allurereport/plugin-
|
|
33
|
-
"@allurereport/plugin-
|
|
34
|
-
"@allurereport/plugin-
|
|
35
|
-
"@allurereport/plugin-
|
|
36
|
-
"@allurereport/plugin-
|
|
37
|
-
"@allurereport/plugin-
|
|
38
|
-
"@allurereport/plugin-
|
|
39
|
-
"@allurereport/plugin-
|
|
40
|
-
"@allurereport/plugin-
|
|
41
|
-
"@allurereport/plugin-
|
|
42
|
-
"@allurereport/plugin-
|
|
43
|
-
"@allurereport/
|
|
44
|
-
"@allurereport/reader
|
|
45
|
-
"@allurereport/
|
|
46
|
-
"@allurereport/
|
|
28
|
+
"@allurereport/ci": "3.15.0",
|
|
29
|
+
"@allurereport/cli-commons": "3.15.0",
|
|
30
|
+
"@allurereport/core-api": "3.15.0",
|
|
31
|
+
"@allurereport/plugin-agent": "3.15.0",
|
|
32
|
+
"@allurereport/plugin-allure2": "3.15.0",
|
|
33
|
+
"@allurereport/plugin-api": "3.15.0",
|
|
34
|
+
"@allurereport/plugin-awesome": "3.15.0",
|
|
35
|
+
"@allurereport/plugin-classic": "3.15.0",
|
|
36
|
+
"@allurereport/plugin-csv": "3.15.0",
|
|
37
|
+
"@allurereport/plugin-dashboard": "3.15.0",
|
|
38
|
+
"@allurereport/plugin-jira": "3.15.0",
|
|
39
|
+
"@allurereport/plugin-log": "3.15.0",
|
|
40
|
+
"@allurereport/plugin-progress": "3.15.0",
|
|
41
|
+
"@allurereport/plugin-slack": "3.15.0",
|
|
42
|
+
"@allurereport/plugin-testops": "3.15.0",
|
|
43
|
+
"@allurereport/plugin-testplan": "3.15.0",
|
|
44
|
+
"@allurereport/reader": "3.15.0",
|
|
45
|
+
"@allurereport/reader-api": "3.15.0",
|
|
46
|
+
"@allurereport/service": "3.15.0",
|
|
47
|
+
"@allurereport/summary": "3.15.0",
|
|
47
48
|
"glob": "^13.0.6",
|
|
48
49
|
"handlebars": "^4.7.9",
|
|
50
|
+
"jiti": "^2.5.1",
|
|
49
51
|
"node-stream-zip": "^1.15.0",
|
|
50
52
|
"p-limit": "^7.3.0",
|
|
51
53
|
"yaml": "^2.8.3",
|