@allurereport/core 3.15.0 → 3.16.1
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 +3 -4
- package/dist/config.d.ts +1 -1
- package/dist/config.js +13 -9
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/qualityGate/qualityGate.d.ts +1 -2
- package/dist/qualityGate/qualityGate.js +3 -3
- package/dist/qualityGate/rules.d.ts +0 -2
- package/dist/qualityGate/rules.js +6 -9
- package/dist/report.d.ts +1 -2
- package/dist/report.js +17 -17
- package/dist/resolutions.d.ts +8 -0
- package/dist/resolutions.js +181 -0
- package/dist/store/convert.js +0 -1
- package/dist/store/store.d.ts +5 -5
- package/dist/store/store.js +78 -37
- package/dist/utils/resultsDir.d.ts +1 -0
- package/dist/utils/resultsDir.js +7 -0
- package/package.json +21 -21
- package/dist/known.d.ts +0 -8
- package/dist/known.js +0 -86
package/dist/api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CategoriesConfig,
|
|
1
|
+
import type { CategoriesConfig, ResolvedAllureServiceConfig } from "@allurereport/core-api";
|
|
2
2
|
import type { Plugin, ReportFiles, Config } from "@allurereport/plugin-api";
|
|
3
3
|
import type { ResultsReader } from "@allurereport/reader-api";
|
|
4
4
|
export interface PluginInstance {
|
|
@@ -8,18 +8,17 @@ export interface PluginInstance {
|
|
|
8
8
|
options: Record<string, any>;
|
|
9
9
|
}
|
|
10
10
|
type FullConfigRequiredFromConfig = Required<Pick<Config, "name" | "output" | "open">>;
|
|
11
|
-
export interface FullConfig extends Omit<Config, "name" | "output" | "open" | "allureService" | "
|
|
11
|
+
export interface FullConfig extends Omit<Config, "name" | "output" | "open" | "allureService" | "plugins" | "port" | "resultsDir">, FullConfigRequiredFromConfig {
|
|
12
12
|
port: Config["port"] | undefined;
|
|
13
13
|
allowedEnvironments?: Config["allowedEnvironments"];
|
|
14
14
|
reportFiles: ReportFiles;
|
|
15
15
|
readers?: ResultsReader[];
|
|
16
16
|
plugins?: PluginInstance[];
|
|
17
|
-
known?: KnownTestFailure[];
|
|
18
|
-
knownIssuesPath?: Config["knownIssuesPath"];
|
|
19
17
|
realTime?: any;
|
|
20
18
|
qualityGate?: Config["qualityGate"];
|
|
21
19
|
allureService?: ResolvedAllureServiceConfig;
|
|
22
20
|
categories?: CategoriesConfig;
|
|
23
21
|
globalAttachments?: string[];
|
|
22
|
+
resultsDir?: string[];
|
|
24
23
|
}
|
|
25
24
|
export {};
|
package/dist/config.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface ConfigOverride {
|
|
|
9
9
|
hideLabels?: Config["hideLabels"];
|
|
10
10
|
historyPath?: Config["historyPath"];
|
|
11
11
|
historyLimit?: Config["historyLimit"];
|
|
12
|
-
|
|
12
|
+
resolutions?: Pick<NonNullable<Config["resolutions"]>, "knownIssuesPath">;
|
|
13
13
|
plugins?: Config["plugins"];
|
|
14
14
|
}
|
|
15
15
|
export declare const parseIntegerConfigValue: (value: unknown, defaultValue: number, minValue: number) => number;
|
package/dist/config.js
CHANGED
|
@@ -4,11 +4,12 @@ import * as process from "node:process";
|
|
|
4
4
|
import { validateEnvironmentName } from "@allurereport/core-api";
|
|
5
5
|
import { createJiti } from "jiti";
|
|
6
6
|
import { parse } from "yaml";
|
|
7
|
-
import { DEFAULT_KNOWN_ISSUES_PATH, hasKnownIssueRules, readKnownIssues, resolveExactIssuesFilePath } from "./known.js";
|
|
8
7
|
import { FileSystemReportFiles } from "./plugin.js";
|
|
8
|
+
import { DEFAULT_KNOWN_ISSUES_PATH, resolveExactIssuesFilePath, validateResolutionsConfig } from "./resolutions.js";
|
|
9
9
|
import { environmentIdentityById, environmentIdentityByName, validateAllowedEnvironmentIds, normalizeEnvironmentDescriptorMap, validateAllowedEnvironmentId, } from "./utils/environment.js";
|
|
10
10
|
import { importWrapper } from "./utils/module.js";
|
|
11
11
|
import { normalizeImportPath } from "./utils/path.js";
|
|
12
|
+
import { normalizeResultsDir } from "./utils/resultsDir.js";
|
|
12
13
|
import { assertValidPluginIdForWindows, isWindows } from "./utils/windows.js";
|
|
13
14
|
const CONFIG_FILENAMES = [
|
|
14
15
|
"allurerc.js",
|
|
@@ -97,8 +98,7 @@ export const validateConfig = (config) => {
|
|
|
97
98
|
"hideLabels",
|
|
98
99
|
"historyPath",
|
|
99
100
|
"historyLimit",
|
|
100
|
-
"
|
|
101
|
-
"knownIssues",
|
|
101
|
+
"resolutions",
|
|
102
102
|
"plugins",
|
|
103
103
|
"defaultLabels",
|
|
104
104
|
"variables",
|
|
@@ -110,6 +110,7 @@ export const validateConfig = (config) => {
|
|
|
110
110
|
"allureService",
|
|
111
111
|
"categories",
|
|
112
112
|
"globalAttachments",
|
|
113
|
+
"resultsDir",
|
|
113
114
|
];
|
|
114
115
|
const unsupportedFields = Object.keys(config).filter((key) => !supportedFields.includes(key));
|
|
115
116
|
return {
|
|
@@ -193,6 +194,7 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
193
194
|
if (!validationResult.valid) {
|
|
194
195
|
throw new Error(`The provided Allure config contains unsupported fields: ${validationResult.fields.join(", ")}`);
|
|
195
196
|
}
|
|
197
|
+
validateResolutionsConfig(config.resolutions);
|
|
196
198
|
const { environments, environment, allowedEnvironments } = resolveConfigEnvironments(config);
|
|
197
199
|
const name = override.name ?? config.name ?? "Allure Report";
|
|
198
200
|
const open = override.open ?? config.open ?? false;
|
|
@@ -201,12 +203,15 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
201
203
|
const historyPath = override.historyPath ?? config.historyPath;
|
|
202
204
|
const historyLimit = override.historyLimit ?? config.historyLimit;
|
|
203
205
|
const appendHistory = config.appendHistory ?? true;
|
|
204
|
-
const configuredKnownIssuesPath = override.knownIssuesPath ?? config.knownIssuesPath;
|
|
205
|
-
const knownIssuesPathInput = configuredKnownIssuesPath ?? (
|
|
206
|
+
const configuredKnownIssuesPath = override.resolutions?.knownIssuesPath ?? config.resolutions?.knownIssuesPath;
|
|
207
|
+
const knownIssuesPathInput = configuredKnownIssuesPath ?? (config.resolutions ? DEFAULT_KNOWN_ISSUES_PATH : undefined);
|
|
206
208
|
const knownIssuesPath = await resolveExactIssuesFilePath(knownIssuesPathInput, "known issues");
|
|
209
|
+
const resolutions = config.resolutions || override.resolutions?.knownIssuesPath !== undefined
|
|
210
|
+
? { ...(config.resolutions ?? { rules: [] }), knownIssuesPath }
|
|
211
|
+
: undefined;
|
|
207
212
|
const output = resolve(override.output ?? config.output ?? "./allure-report");
|
|
208
|
-
const known = knownIssuesPath ? await readKnownIssues(knownIssuesPath) : undefined;
|
|
209
213
|
const variables = config.variables ?? {};
|
|
214
|
+
const resultsDir = normalizeResultsDir(config.resultsDir);
|
|
210
215
|
let pluginInstances = [];
|
|
211
216
|
const hasPluginsOverride = override.plugins !== undefined;
|
|
212
217
|
if (!hasPluginsOverride || Object.keys(override.plugins ?? {}).length > 0) {
|
|
@@ -234,9 +239,7 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
234
239
|
open,
|
|
235
240
|
port,
|
|
236
241
|
hideLabels,
|
|
237
|
-
|
|
238
|
-
known,
|
|
239
|
-
knownIssues: config.knownIssues,
|
|
242
|
+
resolutions,
|
|
240
243
|
environment,
|
|
241
244
|
allowedEnvironments,
|
|
242
245
|
variables,
|
|
@@ -259,6 +262,7 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
259
262
|
: undefined,
|
|
260
263
|
categories: config.categories,
|
|
261
264
|
globalAttachments: config.globalAttachments,
|
|
265
|
+
...(resultsDir.length ? { resultsDir } : {}),
|
|
262
266
|
};
|
|
263
267
|
};
|
|
264
268
|
export const readConfig = async (cwd = process.cwd(), configPath, override) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,9 @@ export * from "./utils/path.js";
|
|
|
5
5
|
export * from "./utils/new.js";
|
|
6
6
|
export * from "./utils/flaky.js";
|
|
7
7
|
export * from "./utils/environment.js";
|
|
8
|
+
export * from "./utils/resultsDir.js";
|
|
8
9
|
export * from "./history.js";
|
|
9
|
-
export * from "./
|
|
10
|
+
export * from "./resolutions.js";
|
|
10
11
|
export { resolveConfig, readConfig, readRawConfig, getPluginInstance } from "./config.js";
|
|
11
12
|
export * from "./report.js";
|
|
12
13
|
export * from "./plugin.js";
|
package/dist/index.js
CHANGED
|
@@ -4,8 +4,9 @@ export * from "./utils/path.js";
|
|
|
4
4
|
export * from "./utils/new.js";
|
|
5
5
|
export * from "./utils/flaky.js";
|
|
6
6
|
export * from "./utils/environment.js";
|
|
7
|
+
export * from "./utils/resultsDir.js";
|
|
7
8
|
export * from "./history.js";
|
|
8
|
-
export * from "./
|
|
9
|
+
export * from "./resolutions.js";
|
|
9
10
|
export { resolveConfig, readConfig, readRawConfig, getPluginInstance } from "./config.js";
|
|
10
11
|
export * from "./report.js";
|
|
11
12
|
export * from "./plugin.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type TestError, type TestResult } from "@allurereport/core-api";
|
|
2
2
|
import type { QualityGateConfig, QualityGateValidationResult } from "@allurereport/plugin-api";
|
|
3
3
|
export declare const stringifyQualityGateResults: (results: QualityGateValidationResult[]) => string;
|
|
4
4
|
export declare const convertQualityGateResultsToTestErrors: (results: QualityGateValidationResult[]) => TestError[];
|
|
@@ -16,7 +16,6 @@ export declare class QualityGate {
|
|
|
16
16
|
validate(payload: {
|
|
17
17
|
state?: QualityGateState;
|
|
18
18
|
trs: TestResult[];
|
|
19
|
-
knownIssues: KnownTestFailure[];
|
|
20
19
|
environment?: string;
|
|
21
20
|
}): Promise<{
|
|
22
21
|
fastFailed: boolean;
|
|
@@ -5,6 +5,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
5
5
|
};
|
|
6
6
|
var _QualityGateState_state, _QualityGateState_processedTestResultIds;
|
|
7
7
|
import { gray, red } from "yoctocolors";
|
|
8
|
+
import { isIgnoredFailure } from "../resolutions.js";
|
|
8
9
|
import { qualityGateDefaultRules } from "./rules.js";
|
|
9
10
|
export const stringifyQualityGateResults = (results) => {
|
|
10
11
|
if (results.length === 0) {
|
|
@@ -58,10 +59,10 @@ export class QualityGate {
|
|
|
58
59
|
this.config = config;
|
|
59
60
|
}
|
|
60
61
|
async validate(payload) {
|
|
61
|
-
const { state, trs,
|
|
62
|
+
const { state, trs, environment } = payload;
|
|
62
63
|
const trsToValidateById = new Map();
|
|
63
64
|
for (const tr of trs) {
|
|
64
|
-
if (tr.isRetry || state?.isTestResultProcessed(tr.id)) {
|
|
65
|
+
if (tr.isRetry || isIgnoredFailure(tr) || state?.isTestResultProcessed(tr.id)) {
|
|
65
66
|
continue;
|
|
66
67
|
}
|
|
67
68
|
trsToValidateById.set(tr.id, tr);
|
|
@@ -97,7 +98,6 @@ export class QualityGate {
|
|
|
97
98
|
setResult: (value, testResults) => state?.setResult?.(ruleId, value, testResults),
|
|
98
99
|
},
|
|
99
100
|
expected,
|
|
100
|
-
knownIssues,
|
|
101
101
|
environment,
|
|
102
102
|
});
|
|
103
103
|
if (result.success) {
|
|
@@ -3,7 +3,6 @@ export declare const maxFailuresRule: QualityGateRule<number>;
|
|
|
3
3
|
export declare const minTestsCountRule: QualityGateRule<number>;
|
|
4
4
|
export declare const successRateRule: QualityGateRule<number, {
|
|
5
5
|
totalCount: number;
|
|
6
|
-
unknownCount: number;
|
|
7
6
|
passedCount: number;
|
|
8
7
|
}>;
|
|
9
8
|
export declare const maxDurationRule: QualityGateRule<number>;
|
|
@@ -11,6 +10,5 @@ export declare const allTestsContainEnvRule: QualityGateRule<string, number>;
|
|
|
11
10
|
export declare const environmentsTestedRule: QualityGateRule<string[]>;
|
|
12
11
|
export declare const qualityGateDefaultRules: (QualityGateRule<number> | QualityGateRule<number, {
|
|
13
12
|
totalCount: number;
|
|
14
|
-
unknownCount: number;
|
|
15
13
|
passedCount: number;
|
|
16
14
|
}> | QualityGateRule<string, number> | QualityGateRule<string[]>)[];
|
|
@@ -5,8 +5,7 @@ export const maxFailuresRule = {
|
|
|
5
5
|
message: ({ actual, expected }) => `The number of failed tests ${bold(String(actual))} exceeds the allowed threshold value ${bold(String(expected))}`,
|
|
6
6
|
validate: async ({ trs, expected, state }) => {
|
|
7
7
|
const previous = state.getResult() ?? 0;
|
|
8
|
-
const
|
|
9
|
-
const failedTrs = unknown.filter(filterUnsuccessful);
|
|
8
|
+
const failedTrs = trs.filter(filterUnsuccessful);
|
|
10
9
|
const testResults = failedTrs.map((tr) => tr.id);
|
|
11
10
|
const actual = previous + failedTrs.length;
|
|
12
11
|
state.setResult(actual, testResults);
|
|
@@ -34,16 +33,14 @@ export const successRateRule = {
|
|
|
34
33
|
rule: "successRate",
|
|
35
34
|
message: ({ actual, expected }) => `Success rate ${bold(String(actual))} is less, than expected ${bold(String(expected))}`,
|
|
36
35
|
validate: async ({ trs, expected, state }) => {
|
|
37
|
-
const previous = state.getResult() ?? { totalCount: 0,
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const notPassedTrs = unknown.filter((tr) => !filterSuccessful(tr));
|
|
36
|
+
const previous = state.getResult() ?? { totalCount: 0, passedCount: 0 };
|
|
37
|
+
const passedTrs = trs.filter(filterSuccessful);
|
|
38
|
+
const notPassedTrs = trs.filter((tr) => !filterSuccessful(tr));
|
|
41
39
|
const totalCount = previous.totalCount + trs.length;
|
|
42
|
-
const unknownCount = previous.unknownCount + unknown.length;
|
|
43
40
|
const passedCount = previous.passedCount + passedTrs.length;
|
|
44
41
|
const testResults = notPassedTrs.map((tr) => tr.id);
|
|
45
|
-
const rate = totalCount === 0 ? 0 :
|
|
46
|
-
state.setResult({ totalCount,
|
|
42
|
+
const rate = totalCount === 0 ? 0 : passedCount / totalCount;
|
|
43
|
+
state.setResult({ totalCount, passedCount }, testResults);
|
|
47
44
|
return {
|
|
48
45
|
success: rate >= expected,
|
|
49
46
|
actual: rate,
|
package/dist/report.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TestResult } from "@allurereport/core-api";
|
|
2
2
|
import { type ResultFile } from "@allurereport/plugin-api";
|
|
3
3
|
import type { FullConfig } from "./api.js";
|
|
4
4
|
import { type QualityGateState } from "./qualityGate/index.js";
|
|
@@ -19,7 +19,6 @@ export declare class AllureReport {
|
|
|
19
19
|
readResult: (data: ResultFile) => Promise<void>;
|
|
20
20
|
validate: (params: {
|
|
21
21
|
trs: TestResult[];
|
|
22
|
-
knownIssues: KnownTestFailure[];
|
|
23
22
|
state?: QualityGateState;
|
|
24
23
|
environment?: string;
|
|
25
24
|
}) => Promise<{
|
package/dist/report.js
CHANGED
|
@@ -31,9 +31,9 @@ import ZipReadStream from "node-stream-zip";
|
|
|
31
31
|
import pLimit from "p-limit";
|
|
32
32
|
import ZipWriteStream from "zip-stream";
|
|
33
33
|
import { AllureLocalHistory, createHistory } from "./history.js";
|
|
34
|
-
import { writeKnownIssues } from "./known.js";
|
|
35
34
|
import { DefaultPluginState, PluginFiles } from "./plugin.js";
|
|
36
35
|
import { QualityGate } from "./qualityGate/index.js";
|
|
36
|
+
import { writeKnownIssues } from "./resolutions.js";
|
|
37
37
|
import { DefaultAllureStore } from "./store/store.js";
|
|
38
38
|
import { environmentIdentityById, environmentIdentityByName } from "./utils/environment.js";
|
|
39
39
|
import { measurePerf, PERF_METRIC_NAMES, PERF_METRIC_PREFIXES, startPerfSpan, writePerfMetrics } from "./utils/perf.js";
|
|
@@ -141,6 +141,7 @@ export class AllureReport {
|
|
|
141
141
|
message: uploadProgressMessage,
|
|
142
142
|
unitLabel: "files uploaded",
|
|
143
143
|
prefix: "[AllureReport]",
|
|
144
|
+
silent: !!__classPrivateFieldGet(this, _AllureReport_realTime, "f"),
|
|
144
145
|
});
|
|
145
146
|
const endPublishPerfSpan = startPerfSpan(PERF_METRIC_NAMES.publishUploadTotal);
|
|
146
147
|
const logUploadProgress = progressLogger.log;
|
|
@@ -282,12 +283,7 @@ export class AllureReport {
|
|
|
282
283
|
}
|
|
283
284
|
};
|
|
284
285
|
this.validate = async (params) => {
|
|
285
|
-
const { trs,
|
|
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
|
-
});
|
|
286
|
+
const { trs, state, environment } = params;
|
|
291
287
|
const qualityGateEnvironment = environment === undefined
|
|
292
288
|
? undefined
|
|
293
289
|
: (environmentIdentityById(__classPrivateFieldGet(this, _AllureReport_environments, "f"), environment)?.name ??
|
|
@@ -295,7 +291,6 @@ export class AllureReport {
|
|
|
295
291
|
environment);
|
|
296
292
|
return __classPrivateFieldGet(this, _AllureReport_qualityGate, "f").validate({
|
|
297
293
|
trs: trs.filter(Boolean),
|
|
298
|
-
knownIssues: [...effectiveKnownIssues.values()],
|
|
299
294
|
state,
|
|
300
295
|
environment: qualityGateEnvironment,
|
|
301
296
|
});
|
|
@@ -392,7 +387,7 @@ export class AllureReport {
|
|
|
392
387
|
const addJsonDumpEntry = async (entryName, value) => {
|
|
393
388
|
await addRequiredDumpEntry(Buffer.from(JSON.stringify(value)), entryName);
|
|
394
389
|
};
|
|
395
|
-
const dumpJsonEntries = ({ testResults, testCases, fixtures, attachments, environments, reportVariables, checkResults = {}, globalAttachmentIds = [], globalErrors = [], indexAttachmentByTestResult = {}, indexTestResultByHistoryId = {}, indexTestResultByTestCase = {}, indexAttachmentByFixture = {}, indexFixturesByTestResult = {},
|
|
390
|
+
const dumpJsonEntries = ({ testResults, testCases, fixtures, attachments, environments, reportVariables, checkResults = {}, globalAttachmentIds = [], globalErrors = [], indexAttachmentByTestResult = {}, indexTestResultByHistoryId = {}, indexTestResultByTestCase = {}, indexTestResultByResolutionIssue = {}, indexAttachmentByFixture = {}, indexFixturesByTestResult = {}, resolutionIssues = {}, qualityGateResults = [], testResultIdsIngestOrder = [], }) => [
|
|
396
391
|
[AllureStoreDumpFiles.TestResults, testResults],
|
|
397
392
|
[AllureStoreDumpFiles.TestCases, testCases],
|
|
398
393
|
[AllureStoreDumpFiles.Fixtures, fixtures],
|
|
@@ -400,12 +395,13 @@ export class AllureReport {
|
|
|
400
395
|
[AllureStoreDumpFiles.CheckResults, checkResults],
|
|
401
396
|
[AllureStoreDumpFiles.Environments, environments],
|
|
402
397
|
[AllureStoreDumpFiles.ReportVariables, reportVariables],
|
|
403
|
-
[AllureStoreDumpFiles.
|
|
398
|
+
[AllureStoreDumpFiles.ResolutionIssues, resolutionIssues],
|
|
404
399
|
[AllureStoreDumpFiles.GlobalAttachments, globalAttachmentIds],
|
|
405
400
|
[AllureStoreDumpFiles.GlobalErrors, globalErrors],
|
|
406
401
|
[AllureStoreDumpFiles.IndexAttachmentsByTestResults, indexAttachmentByTestResult],
|
|
407
402
|
[AllureStoreDumpFiles.IndexTestResultsByHistoryId, indexTestResultByHistoryId],
|
|
408
403
|
[AllureStoreDumpFiles.IndexTestResultsByTestCase, indexTestResultByTestCase],
|
|
404
|
+
[AllureStoreDumpFiles.IndexTestResultsByResolutionIssue, indexTestResultByResolutionIssue],
|
|
409
405
|
[AllureStoreDumpFiles.IndexAttachmentsByFixture, indexAttachmentByFixture],
|
|
410
406
|
[AllureStoreDumpFiles.IndexFixturesByTestResult, indexFixturesByTestResult],
|
|
411
407
|
[AllureStoreDumpFiles.QualityGateResults, qualityGateResults],
|
|
@@ -532,9 +528,10 @@ export class AllureReport {
|
|
|
532
528
|
const indexAttachmentsEntry = await requiredEntryData(AllureStoreDumpFiles.IndexAttachmentsByTestResults);
|
|
533
529
|
const indexTestResultsByHistoryId = await requiredEntryData(AllureStoreDumpFiles.IndexTestResultsByHistoryId);
|
|
534
530
|
const indexTestResultsByTestCaseEntry = await requiredEntryData(AllureStoreDumpFiles.IndexTestResultsByTestCase);
|
|
531
|
+
const indexTestResultsByResolutionIssueEntry = await optionalEntryData(AllureStoreDumpFiles.IndexTestResultsByResolutionIssue);
|
|
535
532
|
const indexAttachmentsByFixtureEntry = await requiredEntryData(AllureStoreDumpFiles.IndexAttachmentsByFixture);
|
|
536
533
|
const indexFixturesByTestResultEntry = await requiredEntryData(AllureStoreDumpFiles.IndexFixturesByTestResult);
|
|
537
|
-
const
|
|
534
|
+
const resolutionIssuesEntry = await optionalEntryData(AllureStoreDumpFiles.ResolutionIssues);
|
|
538
535
|
const qualityGateResultsEntry = await requiredEntryData(AllureStoreDumpFiles.QualityGateResults);
|
|
539
536
|
const testResultIngestOrderEntry = await optionalEntryData(AllureStoreDumpFiles.TestResultIngestOrder);
|
|
540
537
|
const attachmentsLinks = JSON.parse(attachmentsEntry.toString("utf8"));
|
|
@@ -547,12 +544,13 @@ export class AllureReport {
|
|
|
547
544
|
case AllureStoreDumpFiles.Fixtures:
|
|
548
545
|
case AllureStoreDumpFiles.Environments:
|
|
549
546
|
case AllureStoreDumpFiles.ReportVariables:
|
|
550
|
-
case AllureStoreDumpFiles.
|
|
547
|
+
case AllureStoreDumpFiles.ResolutionIssues:
|
|
551
548
|
case AllureStoreDumpFiles.GlobalAttachments:
|
|
552
549
|
case AllureStoreDumpFiles.GlobalErrors:
|
|
553
550
|
case AllureStoreDumpFiles.IndexAttachmentsByTestResults:
|
|
554
551
|
case AllureStoreDumpFiles.IndexTestResultsByHistoryId:
|
|
555
552
|
case AllureStoreDumpFiles.IndexTestResultsByTestCase:
|
|
553
|
+
case AllureStoreDumpFiles.IndexTestResultsByResolutionIssue:
|
|
556
554
|
case AllureStoreDumpFiles.IndexAttachmentsByFixture:
|
|
557
555
|
case AllureStoreDumpFiles.IndexFixturesByTestResult:
|
|
558
556
|
case AllureStoreDumpFiles.QualityGateResults:
|
|
@@ -580,9 +578,12 @@ export class AllureReport {
|
|
|
580
578
|
indexAttachmentByTestResult: JSON.parse(indexAttachmentsEntry.toString("utf8")),
|
|
581
579
|
indexTestResultByHistoryId: JSON.parse(indexTestResultsByHistoryId.toString("utf8")),
|
|
582
580
|
indexTestResultByTestCase: JSON.parse(indexTestResultsByTestCaseEntry.toString("utf8")),
|
|
581
|
+
indexTestResultByResolutionIssue: indexTestResultsByResolutionIssueEntry
|
|
582
|
+
? JSON.parse(indexTestResultsByResolutionIssueEntry.toString("utf8"))
|
|
583
|
+
: {},
|
|
583
584
|
indexAttachmentByFixture: JSON.parse(indexAttachmentsByFixtureEntry.toString("utf8")),
|
|
584
585
|
indexFixturesByTestResult: JSON.parse(indexFixturesByTestResultEntry.toString("utf8")),
|
|
585
|
-
|
|
586
|
+
resolutionIssues: resolutionIssuesEntry ? JSON.parse(resolutionIssuesEntry.toString("utf8")) : {},
|
|
586
587
|
qualityGateResults: JSON.parse(qualityGateResultsEntry.toString("utf8")),
|
|
587
588
|
testResultIdsIngestOrder: testResultIngestOrderEntry
|
|
588
589
|
? JSON.parse(testResultIngestOrderEntry.toString("utf8"))
|
|
@@ -892,7 +893,7 @@ export class AllureReport {
|
|
|
892
893
|
}
|
|
893
894
|
}
|
|
894
895
|
});
|
|
895
|
-
const { name, readers = [allure1, allure2, cucumberjson, junitXml, attachments], plugins = [],
|
|
896
|
+
const { name, readers = [allure1, allure2, cucumberjson, junitXml, attachments], plugins = [], resolutions, reportFiles, realTime, historyPath, historyLimit, appendHistory, defaultLabels = {}, variables = {}, environment, allowedEnvironments, environments, output, hideLabels, qualityGate, dump, categories, allureService, globalAttachments, } = opts;
|
|
896
897
|
const allureServiceAccessToken = allureService?.accessToken;
|
|
897
898
|
if (allureServiceAccessToken) {
|
|
898
899
|
const allureServiceClientConfig = {
|
|
@@ -917,7 +918,7 @@ export class AllureReport {
|
|
|
917
918
|
__classPrivateFieldSet(this, _AllureReport_environments, environments ?? {}, "f");
|
|
918
919
|
__classPrivateFieldSet(this, _AllureReport_globalAttachments, globalAttachments, "f");
|
|
919
920
|
__classPrivateFieldSet(this, _AllureReport_appendHistory, appendHistory ?? true, "f");
|
|
920
|
-
__classPrivateFieldSet(this, _AllureReport_knownIssuesPath, knownIssuesPath, "f");
|
|
921
|
+
__classPrivateFieldSet(this, _AllureReport_knownIssuesPath, resolutions?.knownIssuesPath, "f");
|
|
921
922
|
if (qualityGate) {
|
|
922
923
|
__classPrivateFieldSet(this, _AllureReport_qualityGate, new QualityGate(qualityGate), "f");
|
|
923
924
|
}
|
|
@@ -941,8 +942,7 @@ export class AllureReport {
|
|
|
941
942
|
reportVariables: variables,
|
|
942
943
|
environmentsConfig: environments,
|
|
943
944
|
history: __classPrivateFieldGet(this, _AllureReport_history, "f"),
|
|
944
|
-
|
|
945
|
-
knownIssuesConfig: knownIssues,
|
|
945
|
+
resolutionsConfig: resolutions,
|
|
946
946
|
defaultLabels,
|
|
947
947
|
environment,
|
|
948
948
|
allowedEnvironments,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ResolutionRule, ResolutionsConfig, TestResult } from "@allurereport/core-api";
|
|
2
|
+
import type { AllureStore } from "@allurereport/plugin-api";
|
|
3
|
+
export declare const DEFAULT_KNOWN_ISSUES_PATH = "known-issues.json";
|
|
4
|
+
export declare const validateResolutionsConfig: (config?: ResolutionsConfig) => void;
|
|
5
|
+
export declare const getResolutionByRules: (testResult: TestResult, config?: ResolutionsConfig) => ResolutionRule | undefined;
|
|
6
|
+
export declare const isIgnoredFailure: (testResult: TestResult) => boolean;
|
|
7
|
+
export declare const resolveExactIssuesFilePath: (pathOrDir: string | undefined, label: string) => Promise<string | undefined>;
|
|
8
|
+
export declare const writeKnownIssues: (store: AllureStore, knownIssuesPath?: string) => Promise<void>;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { mkdir, stat, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, extname, resolve } from "node:path";
|
|
3
|
+
import { isFileNotFoundError } from "./utils/misc.js";
|
|
4
|
+
export const DEFAULT_KNOWN_ISSUES_PATH = "known-issues.json";
|
|
5
|
+
const nonEmpty = (value) => typeof value === "string" && value.trim().length > 0;
|
|
6
|
+
const validateStringList = (value, path, errors) => {
|
|
7
|
+
if (value === undefined) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (!Array.isArray(value) || value.length === 0 || value.some((entry) => !nonEmpty(entry))) {
|
|
11
|
+
errors.push(`${path} must be a non-empty array of non-empty strings`);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const placeholderCount = (value) => (typeof value === "string" ? (value.match(/%s/g)?.length ?? 0) : 0);
|
|
15
|
+
const validateLinkTemplate = (type, template, errors) => {
|
|
16
|
+
if (!nonEmpty(type)) {
|
|
17
|
+
errors.push("resolutions.links keys must be non-empty strings");
|
|
18
|
+
}
|
|
19
|
+
if (!nonEmpty(template?.urlTemplate) || placeholderCount(template.urlTemplate) !== 1) {
|
|
20
|
+
errors.push(`resolutions.links.${type}.urlTemplate must contain exactly one %s`);
|
|
21
|
+
}
|
|
22
|
+
if (template?.nameTemplate === undefined) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (!nonEmpty(template.nameTemplate) || placeholderCount(template.nameTemplate) !== 1) {
|
|
26
|
+
errors.push(`resolutions.links.${type}.nameTemplate must contain exactly one %s`);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const validateMessageRegexp = (value, path, errors) => {
|
|
30
|
+
if (value === undefined) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
new RegExp(value);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
errors.push(`${path}.messageRegexp must be a valid regular expression`);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const validateMatcher = (matcher, path, errors) => {
|
|
41
|
+
validateStringList(matcher.testCaseId, `${path}.testCaseId`, errors);
|
|
42
|
+
validateStringList(matcher.retryHash, `${path}.retryHash`, errors);
|
|
43
|
+
validateStringList(matcher.environment, `${path}.environment`, errors);
|
|
44
|
+
if (![matcher.messageRegexp, matcher.testCaseId, matcher.retryHash, matcher.environment].some((value) => value !== undefined)) {
|
|
45
|
+
errors.push(`${path} must contain at least one matcher`);
|
|
46
|
+
}
|
|
47
|
+
validateMessageRegexp(matcher.messageRegexp, path, errors);
|
|
48
|
+
};
|
|
49
|
+
const validateIssueUrl = (rule, template, errors) => {
|
|
50
|
+
if (!nonEmpty(template.urlTemplate) || placeholderCount(template.urlTemplate) !== 1) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
let url;
|
|
54
|
+
try {
|
|
55
|
+
url = new URL(template.urlTemplate.replace("%s", encodeURIComponent(rule.issue.id)));
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
errors.push(`resolutions.links.${rule.issue.type}.urlTemplate must resolve to an absolute URL`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
62
|
+
errors.push(`resolutions.links.${rule.issue.type}.urlTemplate must resolve to an HTTP(S) URL`);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const validateIssueRule = (rule, path, config, issueIds, errors) => {
|
|
66
|
+
if (!nonEmpty(rule.issue?.id) || !nonEmpty(rule.issue?.type)) {
|
|
67
|
+
errors.push(`${path}.issue.id and ${path}.issue.type must be non-empty strings`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (issueIds.has(rule.issue.id)) {
|
|
71
|
+
errors.push(`${path}.issue.id must be unique`);
|
|
72
|
+
}
|
|
73
|
+
issueIds.add(rule.issue.id);
|
|
74
|
+
const template = config.links?.[rule.issue.type];
|
|
75
|
+
if (!template) {
|
|
76
|
+
errors.push(`${path}.issue.type must reference resolutions.links`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
validateIssueUrl(rule, template, errors);
|
|
80
|
+
};
|
|
81
|
+
const validateIgnoredRule = (rule, path, errors) => {
|
|
82
|
+
if (!nonEmpty(rule.comment)) {
|
|
83
|
+
errors.push(`${path}.comment must be a non-empty string`);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
export const validateResolutionsConfig = (config) => {
|
|
87
|
+
if (!config) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const errors = [];
|
|
91
|
+
if (!Array.isArray(config.rules)) {
|
|
92
|
+
throw new Error("The provided resolutions config is invalid: resolutions.rules must be an array");
|
|
93
|
+
}
|
|
94
|
+
for (const [type, template] of Object.entries(config.links ?? {})) {
|
|
95
|
+
validateLinkTemplate(type, template, errors);
|
|
96
|
+
}
|
|
97
|
+
const issueIds = new Set();
|
|
98
|
+
config.rules.forEach((rule, index) => {
|
|
99
|
+
const path = `resolutions.rules[${index}]`;
|
|
100
|
+
const matcher = rule;
|
|
101
|
+
validateMatcher(matcher, path, errors);
|
|
102
|
+
if (matcher.resolution === "issue") {
|
|
103
|
+
validateIssueRule(matcher, path, config, issueIds, errors);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (matcher.resolution === "muted" || matcher.resolution === "accepted") {
|
|
107
|
+
validateIgnoredRule(matcher, path, errors);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
errors.push(`${path}.resolution must be issue, muted, or accepted`);
|
|
111
|
+
});
|
|
112
|
+
if (errors.length > 0) {
|
|
113
|
+
throw new Error(`The provided resolutions config is invalid: ${errors.join("; ")}`);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const matches = (rule, testResult) => {
|
|
117
|
+
const { id, allureId, externalId } = testResult.testCase ?? {};
|
|
118
|
+
const testCaseIds = [id, allureId, externalId].filter((value) => typeof value === "string");
|
|
119
|
+
return ((!rule.messageRegexp || new RegExp(rule.messageRegexp).test(testResult.error?.message ?? "")) &&
|
|
120
|
+
(!rule.testCaseId || rule.testCaseId.some((id) => testCaseIds.includes(id))) &&
|
|
121
|
+
(!rule.retryHash || (!!testResult.retryHash && rule.retryHash.includes(testResult.retryHash))) &&
|
|
122
|
+
(!rule.environment || (!!testResult.environment && rule.environment.includes(testResult.environment))));
|
|
123
|
+
};
|
|
124
|
+
export const getResolutionByRules = (testResult, config) => {
|
|
125
|
+
if ((testResult.status !== "failed" && testResult.status !== "broken") || !config?.rules.length) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
for (const resolution of ["issue", "muted", "accepted"]) {
|
|
129
|
+
const rule = config.rules.find((candidate) => candidate.resolution === resolution && matches(candidate, testResult));
|
|
130
|
+
if (rule) {
|
|
131
|
+
return rule;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return undefined;
|
|
135
|
+
};
|
|
136
|
+
export const isIgnoredFailure = (testResult) => testResult.resolution === "muted" || testResult.resolution === "accepted";
|
|
137
|
+
export const resolveExactIssuesFilePath = async (pathOrDir, label) => {
|
|
138
|
+
if (!pathOrDir)
|
|
139
|
+
return undefined;
|
|
140
|
+
const path = resolve(pathOrDir);
|
|
141
|
+
if (extname(path).toLowerCase() !== ".json") {
|
|
142
|
+
throw new Error(`Invalid ${label} path ${JSON.stringify(pathOrDir)}: expected exact .json file path`);
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
if ((await stat(path)).isDirectory()) {
|
|
146
|
+
throw new Error(`Invalid ${label} path ${JSON.stringify(pathOrDir)}: expected file, got directory`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
if (!isFileNotFoundError(e))
|
|
151
|
+
throw e;
|
|
152
|
+
}
|
|
153
|
+
return path;
|
|
154
|
+
};
|
|
155
|
+
export const writeKnownIssues = async (store, knownIssuesPath) => {
|
|
156
|
+
const path = await resolveExactIssuesFilePath(knownIssuesPath, "known issues");
|
|
157
|
+
if (!path)
|
|
158
|
+
return;
|
|
159
|
+
const records = new Map();
|
|
160
|
+
for (const testResult of await store.allTestResults()) {
|
|
161
|
+
if (testResult.resolution !== "issue" || testResult.isRetry || !testResult.retryHash) {
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const issue = await store.resolutionIssueByTestResultId(testResult.id);
|
|
165
|
+
if (!issue || (testResult.status !== "failed" && testResult.status !== "broken")) {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
const record = records.get(issue.id) ?? { ...issue, testResults: {} };
|
|
169
|
+
record.testResults[testResult.retryHash] = {
|
|
170
|
+
name: testResult.name,
|
|
171
|
+
fullName: testResult.fullName,
|
|
172
|
+
environment: testResult.environment,
|
|
173
|
+
status: testResult.status,
|
|
174
|
+
error: testResult.error,
|
|
175
|
+
};
|
|
176
|
+
records.set(issue.id, record);
|
|
177
|
+
}
|
|
178
|
+
const file = { resolutionIssues: [...records.values()].sort((a, b) => a.id.localeCompare(b.id)) };
|
|
179
|
+
await mkdir(dirname(path), { recursive: true });
|
|
180
|
+
await writeFile(path, `${JSON.stringify(file)}\n`, "utf-8");
|
|
181
|
+
};
|
package/dist/store/convert.js
CHANGED
|
@@ -53,7 +53,6 @@ export const testResultRawToState = (stateData, raw, context) => {
|
|
|
53
53
|
expectedResultHtml: raw.expectedResultHtml,
|
|
54
54
|
flaky: raw.flaky ?? false,
|
|
55
55
|
muted: raw.muted ?? false,
|
|
56
|
-
known: raw.known ?? false,
|
|
57
56
|
isRetry: false,
|
|
58
57
|
labels,
|
|
59
58
|
steps: convertSteps(stateData, raw.steps).convertedSteps,
|
package/dist/store/store.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { type AllureCheckResult, type AllureHistory, type AttachmentLink, type DefaultLabelsConfig, type EnvironmentIdentity, type EnvironmentsConfig, type GlobalAttachmentLink, type HistoryDataPoint, type HistoryTestResult, type
|
|
1
|
+
import { type AllureCheckResult, type AllureHistory, type AttachmentLink, type DefaultLabelsConfig, type EnvironmentIdentity, type EnvironmentsConfig, type GlobalAttachmentLink, type HistoryDataPoint, type HistoryTestResult, type ResolutionIssue, type ResolutionsConfig, 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>;
|
|
9
8
|
readonly indexTestResultByTestCase: Map<string, TestResult[]>;
|
|
10
9
|
readonly indexTestResultByEnvironmentId: Map<string, TestResult[]>;
|
|
11
10
|
readonly indexTestResultByHistoryId: Map<string, TestResult[]>;
|
|
@@ -14,8 +13,7 @@ export declare class DefaultAllureStore implements AllureStore, ResultsVisitor {
|
|
|
14
13
|
readonly indexFixturesByTestResult: Map<string, TestFixtureResult[]>;
|
|
15
14
|
constructor(params?: {
|
|
16
15
|
history?: AllureHistory;
|
|
17
|
-
|
|
18
|
-
knownIssuesConfig?: KnownIssuesConfig;
|
|
16
|
+
resolutionsConfig?: ResolutionsConfig;
|
|
19
17
|
realtimeDispatcher?: RealtimeEventsDispatcher;
|
|
20
18
|
realtimeSubscriber?: RealtimeSubscriber;
|
|
21
19
|
defaultLabels?: DefaultLabelsConfig;
|
|
@@ -56,7 +54,9 @@ export declare class DefaultAllureStore implements AllureStore, ResultsVisitor {
|
|
|
56
54
|
allHistoryDataPoints(): Promise<HistoryDataPoint[]>;
|
|
57
55
|
allHistoryDataPointsByEnvironment(environment: string): Promise<HistoryDataPoint[]>;
|
|
58
56
|
allHistoryDataPointsByEnvironmentId(environmentId: string): Promise<HistoryDataPoint[]>;
|
|
59
|
-
|
|
57
|
+
allResolutionIssues(): Promise<ResolutionIssue[]>;
|
|
58
|
+
resolutionIssueByTestResultId(trId: string): Promise<ResolutionIssue | undefined>;
|
|
59
|
+
testResultsByResolutionIssueId(resolutionIssueId: string): Promise<TestResult[]>;
|
|
60
60
|
allNewTestResults(filter?: TestResultFilter, history?: HistoryDataPoint[]): Promise<TestResult[]>;
|
|
61
61
|
testCaseById(tcId: string): Promise<TestCase | undefined>;
|
|
62
62
|
testResultById(trId: string): Promise<TestResult | undefined>;
|
package/dist/store/store.js
CHANGED
|
@@ -9,11 +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_resolutionsConfig, _DefaultAllureStore_resolutionIssues, _DefaultAllureStore_testResultIdsByResolutionIssueId, _DefaultAllureStore_resolutionIssueIdByTestResultId, _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_mergeEnvironmentIdentity, _DefaultAllureStore_environmentIdForLookup, _DefaultAllureStore_addEnvironments, _DefaultAllureStore_environmentIdByName, _DefaultAllureStore_setTestResultEnvironmentId, _DefaultAllureStore_assertAllowedEnvironmentId, _DefaultAllureStore_assertAllowedStoredEnvironment, _DefaultAllureStore_environmentIdByTestResult, _DefaultAllureStore_assignRetryHash, _DefaultAllureStore_classifyResolution, _DefaultAllureStore_associateResolutionIssue, _DefaultAllureStore_removeResolutionIssueAssociation, _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 {
|
|
16
|
+
import { getResolutionByRules, isIgnoredFailure } from "../resolutions.js";
|
|
17
17
|
import { environmentIdentityById, normalizeEnvironmentDescriptorMap, resolveEnvironmentIdentity, resolveStoredEnvironmentIdentity, validateAllowedEnvironmentId, } from "../utils/environment.js";
|
|
18
18
|
import { isFlaky } from "../utils/flaky.js";
|
|
19
19
|
import { getStatusTransition } from "../utils/new.js";
|
|
@@ -64,8 +64,10 @@ export class DefaultAllureStore {
|
|
|
64
64
|
_DefaultAllureStore_testCases.set(this, void 0);
|
|
65
65
|
_DefaultAllureStore_metadata.set(this, void 0);
|
|
66
66
|
_DefaultAllureStore_history.set(this, void 0);
|
|
67
|
-
|
|
68
|
-
this
|
|
67
|
+
_DefaultAllureStore_resolutionsConfig.set(this, void 0);
|
|
68
|
+
_DefaultAllureStore_resolutionIssues.set(this, new Map());
|
|
69
|
+
_DefaultAllureStore_testResultIdsByResolutionIssueId.set(this, new Map());
|
|
70
|
+
_DefaultAllureStore_resolutionIssueIdByTestResultId.set(this, new Map());
|
|
69
71
|
_DefaultAllureStore_fixtures.set(this, void 0);
|
|
70
72
|
_DefaultAllureStore_defaultLabels.set(this, {});
|
|
71
73
|
_DefaultAllureStore_environment.set(this, void 0);
|
|
@@ -92,7 +94,7 @@ export class DefaultAllureStore {
|
|
|
92
94
|
_DefaultAllureStore_qualityGateResults.set(this, []);
|
|
93
95
|
_DefaultAllureStore_historyPoints.set(this, []);
|
|
94
96
|
_DefaultAllureStore_environments.set(this, []);
|
|
95
|
-
const { history,
|
|
97
|
+
const { history, resolutionsConfig, realtimeDispatcher, realtimeSubscriber, defaultLabels = {}, environment, allowedEnvironments, environmentsConfig = {}, reportVariables = {}, } = params ?? {};
|
|
96
98
|
const errors = [];
|
|
97
99
|
const { normalized: normalizedEnvironmentsConfig, identities, errors: configErrors, } = normalizeEnvironmentDescriptorMap(environmentsConfig, "environmentsConfig");
|
|
98
100
|
errors.push(...configErrors);
|
|
@@ -117,8 +119,7 @@ export class DefaultAllureStore {
|
|
|
117
119
|
__classPrivateFieldSet(this, _DefaultAllureStore_metadata, new Map(), "f");
|
|
118
120
|
__classPrivateFieldSet(this, _DefaultAllureStore_fixtures, new Map(), "f");
|
|
119
121
|
__classPrivateFieldSet(this, _DefaultAllureStore_history, history, "f");
|
|
120
|
-
__classPrivateFieldSet(this,
|
|
121
|
-
known.forEach((ktf) => this.known.set(ktf.historyId, ktf));
|
|
122
|
+
__classPrivateFieldSet(this, _DefaultAllureStore_resolutionsConfig, resolutionsConfig, "f");
|
|
122
123
|
__classPrivateFieldSet(this, _DefaultAllureStore_realtimeDispatcher, realtimeDispatcher, "f");
|
|
123
124
|
__classPrivateFieldSet(this, _DefaultAllureStore_realtimeSubscriber, realtimeSubscriber, "f");
|
|
124
125
|
__classPrivateFieldSet(this, _DefaultAllureStore_defaultLabels, defaultLabels, "f");
|
|
@@ -330,7 +331,7 @@ export class DefaultAllureStore {
|
|
|
330
331
|
testResult.transition = getStatusTransition(testResult, trHistory);
|
|
331
332
|
testResult.flaky = isFlaky(testResult, trHistory);
|
|
332
333
|
}
|
|
333
|
-
|
|
334
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_classifyResolution).call(this, testResult);
|
|
334
335
|
__classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").set(testResult.id, testResult);
|
|
335
336
|
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_setTestResultEnvironmentId).call(this, testResult, environmentIdentity.id);
|
|
336
337
|
__classPrivateFieldGet(this, _DefaultAllureStore_retrySubstore, "f").recordIngestOrder(testResult.id);
|
|
@@ -512,8 +513,21 @@ export class DefaultAllureStore {
|
|
|
512
513
|
return result;
|
|
513
514
|
}, []);
|
|
514
515
|
}
|
|
515
|
-
async
|
|
516
|
-
return [...this.
|
|
516
|
+
async allResolutionIssues() {
|
|
517
|
+
return [...__classPrivateFieldGet(this, _DefaultAllureStore_resolutionIssues, "f").values()];
|
|
518
|
+
}
|
|
519
|
+
async resolutionIssueByTestResultId(trId) {
|
|
520
|
+
const issueId = __classPrivateFieldGet(this, _DefaultAllureStore_resolutionIssueIdByTestResultId, "f").get(trId);
|
|
521
|
+
return issueId ? __classPrivateFieldGet(this, _DefaultAllureStore_resolutionIssues, "f").get(issueId) : undefined;
|
|
522
|
+
}
|
|
523
|
+
async testResultsByResolutionIssueId(resolutionIssueId) {
|
|
524
|
+
const testResultIds = __classPrivateFieldGet(this, _DefaultAllureStore_testResultIdsByResolutionIssueId, "f").get(resolutionIssueId);
|
|
525
|
+
if (!testResultIds) {
|
|
526
|
+
return [];
|
|
527
|
+
}
|
|
528
|
+
return [...testResultIds]
|
|
529
|
+
.map((testResultId) => __classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").get(testResultId))
|
|
530
|
+
.filter(Boolean);
|
|
517
531
|
}
|
|
518
532
|
async allNewTestResults(filter, history) {
|
|
519
533
|
if (!__classPrivateFieldGet(this, _DefaultAllureStore_history, "f") && !history) {
|
|
@@ -631,7 +645,7 @@ export class DefaultAllureStore {
|
|
|
631
645
|
}
|
|
632
646
|
async blockingFailedTestResults() {
|
|
633
647
|
const failedTestResults = await this.failedTestResults();
|
|
634
|
-
return failedTestResults.filter((tr) => !tr
|
|
648
|
+
return failedTestResults.filter((tr) => !isIgnoredFailure(tr));
|
|
635
649
|
}
|
|
636
650
|
async unknownFailedTestResults() {
|
|
637
651
|
return this.blockingFailedTestResults();
|
|
@@ -792,9 +806,10 @@ export class DefaultAllureStore {
|
|
|
792
806
|
indexAttachmentByTestResult: {},
|
|
793
807
|
indexTestResultByHistoryId: {},
|
|
794
808
|
indexTestResultByTestCase: {},
|
|
809
|
+
indexTestResultByResolutionIssue: {},
|
|
795
810
|
indexAttachmentByFixture: {},
|
|
796
811
|
indexFixturesByTestResult: {},
|
|
797
|
-
|
|
812
|
+
resolutionIssues: mapToObject(__classPrivateFieldGet(this, _DefaultAllureStore_resolutionIssues, "f")),
|
|
798
813
|
qualityGateResults: __classPrivateFieldGet(this, _DefaultAllureStore_qualityGateResults, "f"),
|
|
799
814
|
testResultIdsIngestOrder: __classPrivateFieldGet(this, _DefaultAllureStore_retrySubstore, "f").ingestOrderIdsForDump(),
|
|
800
815
|
};
|
|
@@ -810,16 +825,16 @@ export class DefaultAllureStore {
|
|
|
810
825
|
this.indexTestResultByTestCase.forEach((trs, tcId) => {
|
|
811
826
|
storeDump.indexTestResultByTestCase[tcId] = trs.map((tr) => tr.id);
|
|
812
827
|
});
|
|
828
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_testResultIdsByResolutionIssueId, "f").forEach((trIds, resolutionIssueId) => {
|
|
829
|
+
storeDump.indexTestResultByResolutionIssue[resolutionIssueId] = [...trIds];
|
|
830
|
+
});
|
|
813
831
|
this.indexFixturesByTestResult.forEach((fixtures, trId) => {
|
|
814
832
|
storeDump.indexFixturesByTestResult[trId] = fixtures.map((f) => f.id);
|
|
815
833
|
});
|
|
816
|
-
this.known.forEach((known, historyId) => {
|
|
817
|
-
storeDump.knownIssues[historyId] = known;
|
|
818
|
-
});
|
|
819
834
|
return storeDump;
|
|
820
835
|
}
|
|
821
836
|
async restoreState(stateDump, attachmentsContents = {}) {
|
|
822
|
-
const { testResults, attachments, testCases, fixtures, reportVariables, environments, globalAttachmentIds = [], globalErrors = [], checkResults, indexAttachmentByTestResult = {}, indexTestResultByHistoryId = {}, indexTestResultByTestCase = {}, indexAttachmentByFixture = {}, indexFixturesByTestResult = {},
|
|
837
|
+
const { testResults, attachments, testCases, fixtures, reportVariables, environments, globalAttachmentIds = [], globalErrors = [], checkResults, indexAttachmentByTestResult = {}, indexTestResultByHistoryId = {}, indexTestResultByTestCase = {}, indexTestResultByResolutionIssue = {}, indexAttachmentByFixture = {}, indexFixturesByTestResult = {}, resolutionIssues = {}, qualityGateResults = [], testResultIdsIngestOrder = [], } = stateDump;
|
|
823
838
|
const storedEnvironmentAliases = environments.flatMap((environmentValue) => {
|
|
824
839
|
if (typeof environmentValue === "string") {
|
|
825
840
|
return [{ id: environmentValue, name: environmentValue }];
|
|
@@ -869,7 +884,7 @@ export class DefaultAllureStore {
|
|
|
869
884
|
envNameToId.set(id, id);
|
|
870
885
|
}
|
|
871
886
|
Object.values(testResults).forEach((testResult) => {
|
|
872
|
-
|
|
887
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_removeResolutionIssueAssociation).call(this, testResult.id);
|
|
873
888
|
__classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").set(testResult.id, testResult);
|
|
874
889
|
const storedEnvKey = typeof testResult.environment === "string" ? testResult.environment : undefined;
|
|
875
890
|
const envId = (storedEnvKey ? envNameToId.get(storedEnvKey) : undefined) ?? __classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_environmentIdByTestResult).call(this, testResult);
|
|
@@ -885,7 +900,18 @@ export class DefaultAllureStore {
|
|
|
885
900
|
updateMapWithRecord(__classPrivateFieldGet(this, _DefaultAllureStore_attachments, "f"), attachments);
|
|
886
901
|
updateMapWithRecord(__classPrivateFieldGet(this, _DefaultAllureStore_testCases, "f"), testCases);
|
|
887
902
|
updateMapWithRecord(__classPrivateFieldGet(this, _DefaultAllureStore_fixtures, "f"), fixtures);
|
|
888
|
-
updateMapWithRecord(this
|
|
903
|
+
updateMapWithRecord(__classPrivateFieldGet(this, _DefaultAllureStore_resolutionIssues, "f"), resolutionIssues);
|
|
904
|
+
Object.entries(indexTestResultByResolutionIssue).forEach(([resolutionIssueId, testResultIds]) => {
|
|
905
|
+
const resolutionIssue = __classPrivateFieldGet(this, _DefaultAllureStore_resolutionIssues, "f").get(resolutionIssueId);
|
|
906
|
+
if (!resolutionIssue) {
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
testResultIds.forEach((testResultId) => {
|
|
910
|
+
if (__classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").has(testResultId)) {
|
|
911
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_associateResolutionIssue).call(this, resolutionIssue, testResultId);
|
|
912
|
+
}
|
|
913
|
+
});
|
|
914
|
+
});
|
|
889
915
|
Object.entries(attachmentsContents).forEach(([id, content]) => {
|
|
890
916
|
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_restoreAttachmentContent).call(this, id, content);
|
|
891
917
|
});
|
|
@@ -975,8 +1001,13 @@ export class DefaultAllureStore {
|
|
|
975
1001
|
existingFixtures.push(...fxs);
|
|
976
1002
|
});
|
|
977
1003
|
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_rebuildRetrySubstore).call(this);
|
|
978
|
-
|
|
979
|
-
|
|
1004
|
+
if (__classPrivateFieldGet(this, _DefaultAllureStore_resolutionsConfig, "f")) {
|
|
1005
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_resolutionIssues, "f").clear();
|
|
1006
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_testResultIdsByResolutionIssueId, "f").clear();
|
|
1007
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_resolutionIssueIdByTestResultId, "f").clear();
|
|
1008
|
+
for (const testResult of __classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").values()) {
|
|
1009
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_classifyResolution).call(this, testResult);
|
|
1010
|
+
}
|
|
980
1011
|
}
|
|
981
1012
|
qualityGateResults.forEach((result, index) => {
|
|
982
1013
|
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_assertAllowedStoredEnvironment).call(this, {
|
|
@@ -989,9 +1020,7 @@ export class DefaultAllureStore {
|
|
|
989
1020
|
});
|
|
990
1021
|
}
|
|
991
1022
|
}
|
|
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(),
|
|
993
|
-
return historyIdCandidates.find((historyId) => indexByHistoryId.has(historyId));
|
|
994
|
-
}, _DefaultAllureStore_mergeEnvironmentIdentity = function _DefaultAllureStore_mergeEnvironmentIdentity(existingEnvironment, incomingEnvironment) {
|
|
1023
|
+
_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_resolutionsConfig = new WeakMap(), _DefaultAllureStore_resolutionIssues = new WeakMap(), _DefaultAllureStore_testResultIdsByResolutionIssueId = new WeakMap(), _DefaultAllureStore_resolutionIssueIdByTestResultId = 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_mergeEnvironmentIdentity = function _DefaultAllureStore_mergeEnvironmentIdentity(existingEnvironment, incomingEnvironment) {
|
|
995
1024
|
const configuredEnvironment = environmentIdentityById(__classPrivateFieldGet(this, _DefaultAllureStore_environmentsConfig, "f"), incomingEnvironment.id);
|
|
996
1025
|
if (configuredEnvironment) {
|
|
997
1026
|
return configuredEnvironment;
|
|
@@ -1093,23 +1122,35 @@ _DefaultAllureStore_testResults = new WeakMap(), _DefaultAllureStore_environment
|
|
|
1093
1122
|
const environmentId = options?.environmentId ?? __classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_environmentIdByTestResult).call(this, testResult);
|
|
1094
1123
|
const parametersHash = options?.parametersHash ?? calculateParametersHash(testResult.parameters);
|
|
1095
1124
|
testResult.retryHash = calculateRetryHash(testResult.testCase?.id, parametersHash, environmentId);
|
|
1096
|
-
},
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1125
|
+
}, _DefaultAllureStore_classifyResolution = function _DefaultAllureStore_classifyResolution(testResult) {
|
|
1126
|
+
const rule = getResolutionByRules(testResult, __classPrivateFieldGet(this, _DefaultAllureStore_resolutionsConfig, "f"));
|
|
1127
|
+
testResult.resolution = rule?.resolution;
|
|
1128
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_removeResolutionIssueAssociation).call(this, testResult.id);
|
|
1129
|
+
if (rule?.resolution !== "issue") {
|
|
1130
|
+
return;
|
|
1101
1131
|
}
|
|
1102
|
-
const
|
|
1103
|
-
|
|
1104
|
-
|
|
1132
|
+
const resolutionIssue = { ...rule.issue, comment: rule.comment };
|
|
1133
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_associateResolutionIssue).call(this, resolutionIssue, testResult.id);
|
|
1134
|
+
}, _DefaultAllureStore_associateResolutionIssue = function _DefaultAllureStore_associateResolutionIssue(resolutionIssue, testResultId) {
|
|
1135
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_removeResolutionIssueAssociation).call(this, testResultId);
|
|
1136
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_resolutionIssues, "f").set(resolutionIssue.id, resolutionIssue);
|
|
1137
|
+
const testResultIds = __classPrivateFieldGet(this, _DefaultAllureStore_testResultIdsByResolutionIssueId, "f").get(resolutionIssue.id) ?? new Set();
|
|
1138
|
+
testResultIds.add(testResultId);
|
|
1139
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_testResultIdsByResolutionIssueId, "f").set(resolutionIssue.id, testResultIds);
|
|
1140
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_resolutionIssueIdByTestResultId, "f").set(testResultId, resolutionIssue.id);
|
|
1141
|
+
}, _DefaultAllureStore_removeResolutionIssueAssociation = function _DefaultAllureStore_removeResolutionIssueAssociation(testResultId) {
|
|
1142
|
+
const resolutionIssueId = __classPrivateFieldGet(this, _DefaultAllureStore_resolutionIssueIdByTestResultId, "f").get(testResultId);
|
|
1143
|
+
if (!resolutionIssueId) {
|
|
1144
|
+
return;
|
|
1105
1145
|
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1146
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_resolutionIssueIdByTestResultId, "f").delete(testResultId);
|
|
1147
|
+
const testResultIds = __classPrivateFieldGet(this, _DefaultAllureStore_testResultIdsByResolutionIssueId, "f").get(resolutionIssueId);
|
|
1148
|
+
testResultIds?.delete(testResultId);
|
|
1149
|
+
if (testResultIds?.size) {
|
|
1150
|
+
return;
|
|
1110
1151
|
}
|
|
1111
|
-
|
|
1112
|
-
|
|
1152
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_testResultIdsByResolutionIssueId, "f").delete(resolutionIssueId);
|
|
1153
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_resolutionIssues, "f").delete(resolutionIssueId);
|
|
1113
1154
|
}, _DefaultAllureStore_rebuildRetrySubstore = function _DefaultAllureStore_rebuildRetrySubstore() {
|
|
1114
1155
|
__classPrivateFieldGet(this, _DefaultAllureStore_retrySubstore, "f").reset();
|
|
1115
1156
|
for (const [, testResult] of __classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f")) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const normalizeResultsDir: (value?: string | string[]) => string[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.16.1",
|
|
4
4
|
"description": "Collection of generic Allure utilities used across the entire project",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure"
|
|
@@ -25,26 +25,26 @@
|
|
|
25
25
|
"lint:fix": "oxlint --import-plugin --fix src test features stories"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@allurereport/ci": "3.
|
|
29
|
-
"@allurereport/cli-commons": "3.
|
|
30
|
-
"@allurereport/core-api": "3.
|
|
31
|
-
"@allurereport/plugin-agent": "3.
|
|
32
|
-
"@allurereport/plugin-allure2": "3.
|
|
33
|
-
"@allurereport/plugin-api": "3.
|
|
34
|
-
"@allurereport/plugin-awesome": "3.
|
|
35
|
-
"@allurereport/plugin-classic": "3.
|
|
36
|
-
"@allurereport/plugin-csv": "3.
|
|
37
|
-
"@allurereport/plugin-dashboard": "3.
|
|
38
|
-
"@allurereport/plugin-jira": "3.
|
|
39
|
-
"@allurereport/plugin-log": "3.
|
|
40
|
-
"@allurereport/plugin-progress": "3.
|
|
41
|
-
"@allurereport/plugin-slack": "3.
|
|
42
|
-
"@allurereport/plugin-testops": "3.
|
|
43
|
-
"@allurereport/plugin-testplan": "3.
|
|
44
|
-
"@allurereport/reader": "3.
|
|
45
|
-
"@allurereport/reader-api": "3.
|
|
46
|
-
"@allurereport/service": "3.
|
|
47
|
-
"@allurereport/summary": "3.
|
|
28
|
+
"@allurereport/ci": "3.16.1",
|
|
29
|
+
"@allurereport/cli-commons": "3.16.1",
|
|
30
|
+
"@allurereport/core-api": "3.16.1",
|
|
31
|
+
"@allurereport/plugin-agent": "3.16.1",
|
|
32
|
+
"@allurereport/plugin-allure2": "3.16.1",
|
|
33
|
+
"@allurereport/plugin-api": "3.16.1",
|
|
34
|
+
"@allurereport/plugin-awesome": "3.16.1",
|
|
35
|
+
"@allurereport/plugin-classic": "3.16.1",
|
|
36
|
+
"@allurereport/plugin-csv": "3.16.1",
|
|
37
|
+
"@allurereport/plugin-dashboard": "3.16.1",
|
|
38
|
+
"@allurereport/plugin-jira": "3.16.1",
|
|
39
|
+
"@allurereport/plugin-log": "3.16.1",
|
|
40
|
+
"@allurereport/plugin-progress": "3.16.1",
|
|
41
|
+
"@allurereport/plugin-slack": "3.16.1",
|
|
42
|
+
"@allurereport/plugin-testops": "3.16.1",
|
|
43
|
+
"@allurereport/plugin-testplan": "3.16.1",
|
|
44
|
+
"@allurereport/reader": "3.16.1",
|
|
45
|
+
"@allurereport/reader-api": "3.16.1",
|
|
46
|
+
"@allurereport/service": "3.16.1",
|
|
47
|
+
"@allurereport/summary": "3.16.1",
|
|
48
48
|
"glob": "^13.0.6",
|
|
49
49
|
"handlebars": "^4.7.9",
|
|
50
50
|
"jiti": "^2.5.1",
|
package/dist/known.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { KnownIssuesConfig, KnownTestFailure, TestResult } from "@allurereport/core-api";
|
|
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>;
|
|
7
|
-
export declare const readKnownIssues: (knownIssuePath: string) => Promise<KnownTestFailure[]>;
|
|
8
|
-
export declare const writeKnownIssues: (store: AllureStore, knownIssuesPath?: string) => Promise<void>;
|
package/dist/known.js
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
2
|
-
import { dirname, extname, resolve } from "node:path";
|
|
3
|
-
import { isFileNotFoundError } from "./utils/misc.js";
|
|
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
|
-
};
|
|
59
|
-
export const readKnownIssues = async (knownIssuePath) => {
|
|
60
|
-
const path = await resolveExactIssuesFilePath(knownIssuePath, "known issues");
|
|
61
|
-
if (!path) {
|
|
62
|
-
return [];
|
|
63
|
-
}
|
|
64
|
-
try {
|
|
65
|
-
const content = await readFile(path, { encoding: "utf-8" });
|
|
66
|
-
return JSON.parse(content);
|
|
67
|
-
}
|
|
68
|
-
catch (e) {
|
|
69
|
-
if (isFileNotFoundError(e)) {
|
|
70
|
-
return [];
|
|
71
|
-
}
|
|
72
|
-
throw e;
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
const writeKnownIssueRecords = async (knownIssues, knownIssuesPath) => {
|
|
76
|
-
const path = await resolveExactIssuesFilePath(knownIssuesPath, "known issues");
|
|
77
|
-
if (!path) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
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);
|
|
86
|
-
};
|