@allurereport/core 3.16.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 +2 -4
- package/dist/config.d.ts +1 -1
- package/dist/config.js +9 -9
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -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 +16 -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/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,14 +8,12 @@ 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;
|
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,8 +4,8 @@ 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";
|
|
@@ -98,8 +98,7 @@ export const validateConfig = (config) => {
|
|
|
98
98
|
"hideLabels",
|
|
99
99
|
"historyPath",
|
|
100
100
|
"historyLimit",
|
|
101
|
-
"
|
|
102
|
-
"knownIssues",
|
|
101
|
+
"resolutions",
|
|
103
102
|
"plugins",
|
|
104
103
|
"defaultLabels",
|
|
105
104
|
"variables",
|
|
@@ -195,6 +194,7 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
195
194
|
if (!validationResult.valid) {
|
|
196
195
|
throw new Error(`The provided Allure config contains unsupported fields: ${validationResult.fields.join(", ")}`);
|
|
197
196
|
}
|
|
197
|
+
validateResolutionsConfig(config.resolutions);
|
|
198
198
|
const { environments, environment, allowedEnvironments } = resolveConfigEnvironments(config);
|
|
199
199
|
const name = override.name ?? config.name ?? "Allure Report";
|
|
200
200
|
const open = override.open ?? config.open ?? false;
|
|
@@ -203,11 +203,13 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
203
203
|
const historyPath = override.historyPath ?? config.historyPath;
|
|
204
204
|
const historyLimit = override.historyLimit ?? config.historyLimit;
|
|
205
205
|
const appendHistory = config.appendHistory ?? true;
|
|
206
|
-
const configuredKnownIssuesPath = override.knownIssuesPath ?? config.knownIssuesPath;
|
|
207
|
-
const knownIssuesPathInput = configuredKnownIssuesPath ?? (
|
|
206
|
+
const configuredKnownIssuesPath = override.resolutions?.knownIssuesPath ?? config.resolutions?.knownIssuesPath;
|
|
207
|
+
const knownIssuesPathInput = configuredKnownIssuesPath ?? (config.resolutions ? DEFAULT_KNOWN_ISSUES_PATH : undefined);
|
|
208
208
|
const knownIssuesPath = await resolveExactIssuesFilePath(knownIssuesPathInput, "known issues");
|
|
209
|
+
const resolutions = config.resolutions || override.resolutions?.knownIssuesPath !== undefined
|
|
210
|
+
? { ...(config.resolutions ?? { rules: [] }), knownIssuesPath }
|
|
211
|
+
: undefined;
|
|
209
212
|
const output = resolve(override.output ?? config.output ?? "./allure-report");
|
|
210
|
-
const known = knownIssuesPath ? await readKnownIssues(knownIssuesPath) : undefined;
|
|
211
213
|
const variables = config.variables ?? {};
|
|
212
214
|
const resultsDir = normalizeResultsDir(config.resultsDir);
|
|
213
215
|
let pluginInstances = [];
|
|
@@ -237,9 +239,7 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
237
239
|
open,
|
|
238
240
|
port,
|
|
239
241
|
hideLabels,
|
|
240
|
-
|
|
241
|
-
known,
|
|
242
|
-
knownIssues: config.knownIssues,
|
|
242
|
+
resolutions,
|
|
243
243
|
environment,
|
|
244
244
|
allowedEnvironments,
|
|
245
245
|
variables,
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export * from "./utils/flaky.js";
|
|
|
7
7
|
export * from "./utils/environment.js";
|
|
8
8
|
export * from "./utils/resultsDir.js";
|
|
9
9
|
export * from "./history.js";
|
|
10
|
-
export * from "./
|
|
10
|
+
export * from "./resolutions.js";
|
|
11
11
|
export { resolveConfig, readConfig, readRawConfig, getPluginInstance } from "./config.js";
|
|
12
12
|
export * from "./report.js";
|
|
13
13
|
export * from "./plugin.js";
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ export * from "./utils/flaky.js";
|
|
|
6
6
|
export * from "./utils/environment.js";
|
|
7
7
|
export * from "./utils/resultsDir.js";
|
|
8
8
|
export * from "./history.js";
|
|
9
|
-
export * from "./
|
|
9
|
+
export * from "./resolutions.js";
|
|
10
10
|
export { resolveConfig, readConfig, readRawConfig, getPluginInstance } from "./config.js";
|
|
11
11
|
export * from "./report.js";
|
|
12
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";
|
|
@@ -283,12 +283,7 @@ export class AllureReport {
|
|
|
283
283
|
}
|
|
284
284
|
};
|
|
285
285
|
this.validate = async (params) => {
|
|
286
|
-
const { trs,
|
|
287
|
-
const currentKnownIssues = await __classPrivateFieldGet(this, _AllureReport_store, "f").allKnownIssues();
|
|
288
|
-
const effectiveKnownIssues = new Map();
|
|
289
|
-
[...knownIssues, ...currentKnownIssues].forEach((issue) => {
|
|
290
|
-
effectiveKnownIssues.set(issue.historyId, issue);
|
|
291
|
-
});
|
|
286
|
+
const { trs, state, environment } = params;
|
|
292
287
|
const qualityGateEnvironment = environment === undefined
|
|
293
288
|
? undefined
|
|
294
289
|
: (environmentIdentityById(__classPrivateFieldGet(this, _AllureReport_environments, "f"), environment)?.name ??
|
|
@@ -296,7 +291,6 @@ export class AllureReport {
|
|
|
296
291
|
environment);
|
|
297
292
|
return __classPrivateFieldGet(this, _AllureReport_qualityGate, "f").validate({
|
|
298
293
|
trs: trs.filter(Boolean),
|
|
299
|
-
knownIssues: [...effectiveKnownIssues.values()],
|
|
300
294
|
state,
|
|
301
295
|
environment: qualityGateEnvironment,
|
|
302
296
|
});
|
|
@@ -393,7 +387,7 @@ export class AllureReport {
|
|
|
393
387
|
const addJsonDumpEntry = async (entryName, value) => {
|
|
394
388
|
await addRequiredDumpEntry(Buffer.from(JSON.stringify(value)), entryName);
|
|
395
389
|
};
|
|
396
|
-
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 = [], }) => [
|
|
397
391
|
[AllureStoreDumpFiles.TestResults, testResults],
|
|
398
392
|
[AllureStoreDumpFiles.TestCases, testCases],
|
|
399
393
|
[AllureStoreDumpFiles.Fixtures, fixtures],
|
|
@@ -401,12 +395,13 @@ export class AllureReport {
|
|
|
401
395
|
[AllureStoreDumpFiles.CheckResults, checkResults],
|
|
402
396
|
[AllureStoreDumpFiles.Environments, environments],
|
|
403
397
|
[AllureStoreDumpFiles.ReportVariables, reportVariables],
|
|
404
|
-
[AllureStoreDumpFiles.
|
|
398
|
+
[AllureStoreDumpFiles.ResolutionIssues, resolutionIssues],
|
|
405
399
|
[AllureStoreDumpFiles.GlobalAttachments, globalAttachmentIds],
|
|
406
400
|
[AllureStoreDumpFiles.GlobalErrors, globalErrors],
|
|
407
401
|
[AllureStoreDumpFiles.IndexAttachmentsByTestResults, indexAttachmentByTestResult],
|
|
408
402
|
[AllureStoreDumpFiles.IndexTestResultsByHistoryId, indexTestResultByHistoryId],
|
|
409
403
|
[AllureStoreDumpFiles.IndexTestResultsByTestCase, indexTestResultByTestCase],
|
|
404
|
+
[AllureStoreDumpFiles.IndexTestResultsByResolutionIssue, indexTestResultByResolutionIssue],
|
|
410
405
|
[AllureStoreDumpFiles.IndexAttachmentsByFixture, indexAttachmentByFixture],
|
|
411
406
|
[AllureStoreDumpFiles.IndexFixturesByTestResult, indexFixturesByTestResult],
|
|
412
407
|
[AllureStoreDumpFiles.QualityGateResults, qualityGateResults],
|
|
@@ -533,9 +528,10 @@ export class AllureReport {
|
|
|
533
528
|
const indexAttachmentsEntry = await requiredEntryData(AllureStoreDumpFiles.IndexAttachmentsByTestResults);
|
|
534
529
|
const indexTestResultsByHistoryId = await requiredEntryData(AllureStoreDumpFiles.IndexTestResultsByHistoryId);
|
|
535
530
|
const indexTestResultsByTestCaseEntry = await requiredEntryData(AllureStoreDumpFiles.IndexTestResultsByTestCase);
|
|
531
|
+
const indexTestResultsByResolutionIssueEntry = await optionalEntryData(AllureStoreDumpFiles.IndexTestResultsByResolutionIssue);
|
|
536
532
|
const indexAttachmentsByFixtureEntry = await requiredEntryData(AllureStoreDumpFiles.IndexAttachmentsByFixture);
|
|
537
533
|
const indexFixturesByTestResultEntry = await requiredEntryData(AllureStoreDumpFiles.IndexFixturesByTestResult);
|
|
538
|
-
const
|
|
534
|
+
const resolutionIssuesEntry = await optionalEntryData(AllureStoreDumpFiles.ResolutionIssues);
|
|
539
535
|
const qualityGateResultsEntry = await requiredEntryData(AllureStoreDumpFiles.QualityGateResults);
|
|
540
536
|
const testResultIngestOrderEntry = await optionalEntryData(AllureStoreDumpFiles.TestResultIngestOrder);
|
|
541
537
|
const attachmentsLinks = JSON.parse(attachmentsEntry.toString("utf8"));
|
|
@@ -548,12 +544,13 @@ export class AllureReport {
|
|
|
548
544
|
case AllureStoreDumpFiles.Fixtures:
|
|
549
545
|
case AllureStoreDumpFiles.Environments:
|
|
550
546
|
case AllureStoreDumpFiles.ReportVariables:
|
|
551
|
-
case AllureStoreDumpFiles.
|
|
547
|
+
case AllureStoreDumpFiles.ResolutionIssues:
|
|
552
548
|
case AllureStoreDumpFiles.GlobalAttachments:
|
|
553
549
|
case AllureStoreDumpFiles.GlobalErrors:
|
|
554
550
|
case AllureStoreDumpFiles.IndexAttachmentsByTestResults:
|
|
555
551
|
case AllureStoreDumpFiles.IndexTestResultsByHistoryId:
|
|
556
552
|
case AllureStoreDumpFiles.IndexTestResultsByTestCase:
|
|
553
|
+
case AllureStoreDumpFiles.IndexTestResultsByResolutionIssue:
|
|
557
554
|
case AllureStoreDumpFiles.IndexAttachmentsByFixture:
|
|
558
555
|
case AllureStoreDumpFiles.IndexFixturesByTestResult:
|
|
559
556
|
case AllureStoreDumpFiles.QualityGateResults:
|
|
@@ -581,9 +578,12 @@ export class AllureReport {
|
|
|
581
578
|
indexAttachmentByTestResult: JSON.parse(indexAttachmentsEntry.toString("utf8")),
|
|
582
579
|
indexTestResultByHistoryId: JSON.parse(indexTestResultsByHistoryId.toString("utf8")),
|
|
583
580
|
indexTestResultByTestCase: JSON.parse(indexTestResultsByTestCaseEntry.toString("utf8")),
|
|
581
|
+
indexTestResultByResolutionIssue: indexTestResultsByResolutionIssueEntry
|
|
582
|
+
? JSON.parse(indexTestResultsByResolutionIssueEntry.toString("utf8"))
|
|
583
|
+
: {},
|
|
584
584
|
indexAttachmentByFixture: JSON.parse(indexAttachmentsByFixtureEntry.toString("utf8")),
|
|
585
585
|
indexFixturesByTestResult: JSON.parse(indexFixturesByTestResultEntry.toString("utf8")),
|
|
586
|
-
|
|
586
|
+
resolutionIssues: resolutionIssuesEntry ? JSON.parse(resolutionIssuesEntry.toString("utf8")) : {},
|
|
587
587
|
qualityGateResults: JSON.parse(qualityGateResultsEntry.toString("utf8")),
|
|
588
588
|
testResultIdsIngestOrder: testResultIngestOrderEntry
|
|
589
589
|
? JSON.parse(testResultIngestOrderEntry.toString("utf8"))
|
|
@@ -893,7 +893,7 @@ export class AllureReport {
|
|
|
893
893
|
}
|
|
894
894
|
}
|
|
895
895
|
});
|
|
896
|
-
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;
|
|
897
897
|
const allureServiceAccessToken = allureService?.accessToken;
|
|
898
898
|
if (allureServiceAccessToken) {
|
|
899
899
|
const allureServiceClientConfig = {
|
|
@@ -918,7 +918,7 @@ export class AllureReport {
|
|
|
918
918
|
__classPrivateFieldSet(this, _AllureReport_environments, environments ?? {}, "f");
|
|
919
919
|
__classPrivateFieldSet(this, _AllureReport_globalAttachments, globalAttachments, "f");
|
|
920
920
|
__classPrivateFieldSet(this, _AllureReport_appendHistory, appendHistory ?? true, "f");
|
|
921
|
-
__classPrivateFieldSet(this, _AllureReport_knownIssuesPath, knownIssuesPath, "f");
|
|
921
|
+
__classPrivateFieldSet(this, _AllureReport_knownIssuesPath, resolutions?.knownIssuesPath, "f");
|
|
922
922
|
if (qualityGate) {
|
|
923
923
|
__classPrivateFieldSet(this, _AllureReport_qualityGate, new QualityGate(qualityGate), "f");
|
|
924
924
|
}
|
|
@@ -942,8 +942,7 @@ export class AllureReport {
|
|
|
942
942
|
reportVariables: variables,
|
|
943
943
|
environmentsConfig: environments,
|
|
944
944
|
history: __classPrivateFieldGet(this, _AllureReport_history, "f"),
|
|
945
|
-
|
|
946
|
-
knownIssuesConfig: knownIssues,
|
|
945
|
+
resolutionsConfig: resolutions,
|
|
947
946
|
defaultLabels,
|
|
948
947
|
environment,
|
|
949
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")) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/core",
|
|
3
|
-
"version": "3.16.
|
|
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.16.
|
|
29
|
-
"@allurereport/cli-commons": "3.16.
|
|
30
|
-
"@allurereport/core-api": "3.16.
|
|
31
|
-
"@allurereport/plugin-agent": "3.16.
|
|
32
|
-
"@allurereport/plugin-allure2": "3.16.
|
|
33
|
-
"@allurereport/plugin-api": "3.16.
|
|
34
|
-
"@allurereport/plugin-awesome": "3.16.
|
|
35
|
-
"@allurereport/plugin-classic": "3.16.
|
|
36
|
-
"@allurereport/plugin-csv": "3.16.
|
|
37
|
-
"@allurereport/plugin-dashboard": "3.16.
|
|
38
|
-
"@allurereport/plugin-jira": "3.16.
|
|
39
|
-
"@allurereport/plugin-log": "3.16.
|
|
40
|
-
"@allurereport/plugin-progress": "3.16.
|
|
41
|
-
"@allurereport/plugin-slack": "3.16.
|
|
42
|
-
"@allurereport/plugin-testops": "3.16.
|
|
43
|
-
"@allurereport/plugin-testplan": "3.16.
|
|
44
|
-
"@allurereport/reader": "3.16.
|
|
45
|
-
"@allurereport/reader-api": "3.16.
|
|
46
|
-
"@allurereport/service": "3.16.
|
|
47
|
-
"@allurereport/summary": "3.16.
|
|
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
|
-
};
|