@allurereport/core 3.20.1 → 3.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.d.ts +1 -0
- package/dist/config.js +7 -1
- package/dist/history.js +27 -8
- package/dist/qualityGate/qualityGate.js +2 -1
- package/dist/report.js +38 -11
- package/dist/resolutions.d.ts +1 -1
- package/dist/resolutions.js +10 -1
- package/dist/store/convert.js +47 -31
- package/dist/store/retrySubstore.js +7 -1
- package/dist/store/store.js +19 -10
- package/dist/utils/crypto.d.ts +1 -1
- package/dist/utils/crypto.js +2 -2
- package/dist/utils/flaky.d.ts +2 -2
- package/dist/utils/flaky.js +4 -37
- package/package.json +34 -27
package/dist/config.d.ts
CHANGED
package/dist/config.js
CHANGED
|
@@ -87,6 +87,7 @@ export const validateConfig = (config) => {
|
|
|
87
87
|
"output",
|
|
88
88
|
"open",
|
|
89
89
|
"port",
|
|
90
|
+
"host",
|
|
90
91
|
"hideLabels",
|
|
91
92
|
"historyPath",
|
|
92
93
|
"historyBaseUrl",
|
|
@@ -189,10 +190,13 @@ const validateFlakyDetectionConfig = (config) => {
|
|
|
189
190
|
if (config === undefined) {
|
|
190
191
|
return;
|
|
191
192
|
}
|
|
192
|
-
const { historyDepth, includePassedTests } = config;
|
|
193
|
+
const { historyDepth, includePassedTests, stabilizationPeriod } = config;
|
|
193
194
|
if (historyDepth !== undefined && (!Number.isInteger(historyDepth) || historyDepth < -1)) {
|
|
194
195
|
throw new Error("flakyDetection.historyDepth must be an integer greater than or equal to -1");
|
|
195
196
|
}
|
|
197
|
+
if (stabilizationPeriod !== undefined && (!Number.isInteger(stabilizationPeriod) || stabilizationPeriod < 1)) {
|
|
198
|
+
throw new Error("flakyDetection.stabilizationPeriod must be a positive integer");
|
|
199
|
+
}
|
|
196
200
|
if (includePassedTests !== undefined && typeof includePassedTests !== "boolean") {
|
|
197
201
|
throw new TypeError("flakyDetection.includePassedTests must be a boolean");
|
|
198
202
|
}
|
|
@@ -208,6 +212,7 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
208
212
|
const name = override.name ?? config.name ?? "Allure Report";
|
|
209
213
|
const open = override.open ?? config.open ?? false;
|
|
210
214
|
const port = override.port ?? config.port ?? undefined;
|
|
215
|
+
const host = override.host ?? config.host ?? undefined;
|
|
211
216
|
const hideLabels = override.hideLabels ?? config.hideLabels;
|
|
212
217
|
const historyPath = override.historyPath ?? config.historyPath;
|
|
213
218
|
const historyBaseUrl = override.historyBaseUrl ?? config.historyBaseUrl;
|
|
@@ -252,6 +257,7 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
252
257
|
output,
|
|
253
258
|
open,
|
|
254
259
|
port,
|
|
260
|
+
host,
|
|
255
261
|
hideLabels,
|
|
256
262
|
resolutions,
|
|
257
263
|
environment,
|
package/dist/history.js
CHANGED
|
@@ -9,7 +9,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
10
10
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
11
|
};
|
|
12
|
-
var _AllureLocalHistory_cachedHistory, _AllureLocalHistory_openFileToReadIfExists, _AllureLocalHistory_ensureFileOpenedToAppend, _AllureLocalHistory_findFirstEntryAddress, _AllureLocalHistory_throwUnexpectedReadError;
|
|
12
|
+
var _AllureLocalHistory_cachedHistory, _AllureLocalHistory_closeStreams, _AllureLocalHistory_openFileToReadIfExists, _AllureLocalHistory_ensureFileOpenedToAppend, _AllureLocalHistory_findFirstEntryAddress, _AllureLocalHistory_throwUnexpectedReadError;
|
|
13
13
|
import { once } from "node:events";
|
|
14
14
|
import { mkdir, open } from "node:fs/promises";
|
|
15
15
|
import path from "node:path";
|
|
@@ -20,13 +20,14 @@ import { isFileNotFoundError } from "./utils/misc.js";
|
|
|
20
20
|
const createHistoryItems = (testResults, remoteUrl) => {
|
|
21
21
|
return testResults
|
|
22
22
|
.filter((tr) => tr.retryHash)
|
|
23
|
-
.map(({ id, name, fullName, environment, retryHash, status, error: { message, trace } = {}, start, stop, duration, labels, }) => {
|
|
23
|
+
.map(({ id, name, fullName, environment, retryHash, status, retries = [], error: { message, trace } = {}, start, stop, duration, labels, }) => {
|
|
24
24
|
return {
|
|
25
25
|
id,
|
|
26
26
|
name,
|
|
27
27
|
fullName,
|
|
28
28
|
environment,
|
|
29
29
|
status,
|
|
30
|
+
retries: retries.map((retry) => retry.status).reverse(),
|
|
30
31
|
message,
|
|
31
32
|
trace,
|
|
32
33
|
start,
|
|
@@ -82,10 +83,25 @@ export const createHistory = (reportUuid, reportName = "Allure Report", testCase
|
|
|
82
83
|
url: remoteUrl,
|
|
83
84
|
};
|
|
84
85
|
};
|
|
86
|
+
const closeStream = async (stream) => {
|
|
87
|
+
if (stream.closed) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
await new Promise((resolve) => {
|
|
91
|
+
stream.once("error", () => { });
|
|
92
|
+
stream.once("close", () => resolve());
|
|
93
|
+
stream.destroy();
|
|
94
|
+
});
|
|
95
|
+
};
|
|
85
96
|
export class AllureLocalHistory {
|
|
86
97
|
constructor(params) {
|
|
87
98
|
this.params = params;
|
|
88
99
|
_AllureLocalHistory_cachedHistory.set(this, []);
|
|
100
|
+
_AllureLocalHistory_closeStreams.set(this, async (streams) => {
|
|
101
|
+
for (const stream of streams) {
|
|
102
|
+
await closeStream(stream);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
89
105
|
_AllureLocalHistory_openFileToReadIfExists.set(this, async (filePath) => {
|
|
90
106
|
try {
|
|
91
107
|
return await open(filePath, "r");
|
|
@@ -175,9 +191,11 @@ export class AllureLocalHistory {
|
|
|
175
191
|
if (historyFile === undefined) {
|
|
176
192
|
return [];
|
|
177
193
|
}
|
|
194
|
+
const openedStreams = [];
|
|
178
195
|
try {
|
|
179
196
|
const start = await __classPrivateFieldGet(this, _AllureLocalHistory_findFirstEntryAddress, "f").call(this, historyFile, this.params.limit);
|
|
180
197
|
const stream = historyFile.createReadStream({ start, encoding: "utf-8", autoClose: false });
|
|
198
|
+
openedStreams.push(stream);
|
|
181
199
|
const historyPoints = [];
|
|
182
200
|
const readlineInterface = readline
|
|
183
201
|
.createInterface({ input: stream, terminal: false, crlfDelay: Infinity })
|
|
@@ -192,6 +210,7 @@ export class AllureLocalHistory {
|
|
|
192
210
|
return __classPrivateFieldGet(this, _AllureLocalHistory_cachedHistory, "f");
|
|
193
211
|
}
|
|
194
212
|
finally {
|
|
213
|
+
await __classPrivateFieldGet(this, _AllureLocalHistory_closeStreams, "f").call(this, openedStreams);
|
|
195
214
|
await historyFile.close();
|
|
196
215
|
}
|
|
197
216
|
}
|
|
@@ -202,6 +221,7 @@ export class AllureLocalHistory {
|
|
|
202
221
|
const { limit } = this.params;
|
|
203
222
|
await mkdir(parentDir, { recursive: true });
|
|
204
223
|
const { file: historyFile, exists: historyExists } = await __classPrivateFieldGet(this, _AllureLocalHistory_ensureFileOpenedToAppend, "f").call(this, fullPath);
|
|
224
|
+
const openedStreams = [];
|
|
205
225
|
let dst;
|
|
206
226
|
try {
|
|
207
227
|
if (limit === 0) {
|
|
@@ -210,9 +230,11 @@ export class AllureLocalHistory {
|
|
|
210
230
|
return;
|
|
211
231
|
}
|
|
212
232
|
dst = historyFile.createWriteStream({ encoding: "utf-8", start: 0, autoClose: false });
|
|
233
|
+
openedStreams.push(dst);
|
|
213
234
|
if (historyExists) {
|
|
214
235
|
const start = await __classPrivateFieldGet(this, _AllureLocalHistory_findFirstEntryAddress, "f").call(this, historyFile, limit ? limit - 1 : undefined);
|
|
215
236
|
const src = historyFile.createReadStream({ start, autoClose: false });
|
|
237
|
+
openedStreams.push(src);
|
|
216
238
|
await pipeline(src, dst, { end: false });
|
|
217
239
|
}
|
|
218
240
|
const sources = [JSON.stringify(normalizedData), Buffer.from([0x0a])];
|
|
@@ -222,11 +244,8 @@ export class AllureLocalHistory {
|
|
|
222
244
|
}
|
|
223
245
|
}
|
|
224
246
|
finally {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
dst?.destroy();
|
|
228
|
-
}
|
|
229
|
-
await closing;
|
|
247
|
+
await __classPrivateFieldGet(this, _AllureLocalHistory_closeStreams, "f").call(this, openedStreams);
|
|
248
|
+
await historyFile.close();
|
|
230
249
|
if (limit !== 0) {
|
|
231
250
|
__classPrivateFieldGet(this, _AllureLocalHistory_cachedHistory, "f").push(normalizedData);
|
|
232
251
|
}
|
|
@@ -236,4 +255,4 @@ export class AllureLocalHistory {
|
|
|
236
255
|
}
|
|
237
256
|
}
|
|
238
257
|
}
|
|
239
|
-
_AllureLocalHistory_cachedHistory = new WeakMap(), _AllureLocalHistory_openFileToReadIfExists = new WeakMap(), _AllureLocalHistory_ensureFileOpenedToAppend = new WeakMap(), _AllureLocalHistory_findFirstEntryAddress = new WeakMap(), _AllureLocalHistory_throwUnexpectedReadError = new WeakMap();
|
|
258
|
+
_AllureLocalHistory_cachedHistory = new WeakMap(), _AllureLocalHistory_closeStreams = new WeakMap(), _AllureLocalHistory_openFileToReadIfExists = new WeakMap(), _AllureLocalHistory_ensureFileOpenedToAppend = new WeakMap(), _AllureLocalHistory_findFirstEntryAddress = new WeakMap(), _AllureLocalHistory_throwUnexpectedReadError = new WeakMap();
|
|
@@ -65,8 +65,9 @@ export class QualityGate {
|
|
|
65
65
|
async validate(payload) {
|
|
66
66
|
const { state, trs, metrics = [], previousHistory = [], environment } = payload;
|
|
67
67
|
const trsToValidateById = new Map();
|
|
68
|
+
const resolutionEvaluatedAt = Date.now();
|
|
68
69
|
for (const tr of trs) {
|
|
69
|
-
if (tr.isRetry || isIgnoredFailure(tr) || state?.isTestResultProcessed(tr.id)) {
|
|
70
|
+
if (tr.isRetry || isIgnoredFailure(tr, resolutionEvaluatedAt) || state?.isTestResultProcessed(tr.id)) {
|
|
70
71
|
continue;
|
|
71
72
|
}
|
|
72
73
|
trsToValidateById.set(tr.id, tr);
|
package/dist/report.js
CHANGED
|
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _AllureReport_instances, _AllureReport_ci, _AllureReport_store, _AllureReport_readers, _AllureReport_plugins, _AllureReport_reportFiles, _AllureReport_realtimeChannel, _AllureReport_realtimeUpdateScheduler, _AllureReport_realTime, _AllureReport_hideLabels, _AllureReport_output, _AllureReport_history, _AllureReport_historyBaseUrl, _AllureReport_appendHistory, _AllureReport_allureServiceClient, _AllureReport_qualityGate, _AllureReport_dump, _AllureReport_categories, _AllureReport_environments, _AllureReport_globalAttachments, _AllureReport_knownIssuesPath, _AllureReport_dumpTempDirs, _AllureReport_cwd, _AllureReport_state, _AllureReport_executionStage, _AllureReport_historyDataPoint, _AllureReport_summaryPath, _AllureReport_testResultsRegistryPath, _AllureReport_summariesByPluginId, _AllureReport_publishedRemoteHrefs, _AllureReport_artifactFilesByPath, _AllureReport_published, _AllureReport_endGeneratePerfSpan, _AllureReport_resolvedReportUrl, _AllureReport_reportUrl, _AllureReport_resolveReportUrl, _AllureReport_createHistoryDataPoint, _AllureReport_ingestSelfPerfMetrics, _AllureReport_prepareReportFiles, _AllureReport_publish, _AllureReport_getCwd, _AllureReport_runRealtimeUpdate, _AllureReport_recordArtifact, _AllureReport_restoreStateDumps, _AllureReport_getReportsToPublish, _AllureReport_cleanupFailedRemoteReport, _AllureReport_logPublishError, _AllureReport_applyPublishLinksToSummaries, _AllureReport_cloneSummariesByPluginId, _AllureReport_writeSummaryFiles, _AllureReport_writeTestResultRegistry, _AllureReport_getRootRemoteReportFiles, _AllureReport_writeQualityGateFiles, _AllureReport_finishArtifactsManifest, _AllureReport_generateRootSummary, _AllureReport_finishGeneratePerfSpan, _AllureReport_finishPerfMetrics, _AllureReport_eachPlugin, _AllureReport_getPluginState;
|
|
12
|
+
var _AllureReport_instances, _AllureReport_ci, _AllureReport_store, _AllureReport_readers, _AllureReport_plugins, _AllureReport_reportFiles, _AllureReport_realtimeChannel, _AllureReport_realtimeUpdateScheduler, _AllureReport_realTime, _AllureReport_hideLabels, _AllureReport_output, _AllureReport_history, _AllureReport_historyBaseUrl, _AllureReport_appendHistory, _AllureReport_allureServiceClient, _AllureReport_qualityGate, _AllureReport_dump, _AllureReport_categories, _AllureReport_environments, _AllureReport_globalAttachments, _AllureReport_knownIssuesPath, _AllureReport_dumpTempDirs, _AllureReport_cwd, _AllureReport_state, _AllureReport_executionStage, _AllureReport_historyDataPoint, _AllureReport_summaryPath, _AllureReport_overviewHref, _AllureReport_testResultsRegistryPath, _AllureReport_summariesByPluginId, _AllureReport_publishedRemoteHrefs, _AllureReport_artifactFilesByPath, _AllureReport_published, _AllureReport_endGeneratePerfSpan, _AllureReport_resolvedReportUrl, _AllureReport_reportUrl, _AllureReport_resolveReportUrl, _AllureReport_createHistoryDataPoint, _AllureReport_ingestSelfPerfMetrics, _AllureReport_prepareReportFiles, _AllureReport_publish, _AllureReport_getCwd, _AllureReport_runRealtimeUpdate, _AllureReport_recordArtifact, _AllureReport_restoreStateDumps, _AllureReport_resolveOverviewHref, _AllureReport_getReportsToPublish, _AllureReport_cleanupFailedRemoteReport, _AllureReport_logPublishError, _AllureReport_applyPublishLinksToSummaries, _AllureReport_cloneSummariesByPluginId, _AllureReport_writeSummaryFiles, _AllureReport_writeTestResultRegistry, _AllureReport_getRootRemoteReportFiles, _AllureReport_writeQualityGateFiles, _AllureReport_finishArtifactsManifest, _AllureReport_generateRootSummary, _AllureReport_finishGeneratePerfSpan, _AllureReport_finishPerfMetrics, _AllureReport_eachPlugin, _AllureReport_getPluginState;
|
|
13
13
|
import console from "node:console";
|
|
14
14
|
import { randomUUID } from "node:crypto";
|
|
15
15
|
import { once } from "node:events";
|
|
@@ -18,11 +18,11 @@ import { lstat, mkdtemp, readdir, rename, rm, writeFile } from "node:fs/promises
|
|
|
18
18
|
import { tmpdir } from "node:os";
|
|
19
19
|
import { basename, dirname, join, resolve } from "node:path";
|
|
20
20
|
import { promisify } from "node:util";
|
|
21
|
-
import { detect } from "@allurereport/ci";
|
|
21
|
+
import { createReportCiContext, detect } from "@allurereport/ci";
|
|
22
22
|
import { createProgressLogger } from "@allurereport/cli-commons";
|
|
23
23
|
import { normalizeCategoriesConfig, parseIntegerConfigValue } from "@allurereport/core-api";
|
|
24
24
|
import { AllureStoreDumpFiles, createTestResultRegistry, } from "@allurereport/plugin-api";
|
|
25
|
-
import { allure1, allure2, attachments, cucumberjson, cucumberMessages, junitXml, readXcResultBundle, } from "@allurereport/reader";
|
|
25
|
+
import { allure1, allure2, attachments, cucumberjson, cucumberMessages, junitXml, openTestReporting, readXcResultBundle, } from "@allurereport/reader";
|
|
26
26
|
import { PathResultFile } from "@allurereport/reader-api";
|
|
27
27
|
import { AllureRemoteHistory, AllureServiceClient, AllureTestOpsClient, KnownError, UnknownError, } from "@allurereport/service";
|
|
28
28
|
import { generateSummary } from "@allurereport/summary";
|
|
@@ -48,6 +48,7 @@ const MAX_READ_CONCURRENCY = 256;
|
|
|
48
48
|
const DEFAULT_UPLOAD_CONCURRENCY = 10;
|
|
49
49
|
const TEST_RESULTS_REGISTRY_FILENAME = "test-results.json";
|
|
50
50
|
const QUALITY_GATE_RESULTS_FILENAME = "quality-gate.json";
|
|
51
|
+
const AUXILIARY_OUTPUT_DIRECTORIES = new Set(["export"]);
|
|
51
52
|
const ROOT_INTEGRATION_FILENAMES = new Set([
|
|
52
53
|
TEST_RESULTS_REGISTRY_FILENAME,
|
|
53
54
|
QUALITY_GATE_RESULTS_FILENAME,
|
|
@@ -66,11 +67,15 @@ const readConcurrency = () => {
|
|
|
66
67
|
return Math.min(MAX_READ_CONCURRENCY, Math.max(1, parsed));
|
|
67
68
|
};
|
|
68
69
|
const clonePluginSummary = (summary) => structuredClone(summary);
|
|
69
|
-
const
|
|
70
|
+
const remoteBranchParams = (ci, branch) => {
|
|
70
71
|
const repo = ci?.repoName;
|
|
71
|
-
const branch = ci?.jobRunBranch;
|
|
72
72
|
return repo && branch ? { repo, branch } : {};
|
|
73
73
|
};
|
|
74
|
+
const remoteHistoryParams = (ci) => {
|
|
75
|
+
const historyBranch = ci?.targetBranch || ci?.jobRunBranch;
|
|
76
|
+
return remoteBranchParams(ci, historyBranch);
|
|
77
|
+
};
|
|
78
|
+
const remoteReportParams = (ci) => remoteBranchParams(ci, ci?.jobRunBranch);
|
|
74
79
|
const errorDetails = (err) => (err instanceof Error ? (err.stack ?? err.message) : String(err));
|
|
75
80
|
const getExecutorReportUrl = (executor) => {
|
|
76
81
|
if (!executor || typeof executor !== "object" || !("reportUrl" in executor)) {
|
|
@@ -126,6 +131,7 @@ export class AllureReport {
|
|
|
126
131
|
_AllureReport_executionStage.set(this, "init");
|
|
127
132
|
_AllureReport_historyDataPoint.set(this, void 0);
|
|
128
133
|
_AllureReport_summaryPath.set(this, void 0);
|
|
134
|
+
_AllureReport_overviewHref.set(this, void 0);
|
|
129
135
|
_AllureReport_testResultsRegistryPath.set(this, void 0);
|
|
130
136
|
_AllureReport_summariesByPluginId.set(this, new Map());
|
|
131
137
|
_AllureReport_publishedRemoteHrefs.set(this, new Set());
|
|
@@ -149,7 +155,10 @@ export class AllureReport {
|
|
|
149
155
|
__classPrivateFieldSet(this, _AllureReport_resolvedReportUrl, executorReportUrl, "f");
|
|
150
156
|
});
|
|
151
157
|
_AllureReport_createHistoryDataPoint.set(this, async (flattenReport) => {
|
|
152
|
-
const allTrs = await __classPrivateFieldGet(this, _AllureReport_store, "f").allTestResults()
|
|
158
|
+
const allTrs = await Promise.all((await __classPrivateFieldGet(this, _AllureReport_store, "f").allTestResults()).map(async (tr) => ({
|
|
159
|
+
...tr,
|
|
160
|
+
retries: await __classPrivateFieldGet(this, _AllureReport_store, "f").retriesByTrId(tr.id),
|
|
161
|
+
})));
|
|
153
162
|
const allTcs = await __classPrivateFieldGet(this, _AllureReport_store, "f").allTestCases();
|
|
154
163
|
const historyUrl = __classPrivateFieldGet(this, _AllureReport_reportUrl, "f") ?? (!flattenReport && __classPrivateFieldGet(this, _AllureReport_historyBaseUrl, "f") ? __classPrivateFieldGet(this, _AllureReport_historyBaseUrl, "f") : __classPrivateFieldGet(this, _AllureReport_resolvedReportUrl, "f"));
|
|
155
164
|
return createHistory(this.reportUuid, this.reportName, allTcs, allTrs, historyUrl ?? "", await __classPrivateFieldGet(this, _AllureReport_store, "f").allMetrics());
|
|
@@ -747,6 +756,19 @@ export class AllureReport {
|
|
|
747
756
|
}
|
|
748
757
|
return restoredCount;
|
|
749
758
|
}));
|
|
759
|
+
_AllureReport_resolveOverviewHref.set(this, async () => {
|
|
760
|
+
if (__classPrivateFieldGet(this, _AllureReport_realTime, "f")) {
|
|
761
|
+
return undefined;
|
|
762
|
+
}
|
|
763
|
+
let summariesCount = 0;
|
|
764
|
+
await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, false, async (plugin, context) => {
|
|
765
|
+
const summary = await plugin.info?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"));
|
|
766
|
+
if (summary) {
|
|
767
|
+
summariesCount += 1;
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
return summariesCount > 1 ? "../index.html" : undefined;
|
|
771
|
+
});
|
|
750
772
|
_AllureReport_getReportsToPublish.set(this, async () => {
|
|
751
773
|
const reports = [];
|
|
752
774
|
for (const { enabled, id, options } of __classPrivateFieldGet(this, _AllureReport_plugins, "f")) {
|
|
@@ -866,6 +888,7 @@ export class AllureReport {
|
|
|
866
888
|
return;
|
|
867
889
|
}
|
|
868
890
|
await __classPrivateFieldGet(this, _AllureReport_resolveReportUrl, "f").call(this);
|
|
891
|
+
__classPrivateFieldSet(this, _AllureReport_overviewHref, await __classPrivateFieldGet(this, _AllureReport_resolveOverviewHref, "f").call(this), "f");
|
|
869
892
|
await measurePerf(PERF_METRIC_NAMES.generatePluginsDone, async () => {
|
|
870
893
|
await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, false, async (plugin, context) => {
|
|
871
894
|
await measurePerf(`${PERF_METRIC_PREFIXES.generatePluginDone}${context.id}`, async () => {
|
|
@@ -875,6 +898,7 @@ export class AllureReport {
|
|
|
875
898
|
});
|
|
876
899
|
__classPrivateFieldGet(this, _AllureReport_finishGeneratePerfSpan, "f").call(this);
|
|
877
900
|
await __classPrivateFieldGet(this, _AllureReport_ingestSelfPerfMetrics, "f").call(this);
|
|
901
|
+
const ciContext = createReportCiContext(__classPrivateFieldGet(this, _AllureReport_ci, "f"));
|
|
878
902
|
await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, false, async (plugin, context) => {
|
|
879
903
|
const summary = await plugin?.info?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"));
|
|
880
904
|
if (!summary) {
|
|
@@ -883,6 +907,7 @@ export class AllureReport {
|
|
|
883
907
|
summary.pluginId = context.id;
|
|
884
908
|
summary.pullRequestHref = __classPrivateFieldGet(this, _AllureReport_ci, "f")?.pullRequestUrl;
|
|
885
909
|
summary.jobHref = __classPrivateFieldGet(this, _AllureReport_ci, "f")?.jobRunUrl;
|
|
910
|
+
Object.assign(summary, ciContext);
|
|
886
911
|
summaries.push({
|
|
887
912
|
...summary,
|
|
888
913
|
href: `${context.id}/`,
|
|
@@ -899,7 +924,8 @@ export class AllureReport {
|
|
|
899
924
|
catch { }
|
|
900
925
|
const outputEntries = await Promise.all(outputDirFiles.map(async (file) => ({ file, stats: await lstat(join(__classPrivateFieldGet(this, _AllureReport_output, "f"), file)) })));
|
|
901
926
|
const outputDirectoryEntries = outputEntries.filter(({ stats }) => stats.isDirectory());
|
|
902
|
-
const
|
|
927
|
+
const reportDirectoryEntries = outputDirectoryEntries.filter(({ file }) => !AUXILIARY_OUTPUT_DIRECTORIES.has(file));
|
|
928
|
+
const shouldFlattenOutput = reportDirectoryEntries.length === 1 && __classPrivateFieldGet(this, _AllureReport_plugins, "f").some(({ id }) => id === reportDirectoryEntries[0].file);
|
|
903
929
|
__classPrivateFieldSet(this, _AllureReport_historyDataPoint, await __classPrivateFieldGet(this, _AllureReport_createHistoryDataPoint, "f").call(this, shouldFlattenOutput), "f");
|
|
904
930
|
await __classPrivateFieldGet(this, _AllureReport_publish, "f").call(this);
|
|
905
931
|
if (__classPrivateFieldGet(this, _AllureReport_knownIssuesPath, "f")) {
|
|
@@ -909,7 +935,7 @@ export class AllureReport {
|
|
|
909
935
|
return;
|
|
910
936
|
}
|
|
911
937
|
if (shouldFlattenOutput) {
|
|
912
|
-
const reportPath = join(__classPrivateFieldGet(this, _AllureReport_output, "f"),
|
|
938
|
+
const reportPath = join(__classPrivateFieldGet(this, _AllureReport_output, "f"), reportDirectoryEntries[0].file);
|
|
913
939
|
const reportContent = await readdir(reportPath);
|
|
914
940
|
for (const entry of reportContent) {
|
|
915
941
|
if (ROOT_INTEGRATION_FILENAMES.has(entry)) {
|
|
@@ -1015,6 +1041,7 @@ export class AllureReport {
|
|
|
1015
1041
|
}
|
|
1016
1042
|
: {}),
|
|
1017
1043
|
reportUrl: this.reportUrl,
|
|
1044
|
+
overviewHref: __classPrivateFieldGet(this, _AllureReport_overviewHref, "f"),
|
|
1018
1045
|
realTime: !!__classPrivateFieldGet(this, _AllureReport_realTime, "f"),
|
|
1019
1046
|
output: __classPrivateFieldGet(this, _AllureReport_output, "f"),
|
|
1020
1047
|
ci: __classPrivateFieldGet(this, _AllureReport_ci, "f"),
|
|
@@ -1035,7 +1062,7 @@ export class AllureReport {
|
|
|
1035
1062
|
}
|
|
1036
1063
|
}
|
|
1037
1064
|
});
|
|
1038
|
-
const { name, readers = [allure1, allure2, cucumberjson, cucumberMessages, junitXml, attachments], plugins = [], resolutions, reportFiles, realTime, historyPath, historyBaseUrl, historyLimit, flakyDetection, appendHistory, defaultLabels = {}, variables = {}, environment, allowedEnvironments, environments, output, hideLabels, qualityGate, performance, dump, categories, allureService, globalAttachments, cwd, } = opts;
|
|
1065
|
+
const { name, readers = [allure1, allure2, cucumberjson, cucumberMessages, openTestReporting, junitXml, attachments], plugins = [], resolutions, reportFiles, realTime, historyPath, historyBaseUrl, historyLimit, flakyDetection, appendHistory, defaultLabels = {}, variables = {}, environment, allowedEnvironments, environments, output, hideLabels, qualityGate, performance, dump, categories, allureService, globalAttachments, cwd, } = opts;
|
|
1039
1066
|
const allureServiceAccessToken = allureService?.accessToken;
|
|
1040
1067
|
if (allureServiceAccessToken) {
|
|
1041
1068
|
const allureServiceClientConfig = {
|
|
@@ -1075,7 +1102,7 @@ export class AllureReport {
|
|
|
1075
1102
|
if (__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f")) {
|
|
1076
1103
|
__classPrivateFieldSet(this, _AllureReport_history, new AllureRemoteHistory({
|
|
1077
1104
|
limit: historyLimit,
|
|
1078
|
-
...
|
|
1105
|
+
...remoteHistoryParams(__classPrivateFieldGet(this, _AllureReport_ci, "f")),
|
|
1079
1106
|
allureServiceClient: __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f"),
|
|
1080
1107
|
}), "f");
|
|
1081
1108
|
}
|
|
@@ -1122,6 +1149,6 @@ export class AllureReport {
|
|
|
1122
1149
|
__classPrivateFieldSet(this, _AllureReport_reportUrl, url, "f");
|
|
1123
1150
|
}
|
|
1124
1151
|
}
|
|
1125
|
-
_AllureReport_ci = new WeakMap(), _AllureReport_store = new WeakMap(), _AllureReport_readers = new WeakMap(), _AllureReport_plugins = new WeakMap(), _AllureReport_reportFiles = new WeakMap(), _AllureReport_realtimeChannel = new WeakMap(), _AllureReport_realtimeUpdateScheduler = new WeakMap(), _AllureReport_realTime = new WeakMap(), _AllureReport_hideLabels = new WeakMap(), _AllureReport_output = new WeakMap(), _AllureReport_history = new WeakMap(), _AllureReport_historyBaseUrl = new WeakMap(), _AllureReport_appendHistory = new WeakMap(), _AllureReport_allureServiceClient = new WeakMap(), _AllureReport_qualityGate = new WeakMap(), _AllureReport_dump = new WeakMap(), _AllureReport_categories = new WeakMap(), _AllureReport_environments = new WeakMap(), _AllureReport_globalAttachments = new WeakMap(), _AllureReport_knownIssuesPath = new WeakMap(), _AllureReport_dumpTempDirs = new WeakMap(), _AllureReport_cwd = new WeakMap(), _AllureReport_state = new WeakMap(), _AllureReport_executionStage = new WeakMap(), _AllureReport_historyDataPoint = new WeakMap(), _AllureReport_summaryPath = new WeakMap(), _AllureReport_testResultsRegistryPath = new WeakMap(), _AllureReport_summariesByPluginId = new WeakMap(), _AllureReport_publishedRemoteHrefs = new WeakMap(), _AllureReport_artifactFilesByPath = new WeakMap(), _AllureReport_published = new WeakMap(), _AllureReport_endGeneratePerfSpan = new WeakMap(), _AllureReport_resolvedReportUrl = new WeakMap(), _AllureReport_reportUrl = new WeakMap(), _AllureReport_resolveReportUrl = new WeakMap(), _AllureReport_createHistoryDataPoint = new WeakMap(), _AllureReport_ingestSelfPerfMetrics = new WeakMap(), _AllureReport_prepareReportFiles = new WeakMap(), _AllureReport_publish = new WeakMap(), _AllureReport_getCwd = new WeakMap(), _AllureReport_runRealtimeUpdate = new WeakMap(), _AllureReport_recordArtifact = new WeakMap(), _AllureReport_restoreStateDumps = new WeakMap(), _AllureReport_getReportsToPublish = new WeakMap(), _AllureReport_cleanupFailedRemoteReport = new WeakMap(), _AllureReport_logPublishError = new WeakMap(), _AllureReport_applyPublishLinksToSummaries = new WeakMap(), _AllureReport_cloneSummariesByPluginId = new WeakMap(), _AllureReport_writeSummaryFiles = new WeakMap(), _AllureReport_writeTestResultRegistry = new WeakMap(), _AllureReport_getRootRemoteReportFiles = new WeakMap(), _AllureReport_writeQualityGateFiles = new WeakMap(), _AllureReport_finishArtifactsManifest = new WeakMap(), _AllureReport_generateRootSummary = new WeakMap(), _AllureReport_finishGeneratePerfSpan = new WeakMap(), _AllureReport_finishPerfMetrics = new WeakMap(), _AllureReport_eachPlugin = new WeakMap(), _AllureReport_instances = new WeakSet(), _AllureReport_getPluginState = function _AllureReport_getPluginState(init, id) {
|
|
1152
|
+
_AllureReport_ci = new WeakMap(), _AllureReport_store = new WeakMap(), _AllureReport_readers = new WeakMap(), _AllureReport_plugins = new WeakMap(), _AllureReport_reportFiles = new WeakMap(), _AllureReport_realtimeChannel = new WeakMap(), _AllureReport_realtimeUpdateScheduler = new WeakMap(), _AllureReport_realTime = new WeakMap(), _AllureReport_hideLabels = new WeakMap(), _AllureReport_output = new WeakMap(), _AllureReport_history = new WeakMap(), _AllureReport_historyBaseUrl = new WeakMap(), _AllureReport_appendHistory = new WeakMap(), _AllureReport_allureServiceClient = new WeakMap(), _AllureReport_qualityGate = new WeakMap(), _AllureReport_dump = new WeakMap(), _AllureReport_categories = new WeakMap(), _AllureReport_environments = new WeakMap(), _AllureReport_globalAttachments = new WeakMap(), _AllureReport_knownIssuesPath = new WeakMap(), _AllureReport_dumpTempDirs = new WeakMap(), _AllureReport_cwd = new WeakMap(), _AllureReport_state = new WeakMap(), _AllureReport_executionStage = new WeakMap(), _AllureReport_historyDataPoint = new WeakMap(), _AllureReport_summaryPath = new WeakMap(), _AllureReport_overviewHref = new WeakMap(), _AllureReport_testResultsRegistryPath = new WeakMap(), _AllureReport_summariesByPluginId = new WeakMap(), _AllureReport_publishedRemoteHrefs = new WeakMap(), _AllureReport_artifactFilesByPath = new WeakMap(), _AllureReport_published = new WeakMap(), _AllureReport_endGeneratePerfSpan = new WeakMap(), _AllureReport_resolvedReportUrl = new WeakMap(), _AllureReport_reportUrl = new WeakMap(), _AllureReport_resolveReportUrl = new WeakMap(), _AllureReport_createHistoryDataPoint = new WeakMap(), _AllureReport_ingestSelfPerfMetrics = new WeakMap(), _AllureReport_prepareReportFiles = new WeakMap(), _AllureReport_publish = new WeakMap(), _AllureReport_getCwd = new WeakMap(), _AllureReport_runRealtimeUpdate = new WeakMap(), _AllureReport_recordArtifact = new WeakMap(), _AllureReport_restoreStateDumps = new WeakMap(), _AllureReport_resolveOverviewHref = new WeakMap(), _AllureReport_getReportsToPublish = new WeakMap(), _AllureReport_cleanupFailedRemoteReport = new WeakMap(), _AllureReport_logPublishError = new WeakMap(), _AllureReport_applyPublishLinksToSummaries = new WeakMap(), _AllureReport_cloneSummariesByPluginId = new WeakMap(), _AllureReport_writeSummaryFiles = new WeakMap(), _AllureReport_writeTestResultRegistry = new WeakMap(), _AllureReport_getRootRemoteReportFiles = new WeakMap(), _AllureReport_writeQualityGateFiles = new WeakMap(), _AllureReport_finishArtifactsManifest = new WeakMap(), _AllureReport_generateRootSummary = new WeakMap(), _AllureReport_finishGeneratePerfSpan = new WeakMap(), _AllureReport_finishPerfMetrics = new WeakMap(), _AllureReport_eachPlugin = new WeakMap(), _AllureReport_instances = new WeakSet(), _AllureReport_getPluginState = function _AllureReport_getPluginState(init, id) {
|
|
1126
1153
|
return init ? new DefaultPluginState({}) : __classPrivateFieldGet(this, _AllureReport_state, "f")?.[id];
|
|
1127
1154
|
};
|
package/dist/resolutions.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export declare const KNOWN_FROM_RESULT_RESOLUTION: {
|
|
|
11
11
|
readonly comment: "Accepted from result (known)";
|
|
12
12
|
};
|
|
13
13
|
export declare const getResolutionByRules: (testResult: TestResult, config?: ResolutionsConfig) => ResolutionRule | undefined;
|
|
14
|
-
export declare const isIgnoredFailure: (testResult: TestResult) => boolean;
|
|
14
|
+
export declare const isIgnoredFailure: (testResult: TestResult, now?: number) => boolean;
|
|
15
15
|
export declare const createResolutionIssue: (rule: IssueResolutionRule, config?: ResolutionsConfig) => ResolutionIssue;
|
|
16
16
|
export declare const resolveExactIssuesFilePath: (pathOrDir: string | undefined, label: string) => Promise<string | undefined>;
|
|
17
17
|
export declare const writeKnownIssues: (store: AllureStore, knownIssuesPath?: string) => Promise<void>;
|
package/dist/resolutions.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mkdir, stat, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname, extname, resolve } from "node:path";
|
|
3
|
+
import { isIgnoredResolution, parseResolutionExpiresAt } from "@allurereport/core-api";
|
|
3
4
|
import { isFileNotFoundError } from "./utils/misc.js";
|
|
4
5
|
export const DEFAULT_KNOWN_ISSUES_PATH = "known-issues.json";
|
|
5
6
|
const nonEmpty = (value) => typeof value === "string" && value.trim().length > 0;
|
|
@@ -82,6 +83,14 @@ const validateIgnoredRule = (rule, path, errors) => {
|
|
|
82
83
|
if (!nonEmpty(rule.comment)) {
|
|
83
84
|
errors.push(`${path}.comment must be a non-empty string`);
|
|
84
85
|
}
|
|
86
|
+
if (rule.resolution === "accepted" && rule.expiresAt !== undefined) {
|
|
87
|
+
errors.push(`${path}.expiresAt is only supported for muted resolutions`);
|
|
88
|
+
}
|
|
89
|
+
if (rule.resolution === "muted" &&
|
|
90
|
+
rule.expiresAt !== undefined &&
|
|
91
|
+
(!nonEmpty(rule.expiresAt) || parseResolutionExpiresAt(rule.expiresAt) === undefined)) {
|
|
92
|
+
errors.push(`${path}.expiresAt must be a JavaScript-compatible ISO 8601 timestamp with an explicit timezone`);
|
|
93
|
+
}
|
|
85
94
|
};
|
|
86
95
|
export const validateResolutionsConfig = (config) => {
|
|
87
96
|
if (!config) {
|
|
@@ -154,7 +163,7 @@ export const getResolutionByRules = (testResult, config) => {
|
|
|
154
163
|
}
|
|
155
164
|
return undefined;
|
|
156
165
|
};
|
|
157
|
-
export const isIgnoredFailure = (testResult
|
|
166
|
+
export const isIgnoredFailure = (testResult, now = Date.now()) => isIgnoredResolution(testResult, now);
|
|
158
167
|
export const createResolutionIssue = (rule, config) => {
|
|
159
168
|
const template = config?.links?.[rule.issue.type];
|
|
160
169
|
const issue = { ...rule.issue, comment: rule.comment };
|
package/dist/store/convert.js
CHANGED
|
@@ -36,7 +36,8 @@ export const testFixtureResultRawToState = (stateData, raw, context) => {
|
|
|
36
36
|
};
|
|
37
37
|
};
|
|
38
38
|
export const testResultRawToState = (stateData, raw, context) => {
|
|
39
|
-
const
|
|
39
|
+
const testCaseHash = calculateTestCaseHash(raw.testId, raw.fullName);
|
|
40
|
+
const legacyTestCaseHash = calculateLegacyTestCaseHash(raw, testCaseHash);
|
|
40
41
|
const allureId = raw.labels
|
|
41
42
|
?.find((label) => (label?.name === "ALLURE_ID" || label?.name === "AS_ID") && label.value?.trim())
|
|
42
43
|
?.value?.trim();
|
|
@@ -45,9 +46,8 @@ export const testResultRawToState = (stateData, raw, context) => {
|
|
|
45
46
|
const threadId = findByLabelName(labels, "thread");
|
|
46
47
|
const name = raw.name || "Unknown test";
|
|
47
48
|
const parameters = convertParameters(raw.parameters);
|
|
48
|
-
const error = convertRawError(raw);
|
|
49
49
|
const errors = convertTestErrors(raw);
|
|
50
|
-
const
|
|
50
|
+
const error = errors?.[0] ?? convertRawError(raw);
|
|
51
51
|
const parametersHash = calculateParametersHash(parameters);
|
|
52
52
|
const testCase = processTestCase({ stateData, raw, allureId, testCaseHash });
|
|
53
53
|
return {
|
|
@@ -60,7 +60,7 @@ export const testResultRawToState = (stateData, raw, context) => {
|
|
|
60
60
|
environmentHash: null,
|
|
61
61
|
retryHash: calculateRetryHash({ testCaseHash, parametersHash }),
|
|
62
62
|
status: raw.status ?? defaultStatus,
|
|
63
|
-
error
|
|
63
|
+
error,
|
|
64
64
|
errors,
|
|
65
65
|
...processTimings(raw),
|
|
66
66
|
description: raw.description,
|
|
@@ -89,18 +89,12 @@ export const testResultRawToState = (stateData, raw, context) => {
|
|
|
89
89
|
titlePath: raw.titlePath ?? [],
|
|
90
90
|
};
|
|
91
91
|
};
|
|
92
|
-
const calculateLegacyTestCaseHash = (raw) => {
|
|
92
|
+
const calculateLegacyTestCaseHash = (raw, testCaseHash) => {
|
|
93
93
|
const maybeAllureId = raw.labels?.find((label) => (label?.name === "ALLURE_ID" || label?.name === "AS_ID") && label.value !== "-1")?.value;
|
|
94
94
|
if (maybeAllureId) {
|
|
95
95
|
return md5(`ALLURE_ID=${maybeAllureId}`);
|
|
96
96
|
}
|
|
97
|
-
|
|
98
|
-
return md5(raw.testId);
|
|
99
|
-
}
|
|
100
|
-
if (raw.fullName) {
|
|
101
|
-
return md5(raw.fullName);
|
|
102
|
-
}
|
|
103
|
-
return undefined;
|
|
97
|
+
return testCaseHash ?? undefined;
|
|
104
98
|
};
|
|
105
99
|
const processTestCase = ({ stateData: { testCases }, raw, allureId, testCaseHash, }) => {
|
|
106
100
|
if (testCaseHash) {
|
|
@@ -201,7 +195,16 @@ const processTimings = ({ start, stop, duration, }) => {
|
|
|
201
195
|
return { start: undefined, stop: undefined, duration };
|
|
202
196
|
};
|
|
203
197
|
const convertLabels = (labels) => {
|
|
204
|
-
|
|
198
|
+
const convertedLabels = [];
|
|
199
|
+
for (const label of labels ?? []) {
|
|
200
|
+
if (!notNull(label)) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
for (const expandedLabel of processTagLabels(convertLabel(label))) {
|
|
204
|
+
convertedLabels.push(normalizeAllureIdLabel(expandedLabel));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return convertedLabels;
|
|
205
208
|
};
|
|
206
209
|
const convertLabel = (label) => {
|
|
207
210
|
return {
|
|
@@ -210,16 +213,19 @@ const convertLabel = (label) => {
|
|
|
210
213
|
};
|
|
211
214
|
};
|
|
212
215
|
const convertSteps = (stateData, steps) => {
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
216
|
+
const convertedSteps = [];
|
|
217
|
+
const messages = new Set();
|
|
218
|
+
for (const step of steps ?? []) {
|
|
219
|
+
if (!notNull(step)) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
const converted = convertStep(stateData, step);
|
|
223
|
+
convertedSteps.push(converted.convertedStep);
|
|
224
|
+
for (const message of converted.messages ?? []) {
|
|
225
|
+
messages.add(message);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return { convertedSteps, messages };
|
|
223
229
|
};
|
|
224
230
|
const convertStep = (stateData, step) => {
|
|
225
231
|
if (step.type === "step") {
|
|
@@ -251,10 +257,15 @@ const convertStep = (stateData, step) => {
|
|
|
251
257
|
},
|
|
252
258
|
};
|
|
253
259
|
};
|
|
254
|
-
const convertParameters = (parameters) =>
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
260
|
+
const convertParameters = (parameters) => {
|
|
261
|
+
const convertedParameters = [];
|
|
262
|
+
for (const parameter of parameters ?? []) {
|
|
263
|
+
if (notNull(parameter) && typeof parameter.name === "string" && parameter.name.length > 0) {
|
|
264
|
+
convertedParameters.push(convertParameter(parameter));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return convertedParameters;
|
|
268
|
+
};
|
|
258
269
|
const convertParameter = (param) => ({
|
|
259
270
|
name: param.name ?? UNKNOWN_PARAMETER_VALUE,
|
|
260
271
|
value: param.value ?? UNKNOWN_PARAMETER_VALUE,
|
|
@@ -262,10 +273,15 @@ const convertParameter = (param) => ({
|
|
|
262
273
|
excluded: param.excluded ?? false,
|
|
263
274
|
masked: param.masked ?? false,
|
|
264
275
|
});
|
|
265
|
-
const convertLinks = (links) =>
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
276
|
+
const convertLinks = (links) => {
|
|
277
|
+
const convertedLinks = [];
|
|
278
|
+
for (const link of links ?? []) {
|
|
279
|
+
if (notNull(link) && link.url) {
|
|
280
|
+
convertedLinks.push(convertLink(link));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return convertedLinks;
|
|
284
|
+
};
|
|
269
285
|
const convertLink = (link) => ({
|
|
270
286
|
name: link.name,
|
|
271
287
|
url: link.url ?? UNKNOWN_PARAMETER_VALUE,
|
|
@@ -41,7 +41,13 @@ export class RetrySubstore {
|
|
|
41
41
|
__classPrivateFieldGet(this, _RetrySubstore_testResultsByRetryHash, "f").set(testResult.retryHash, [testResult]);
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
|
-
results.
|
|
44
|
+
const existingIndex = results.findIndex((attempt) => attempt.id === testResult.id);
|
|
45
|
+
if (existingIndex !== -1) {
|
|
46
|
+
results.splice(existingIndex, 1, testResult);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
results.push(testResult);
|
|
50
|
+
}
|
|
45
51
|
results.sort((first, second) => __classPrivateFieldGet(this, _RetrySubstore_instances, "m", _RetrySubstore_compareResults).call(this, first, second));
|
|
46
52
|
results.forEach((attempt, index) => {
|
|
47
53
|
attempt.isRetry = index !== 0;
|
package/dist/store/store.js
CHANGED
|
@@ -11,7 +11,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
11
11
|
};
|
|
12
12
|
var _DefaultAllureStore_instances, _DefaultAllureStore_testResults, _DefaultAllureStore_attachments, _DefaultAllureStore_attachmentContents, _DefaultAllureStore_testCases, _DefaultAllureStore_metadata, _DefaultAllureStore_history, _DefaultAllureStore_detectFlaky, _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_globalAttachmentIds, _DefaultAllureStore_globalAttachmentIdsByEnv, _DefaultAllureStore_globalErrors, _DefaultAllureStore_globalErrorsByEnv, _DefaultAllureStore_processGlobalAttachmentIds, _DefaultAllureStore_processGlobalAttachmentIdsByEnv, _DefaultAllureStore_processGlobalErrors, _DefaultAllureStore_processGlobalErrorsByEnv, _DefaultAllureStore_globalExitCode, _DefaultAllureStore_checkResultsById, _DefaultAllureStore_qualityGateResults, _DefaultAllureStore_metrics, _DefaultAllureStore_performance, _DefaultAllureStore_historyPoints, _DefaultAllureStore_historyLookup, _DefaultAllureStore_environments, _DefaultAllureStore_mergeEnvironmentIdentity, _DefaultAllureStore_environmentIdForLookup, _DefaultAllureStore_environmentIdByName, _DefaultAllureStore_addEnvironments, _DefaultAllureStore_setTestResultEnvironmentId, _DefaultAllureStore_assertAllowedEnvironmentId, _DefaultAllureStore_assertAllowedStoredEnvironment, _DefaultAllureStore_environmentIdByTestResult, _DefaultAllureStore_assignIdentityHashes, _DefaultAllureStore_classifyResolution, _DefaultAllureStore_associateResolutionIssue, _DefaultAllureStore_removeResolutionIssueAssociation, _DefaultAllureStore_rebuildRetrySubstore, _DefaultAllureStore_rebuildIdentityIndexes, _DefaultAllureStore_rebuildEnvironmentIndexes, _DefaultAllureStore_resolveGlobalEnvironmentIdentity, _DefaultAllureStore_globalAttachmentId, _DefaultAllureStore_processGlobalAttachmentId, _DefaultAllureStore_indexGlobalError, _DefaultAllureStore_addGlobalError, _DefaultAllureStore_indexGlobalAttachment, _DefaultAllureStore_addGlobalAttachment, _DefaultAllureStore_resetProcessGlobals, _DefaultAllureStore_getHistoryLookup, _DefaultAllureStore_historyFor, _DefaultAllureStore_applyHistoryFlags, _DefaultAllureStore_restoreAttachmentContent, _DefaultAllureStore_relinkRestoredAttachmentSteps, _DefaultAllureStore_retriesByTr, _DefaultAllureStore_historyByTr;
|
|
13
13
|
import { extname } from "node:path";
|
|
14
|
-
import { DEFAULT_ENVIRONMENT, DEFAULT_ENVIRONMENT_IDENTITY, calculateEnvironmentHash, calculateParametersHash, calculateRetryHash, calculateTestCaseHash, compareBy, createDictionary, fallbackTestCaseIdLabelName, getWorstStatus, createHistoryTestResultLookup, normalizeHistoryDataPoint, ordinal, reverse, resolveMetricSamples, validateEnvironmentId, validateEnvironmentName, } from "@allurereport/core-api";
|
|
14
|
+
import { DEFAULT_ENVIRONMENT, DEFAULT_ENVIRONMENT_IDENTITY, calculateEnvironmentHash, calculateParametersHash, calculateRetryHash, calculateTestCaseHash, compareBy, createDictionary, fallbackTestCaseIdLabelName, getWorstStatus, createHistoryTestResultLookup, hasRetriesStatusChange, normalizeHistoryDataPoint, ordinal, reverse, resolveMetricSamples, validateEnvironmentId, validateEnvironmentName, } from "@allurereport/core-api";
|
|
15
15
|
import { md5, } from "@allurereport/plugin-api";
|
|
16
16
|
import { createResolutionIssue, getResolutionByRules, isIgnoredFailure } from "../resolutions.js";
|
|
17
17
|
import { environmentIdentityById, normalizeEnvironmentDescriptorMap, resolveEnvironmentIdentity, resolveStoredEnvironmentIdentity, validateAllowedEnvironmentId, } from "../utils/environment.js";
|
|
@@ -22,10 +22,11 @@ import { testFixtureResultRawToState, testResultRawToState } from "./convert.js"
|
|
|
22
22
|
import { RetrySubstore } from "./retrySubstore.js";
|
|
23
23
|
const index = (indexMap, key, ...items) => {
|
|
24
24
|
if (key) {
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
let current = indexMap.get(key);
|
|
26
|
+
if (!current) {
|
|
27
|
+
current = [];
|
|
28
|
+
indexMap.set(key, current);
|
|
27
29
|
}
|
|
28
|
-
const current = indexMap.get(key);
|
|
29
30
|
current.push(...items);
|
|
30
31
|
}
|
|
31
32
|
};
|
|
@@ -722,7 +723,8 @@ export class DefaultAllureStore {
|
|
|
722
723
|
}
|
|
723
724
|
async blockingFailedTestResults() {
|
|
724
725
|
const failedTestResults = await this.failedTestResults();
|
|
725
|
-
|
|
726
|
+
const resolutionEvaluatedAt = Date.now();
|
|
727
|
+
return failedTestResults.filter((tr) => !isIgnoredFailure(tr, resolutionEvaluatedAt));
|
|
726
728
|
}
|
|
727
729
|
async unknownFailedTestResults() {
|
|
728
730
|
return this.blockingFailedTestResults();
|
|
@@ -776,6 +778,9 @@ export class DefaultAllureStore {
|
|
|
776
778
|
if (retries.length > 0) {
|
|
777
779
|
statistic.retries = (statistic.retries ?? 0) + 1;
|
|
778
780
|
}
|
|
781
|
+
if (hasRetriesStatusChange(tr, retries)) {
|
|
782
|
+
statistic.retriesStatusChange = (statistic.retriesStatusChange ?? 0) + 1;
|
|
783
|
+
}
|
|
779
784
|
if (tr.flaky) {
|
|
780
785
|
statistic.flaky = (statistic.flaky ?? 0) + 1;
|
|
781
786
|
}
|
|
@@ -939,6 +944,7 @@ export class DefaultAllureStore {
|
|
|
939
944
|
for (const testResult of __classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").values()) {
|
|
940
945
|
delete testResult.resolution;
|
|
941
946
|
delete testResult.resolutionComment;
|
|
947
|
+
delete testResult.resolutionExpiresAt;
|
|
942
948
|
}
|
|
943
949
|
const normalizedEnvironments = environments
|
|
944
950
|
.map((environmentValue) => {
|
|
@@ -989,6 +995,7 @@ export class DefaultAllureStore {
|
|
|
989
995
|
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_removeResolutionIssueAssociation).call(this, testResult.id);
|
|
990
996
|
delete testResult.resolution;
|
|
991
997
|
delete testResult.resolutionComment;
|
|
998
|
+
delete testResult.resolutionExpiresAt;
|
|
992
999
|
__classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").set(testResult.id, testResult);
|
|
993
1000
|
const envId = __classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_environmentIdByTestResult).call(this, testResult);
|
|
994
1001
|
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_assertAllowedEnvironmentId).call(this, envId, `restored testResults[${JSON.stringify(testResult.id)}]`);
|
|
@@ -1198,6 +1205,10 @@ _DefaultAllureStore_testResults = new WeakMap(), _DefaultAllureStore_attachments
|
|
|
1198
1205
|
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_removeResolutionIssueAssociation).call(this, testResult.id);
|
|
1199
1206
|
testResult.resolution = rule.resolution;
|
|
1200
1207
|
testResult.resolutionComment = rule.comment;
|
|
1208
|
+
delete testResult.resolutionExpiresAt;
|
|
1209
|
+
if (rule.resolution === "muted" && rule.expiresAt !== undefined) {
|
|
1210
|
+
testResult.resolutionExpiresAt = rule.expiresAt;
|
|
1211
|
+
}
|
|
1201
1212
|
if (rule.resolution === "issue") {
|
|
1202
1213
|
__classPrivateFieldGet(this, _DefaultAllureStore_instances, "m", _DefaultAllureStore_associateResolutionIssue).call(this, createResolutionIssue(rule, __classPrivateFieldGet(this, _DefaultAllureStore_resolutionsConfig, "f")), testResult.id);
|
|
1203
1214
|
}
|
|
@@ -1298,13 +1309,11 @@ _DefaultAllureStore_testResults = new WeakMap(), _DefaultAllureStore_attachments
|
|
|
1298
1309
|
}, _DefaultAllureStore_getHistoryLookup = function _DefaultAllureStore_getHistoryLookup() {
|
|
1299
1310
|
return (__classPrivateFieldSet(this, _DefaultAllureStore_historyLookup, __classPrivateFieldGet(this, _DefaultAllureStore_historyLookup, "f") ?? createHistoryTestResultLookup(__classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").values()), "f"));
|
|
1300
1311
|
}, _DefaultAllureStore_historyFor = function _DefaultAllureStore_historyFor(result, lookup) {
|
|
1301
|
-
return __classPrivateFieldGet(this, _DefaultAllureStore_historyPoints, "f").
|
|
1302
|
-
const historicalResult = lookup(point, result);
|
|
1303
|
-
return historicalResult ? [historicalResult] : [];
|
|
1304
|
-
});
|
|
1312
|
+
return __classPrivateFieldGet(this, _DefaultAllureStore_historyPoints, "f").map((point) => lookup(point, result));
|
|
1305
1313
|
}, _DefaultAllureStore_applyHistoryFlags = function _DefaultAllureStore_applyHistoryFlags(result, history) {
|
|
1306
1314
|
result.flaky = result.sourceMetadata?.reportedFlaky === true || __classPrivateFieldGet(this, _DefaultAllureStore_detectFlaky, "f").call(this, result, history);
|
|
1307
|
-
|
|
1315
|
+
const resolvedHistory = history.filter((entry) => entry !== undefined);
|
|
1316
|
+
result.transition = getStatusTransition(result, resolvedHistory);
|
|
1308
1317
|
}, _DefaultAllureStore_restoreAttachmentContent = function _DefaultAllureStore_restoreAttachmentContent(id, content) {
|
|
1309
1318
|
const attachment = __classPrivateFieldGet(this, _DefaultAllureStore_attachments, "f").get(id);
|
|
1310
1319
|
__classPrivateFieldGet(this, _DefaultAllureStore_attachmentContents, "f").set(id, content);
|
package/dist/utils/crypto.d.ts
CHANGED
package/dist/utils/crypto.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { randomBytes
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
export { md5 } from "@allurereport/plugin-api";
|
|
2
3
|
export const shortHash = () => randomBytes(8).toString("hex");
|
|
3
|
-
export const md5 = (data) => createHash("md5").update(data).digest("hex");
|
package/dist/utils/flaky.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
export declare const createFlakyDetector: ({
|
|
1
|
+
import { type HistoryTestResult, type FlakyDetectionConfig, type TestResult } from "@allurereport/core-api";
|
|
2
|
+
export declare const createFlakyDetector: ({ includePassedTests, historyDepth, stabilizationPeriod }?: FlakyDetectionConfig) => (tr: TestResult, history: (HistoryTestResult | undefined)[]) => boolean;
|
package/dist/utils/flaky.js
CHANGED
|
@@ -1,40 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
const STABILITY_PRIOR_WEIGHT = 3;
|
|
5
|
-
const FLAKY_SCORE_THRESHOLD = 30;
|
|
6
|
-
const badStatuses = ["failed", "broken"];
|
|
7
|
-
const isFlakyByWeightedTransitions = (tr, history, historyDepth, includePassedTests) => {
|
|
8
|
-
const currentPassed = tr.status === "passed";
|
|
9
|
-
const isEligibleStatus = badStatuses.includes(tr.status) || (includePassedTests && currentPassed);
|
|
10
|
-
if (historyDepth === -1 || !isEligibleStatus) {
|
|
1
|
+
import { getTestFlakiness, } from "@allurereport/core-api";
|
|
2
|
+
export const createFlakyDetector = ({ includePassedTests = false, historyDepth, stabilizationPeriod } = {}) => (tr, history) => {
|
|
3
|
+
if (tr.status !== "failed" && tr.status !== "broken" && !(includePassedTests && tr.status === "passed")) {
|
|
11
4
|
return false;
|
|
12
5
|
}
|
|
13
|
-
|
|
14
|
-
let comparisons = 0;
|
|
15
|
-
let weightedTransitions = 0;
|
|
16
|
-
let totalWeight = 0;
|
|
17
|
-
for (const result of history) {
|
|
18
|
-
if (historyDepth !== 0 && comparisons >= historyDepth) {
|
|
19
|
-
break;
|
|
20
|
-
}
|
|
21
|
-
if (result.id === tr.id ||
|
|
22
|
-
(result.environment ?? DEFAULT_ENVIRONMENT) !== (tr.environment ?? DEFAULT_ENVIRONMENT) ||
|
|
23
|
-
(result.status !== "passed" && !badStatuses.includes(result.status))) {
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
const passed = result.status === "passed";
|
|
27
|
-
const weight = 2 ** (-comparisons / TRANSITION_HALF_LIFE);
|
|
28
|
-
if (passed !== previousPassed) {
|
|
29
|
-
weightedTransitions += weight;
|
|
30
|
-
}
|
|
31
|
-
totalWeight += weight;
|
|
32
|
-
previousPassed = passed;
|
|
33
|
-
comparisons++;
|
|
34
|
-
}
|
|
35
|
-
const score = (100 * weightedTransitions) / (STABILITY_PRIOR_WEIGHT + totalWeight);
|
|
36
|
-
return score >= FLAKY_SCORE_THRESHOLD;
|
|
37
|
-
};
|
|
38
|
-
export const createFlakyDetector = ({ historyDepth = DEFAULT_HISTORY_DEPTH, includePassedTests = false, } = {}) => {
|
|
39
|
-
return (tr, history) => isFlakyByWeightedTransitions(tr, history, historyDepth, includePassedTests);
|
|
6
|
+
return getTestFlakiness(tr, history, { historyDepth, stabilizationPeriod }) === true;
|
|
40
7
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.22.0",
|
|
4
4
|
"description": "Collection of generic Allure utilities used across the entire project",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure"
|
|
@@ -20,33 +20,36 @@
|
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "run clean && tsc --project ./tsconfig.json",
|
|
22
22
|
"clean": "rimraf ./dist",
|
|
23
|
-
"test": "
|
|
24
|
-
"
|
|
25
|
-
"lint
|
|
23
|
+
"test": "rimraf out && vp test run",
|
|
24
|
+
"test:unit": "yarn test",
|
|
25
|
+
"lint": "vp lint --import-plugin src test features stories",
|
|
26
|
+
"lint:fix": "vp lint --import-plugin --fix src test features stories"
|
|
26
27
|
},
|
|
27
28
|
"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-
|
|
41
|
-
"@allurereport/plugin-
|
|
42
|
-
"@allurereport/plugin-
|
|
43
|
-
"@allurereport/plugin-
|
|
44
|
-
"@allurereport/
|
|
45
|
-
"@allurereport/
|
|
46
|
-
"@allurereport/
|
|
47
|
-
"@allurereport/
|
|
29
|
+
"@allurereport/ci": "3.22.0",
|
|
30
|
+
"@allurereport/cli-commons": "3.22.0",
|
|
31
|
+
"@allurereport/core-api": "3.22.0",
|
|
32
|
+
"@allurereport/plugin-agent": "3.22.0",
|
|
33
|
+
"@allurereport/plugin-allure2": "3.22.0",
|
|
34
|
+
"@allurereport/plugin-api": "3.22.0",
|
|
35
|
+
"@allurereport/plugin-awesome": "3.22.0",
|
|
36
|
+
"@allurereport/plugin-classic": "3.22.0",
|
|
37
|
+
"@allurereport/plugin-csv": "3.22.0",
|
|
38
|
+
"@allurereport/plugin-dashboard": "3.22.0",
|
|
39
|
+
"@allurereport/plugin-jira": "3.22.0",
|
|
40
|
+
"@allurereport/plugin-log": "3.22.0",
|
|
41
|
+
"@allurereport/plugin-metrics": "3.22.0",
|
|
42
|
+
"@allurereport/plugin-progress": "3.22.0",
|
|
43
|
+
"@allurereport/plugin-slack": "3.22.0",
|
|
44
|
+
"@allurereport/plugin-testops": "3.22.0",
|
|
45
|
+
"@allurereport/plugin-testplan": "3.22.0",
|
|
46
|
+
"@allurereport/plugin-xray": "3.22.0",
|
|
47
|
+
"@allurereport/reader": "3.22.0",
|
|
48
|
+
"@allurereport/reader-api": "3.22.0",
|
|
49
|
+
"@allurereport/service": "3.22.0",
|
|
50
|
+
"@allurereport/summary": "3.22.0",
|
|
48
51
|
"glob": "^13.0.6",
|
|
49
|
-
"handlebars": "
|
|
52
|
+
"handlebars": "4.7.10",
|
|
50
53
|
"jiti": "^2.5.1",
|
|
51
54
|
"node-stream-zip": "^1.15.0",
|
|
52
55
|
"p-limit": "^7.3.0",
|
|
@@ -55,15 +58,19 @@
|
|
|
55
58
|
"zip-stream": "^7.0.5"
|
|
56
59
|
},
|
|
57
60
|
"devDependencies": {
|
|
61
|
+
"@allurereport/common-config": "3.22.0",
|
|
58
62
|
"@types/node": "^20",
|
|
59
63
|
"@types/zip-stream": "^7.0.0",
|
|
64
|
+
"@vitest/coverage-istanbul": "5.0.4",
|
|
60
65
|
"@vitest/runner": "^2",
|
|
61
|
-
"@vitest/snapshot": "
|
|
66
|
+
"@vitest/snapshot": "5.0.4",
|
|
62
67
|
"allure-js-commons": "^3",
|
|
63
68
|
"allure-vitest": "^3",
|
|
64
69
|
"rimraf": "^6",
|
|
65
70
|
"tslib": "^2.7.0",
|
|
66
71
|
"typescript": "^5",
|
|
67
|
-
"
|
|
72
|
+
"vite": "@voidzero-dev/vite-plus-core@1.2.0",
|
|
73
|
+
"vite-plus": "1.2.0",
|
|
74
|
+
"vitest": "5.0.4"
|
|
68
75
|
}
|
|
69
76
|
}
|