@allurereport/core 3.18.0 → 3.19.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/config.js +15 -0
- package/dist/history.js +7 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/qualityGate/qualityGate.js +1 -1
- package/dist/qualityGate/rules.d.ts +2 -1
- package/dist/qualityGate/rules.js +29 -4
- package/dist/report.js +56 -16
- package/dist/store/convert.d.ts +0 -1
- package/dist/store/convert.js +71 -58
- package/dist/store/retrySubstore.d.ts +1 -3
- package/dist/store/retrySubstore.js +0 -14
- package/dist/store/store.d.ts +4 -2
- package/dist/store/store.js +223 -197
- package/dist/utils/event.d.ts +1 -1
- package/dist/utils/event.js +9 -4
- package/dist/utils/flaky.d.ts +2 -2
- package/dist/utils/flaky.js +36 -8
- package/dist/utils/perf.d.ts +24 -12
- package/dist/utils/perf.js +116 -16
- package/dist/utils/realtimeChannel.d.ts +1 -0
- package/dist/utils/realtimeChannel.js +2 -2
- package/package.json +22 -22
package/dist/store/convert.js
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { findByLabelName, notNull } from "@allurereport/core-api";
|
|
2
|
+
import { UNKNOWN_PARAMETER_VALUE, calculateParametersHash, calculateRetryHash, calculateTestCaseHash, findByLabelName, notNull, } from "@allurereport/core-api";
|
|
3
3
|
import { md5 } from "@allurereport/plugin-api";
|
|
4
4
|
import { extension, lookupContentType } from "@allurereport/reader-api";
|
|
5
5
|
const defaultStatus = "unknown";
|
|
6
|
-
|
|
6
|
+
const convertRawError = (raw) => ({
|
|
7
|
+
message: raw.message,
|
|
8
|
+
trace: raw.trace,
|
|
9
|
+
...(raw.actual && raw.expected ? { expected: raw.expected, actual: raw.actual } : {}),
|
|
10
|
+
});
|
|
11
|
+
const convertTestErrors = (raw) => {
|
|
12
|
+
const errors = raw.errors?.filter(notNull);
|
|
13
|
+
if (errors?.length) {
|
|
14
|
+
return errors.map(convertRawError);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
7
17
|
export const testFixtureResultRawToState = (stateData, raw, context) => {
|
|
8
18
|
const name = raw.name || "Unknown test";
|
|
9
19
|
return {
|
|
@@ -26,24 +36,32 @@ export const testFixtureResultRawToState = (stateData, raw, context) => {
|
|
|
26
36
|
};
|
|
27
37
|
};
|
|
28
38
|
export const testResultRawToState = (stateData, raw, context) => {
|
|
39
|
+
const legacyTestCaseHash = calculateLegacyTestCaseHash(raw);
|
|
40
|
+
const allureId = raw.labels
|
|
41
|
+
?.find((label) => (label?.name === "ALLURE_ID" || label?.name === "AS_ID") && label.value?.trim())
|
|
42
|
+
?.value?.trim();
|
|
29
43
|
const labels = convertLabels(raw.labels);
|
|
30
44
|
const hostId = findByLabelName(labels, "host");
|
|
31
45
|
const threadId = findByLabelName(labels, "thread");
|
|
32
46
|
const name = raw.name || "Unknown test";
|
|
33
|
-
const testCase = processTestCase(stateData, raw);
|
|
34
47
|
const parameters = convertParameters(raw.parameters);
|
|
48
|
+
const error = convertRawError(raw);
|
|
49
|
+
const errors = convertTestErrors(raw);
|
|
50
|
+
const testCaseHash = calculateTestCaseHash(raw.testId, raw.fullName);
|
|
51
|
+
const parametersHash = calculateParametersHash(parameters);
|
|
52
|
+
const testCase = processTestCase({ stateData, raw, allureId, testCaseHash });
|
|
35
53
|
return {
|
|
36
54
|
id: md5(raw.uuid || randomUUID()),
|
|
37
55
|
name,
|
|
38
56
|
testCase,
|
|
39
57
|
fullName: raw.fullName,
|
|
40
|
-
|
|
58
|
+
testCaseHash,
|
|
59
|
+
parametersHash,
|
|
60
|
+
environmentHash: null,
|
|
61
|
+
retryHash: calculateRetryHash({ testCaseHash, parametersHash }),
|
|
41
62
|
status: raw.status ?? defaultStatus,
|
|
42
|
-
error:
|
|
43
|
-
|
|
44
|
-
trace: raw.trace,
|
|
45
|
-
...(raw.actual && raw.expected ? { expected: raw.expected, actual: raw.actual } : {}),
|
|
46
|
-
},
|
|
63
|
+
error: errors?.[0] ?? error,
|
|
64
|
+
errors,
|
|
47
65
|
...processTimings(raw),
|
|
48
66
|
description: raw.description,
|
|
49
67
|
descriptionHtml: raw.descriptionHtml,
|
|
@@ -64,25 +82,43 @@ export const testResultRawToState = (stateData, raw, context) => {
|
|
|
64
82
|
sourceMetadata: {
|
|
65
83
|
readerId: context.readerId,
|
|
66
84
|
metadata: context.metadata ?? {},
|
|
85
|
+
legacyHistoryId: raw.historyId?.length ? raw.historyId : undefined,
|
|
86
|
+
reportedFlaky: raw.flaky ?? false,
|
|
87
|
+
legacyTestCaseHash,
|
|
67
88
|
},
|
|
68
89
|
titlePath: raw.titlePath ?? [],
|
|
69
90
|
};
|
|
70
91
|
};
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
if (
|
|
74
|
-
|
|
92
|
+
const calculateLegacyTestCaseHash = (raw) => {
|
|
93
|
+
const maybeAllureId = raw.labels?.find((label) => (label?.name === "ALLURE_ID" || label?.name === "AS_ID") && label.value !== "-1")?.value;
|
|
94
|
+
if (maybeAllureId) {
|
|
95
|
+
return md5(`ALLURE_ID=${maybeAllureId}`);
|
|
96
|
+
}
|
|
97
|
+
if (raw.testId) {
|
|
98
|
+
return md5(raw.testId);
|
|
99
|
+
}
|
|
100
|
+
if (raw.fullName) {
|
|
101
|
+
return md5(raw.fullName);
|
|
102
|
+
}
|
|
103
|
+
return undefined;
|
|
104
|
+
};
|
|
105
|
+
const processTestCase = ({ stateData: { testCases }, raw, allureId, testCaseHash, }) => {
|
|
106
|
+
if (testCaseHash) {
|
|
107
|
+
const maybeTestCase = testCases.get(testCaseHash);
|
|
75
108
|
if (maybeTestCase) {
|
|
109
|
+
if (!maybeTestCase.allureId && allureId) {
|
|
110
|
+
maybeTestCase.allureId = allureId;
|
|
111
|
+
}
|
|
76
112
|
return maybeTestCase;
|
|
77
113
|
}
|
|
78
114
|
const testCase = {
|
|
79
|
-
id,
|
|
115
|
+
id: testCaseHash,
|
|
80
116
|
allureId,
|
|
81
117
|
externalId: raw.testId,
|
|
82
|
-
name: raw.testCaseName ?? raw.name ??
|
|
118
|
+
name: raw.testCaseName ?? raw.name ?? UNKNOWN_PARAMETER_VALUE,
|
|
83
119
|
fullName: raw.fullName,
|
|
84
120
|
};
|
|
85
|
-
testCases.set(
|
|
121
|
+
testCases.set(testCaseHash, testCase);
|
|
86
122
|
return testCase;
|
|
87
123
|
}
|
|
88
124
|
return undefined;
|
|
@@ -100,7 +136,7 @@ const processAttachmentLink = ({ attachments, visitAttachmentLink }, attach) =>
|
|
|
100
136
|
originalFileName: undefined,
|
|
101
137
|
contentType: attach.contentType,
|
|
102
138
|
ext: "",
|
|
103
|
-
name: attach.name ??
|
|
139
|
+
name: attach.name ?? UNKNOWN_PARAMETER_VALUE,
|
|
104
140
|
missed: true,
|
|
105
141
|
used: true,
|
|
106
142
|
});
|
|
@@ -128,7 +164,7 @@ const processAttachmentLink = ({ attachments, visitAttachmentLink }, attach) =>
|
|
|
128
164
|
id: randomUUID(),
|
|
129
165
|
originalFileName: undefined,
|
|
130
166
|
ext: "",
|
|
131
|
-
name: attach.name ?? attach.originalFileName ??
|
|
167
|
+
name: attach.name ?? attach.originalFileName ?? UNKNOWN_PARAMETER_VALUE,
|
|
132
168
|
contentType: attach.contentType,
|
|
133
169
|
missed: true,
|
|
134
170
|
used: true,
|
|
@@ -165,11 +201,11 @@ const processTimings = ({ start, stop, duration, }) => {
|
|
|
165
201
|
return { start: undefined, stop: undefined, duration };
|
|
166
202
|
};
|
|
167
203
|
const convertLabels = (labels) => {
|
|
168
|
-
return labels?.filter(notNull)?.map(convertLabel)?.flatMap(processTagLabels) ?? [];
|
|
204
|
+
return labels?.filter(notNull)?.map(convertLabel)?.flatMap(processTagLabels).map(normalizeAllureIdLabel) ?? [];
|
|
169
205
|
};
|
|
170
206
|
const convertLabel = (label) => {
|
|
171
207
|
return {
|
|
172
|
-
name: label.name ??
|
|
208
|
+
name: label.name ?? UNKNOWN_PARAMETER_VALUE,
|
|
173
209
|
value: label.value,
|
|
174
210
|
};
|
|
175
211
|
};
|
|
@@ -196,7 +232,7 @@ const convertStep = (stateData, step) => {
|
|
|
196
232
|
return {
|
|
197
233
|
convertedStep: {
|
|
198
234
|
stepId: md5(`${step.name}${step.start}`),
|
|
199
|
-
name: step.name ??
|
|
235
|
+
name: step.name ?? UNKNOWN_PARAMETER_VALUE,
|
|
200
236
|
status: step.status ?? defaultStatus,
|
|
201
237
|
steps: subSteps,
|
|
202
238
|
parameters: convertParameters(step.parameters),
|
|
@@ -217,11 +253,11 @@ const convertStep = (stateData, step) => {
|
|
|
217
253
|
};
|
|
218
254
|
const convertParameters = (parameters) => parameters
|
|
219
255
|
?.filter(notNull)
|
|
220
|
-
?.filter((p) => p.name)
|
|
256
|
+
?.filter((p) => typeof p.name === "string" && p.name.length > 0)
|
|
221
257
|
?.map(convertParameter) ?? [];
|
|
222
258
|
const convertParameter = (param) => ({
|
|
223
|
-
name: param.name ??
|
|
224
|
-
value: param.value ??
|
|
259
|
+
name: param.name ?? UNKNOWN_PARAMETER_VALUE,
|
|
260
|
+
value: param.value ?? UNKNOWN_PARAMETER_VALUE,
|
|
225
261
|
hidden: param.hidden ?? false,
|
|
226
262
|
excluded: param.excluded ?? false,
|
|
227
263
|
masked: param.masked ?? false,
|
|
@@ -232,42 +268,9 @@ const convertLinks = (links) => links
|
|
|
232
268
|
?.map(convertLink) ?? [];
|
|
233
269
|
const convertLink = (link) => ({
|
|
234
270
|
name: link.name,
|
|
235
|
-
url: link.url ??
|
|
271
|
+
url: link.url ?? UNKNOWN_PARAMETER_VALUE,
|
|
236
272
|
type: link.type,
|
|
237
273
|
});
|
|
238
|
-
const calculateTestId = (raw) => {
|
|
239
|
-
const maybeAllureId = raw.labels?.find((label) => (label.name === "ALLURE_ID" || label.name === "AS_ID") && label.value !== "-1")?.value;
|
|
240
|
-
if (maybeAllureId) {
|
|
241
|
-
return [md5(`ALLURE_ID=${maybeAllureId}`), maybeAllureId];
|
|
242
|
-
}
|
|
243
|
-
if (raw.testId) {
|
|
244
|
-
return [md5(raw.testId), undefined];
|
|
245
|
-
}
|
|
246
|
-
if (raw.fullName) {
|
|
247
|
-
return [md5(raw.fullName), undefined];
|
|
248
|
-
}
|
|
249
|
-
return [undefined, undefined];
|
|
250
|
-
};
|
|
251
|
-
const calculateHistoryId = (testCase, parameters) => {
|
|
252
|
-
if (!testCase) {
|
|
253
|
-
return undefined;
|
|
254
|
-
}
|
|
255
|
-
const paramsPart = stringifyParams(parameters);
|
|
256
|
-
return `${testCase.id}.${md5(paramsPart)}`;
|
|
257
|
-
};
|
|
258
|
-
const parametersCompare = (a, b) => {
|
|
259
|
-
return (a.name ?? "").localeCompare(b.name) || a.value.localeCompare(b.value ?? "");
|
|
260
|
-
};
|
|
261
|
-
const stringifyParams = (parameters) => {
|
|
262
|
-
if (!parameters) {
|
|
263
|
-
return "";
|
|
264
|
-
}
|
|
265
|
-
return parameters
|
|
266
|
-
.filter((p) => !p?.excluded)
|
|
267
|
-
.sort(parametersCompare)
|
|
268
|
-
.map((p) => `${p.name}:${p.value}`)
|
|
269
|
-
.join(",");
|
|
270
|
-
};
|
|
271
274
|
const idLabelMatcher = new RegExp("^@?allure\\.id[:=](?<id>.+)$");
|
|
272
275
|
const tagLabelMatcher = new RegExp("^@?allure\\.label\\.(?<name>.+)[:=](?<value>.+)$");
|
|
273
276
|
const processTagLabels = (label) => {
|
|
@@ -286,3 +289,13 @@ const processTagLabels = (label) => {
|
|
|
286
289
|
}
|
|
287
290
|
return label.name ? [{ name: label.name, value: label.value }] : [];
|
|
288
291
|
};
|
|
292
|
+
const normalizeAllureIdLabel = (label) => {
|
|
293
|
+
if (label.name !== "ALLURE_ID" && label.name !== "AS_ID") {
|
|
294
|
+
return label;
|
|
295
|
+
}
|
|
296
|
+
const value = label.value?.trim();
|
|
297
|
+
return {
|
|
298
|
+
name: "ALLURE_ID",
|
|
299
|
+
value: value?.length ? value : undefined,
|
|
300
|
+
};
|
|
301
|
+
};
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare const calculateParametersHash: (parameters?: TestParameter[]) => string;
|
|
3
|
-
export declare const calculateRetryHash: (testCaseId: string | undefined, parametersHash: string, environmentId: string | undefined) => string | undefined;
|
|
1
|
+
import type { TestResult } from "@allurereport/core-api";
|
|
4
2
|
export declare class RetrySubstore {
|
|
5
3
|
#private;
|
|
6
4
|
recordIngestOrder(testResultId: string): void;
|
|
@@ -4,21 +4,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
4
4
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
5
|
};
|
|
6
6
|
var _RetrySubstore_instances, _RetrySubstore_testResultsByRetryHash, _RetrySubstore_testResultIngestIndexById, _RetrySubstore_getIngestIndex, _RetrySubstore_compareResults;
|
|
7
|
-
import { md5 } from "../utils/crypto.js";
|
|
8
7
|
const NO_RETRIES = [];
|
|
9
|
-
const compareByNameThenValue = (first, second) => first.name.localeCompare(second.name) || first.value.localeCompare(second.value);
|
|
10
|
-
const stringifyRetryParameters = (parameters = []) => parameters
|
|
11
|
-
.filter((parameter) => !parameter.excluded)
|
|
12
|
-
.sort(compareByNameThenValue)
|
|
13
|
-
.map((parameter) => `${parameter.name}:${parameter.value}`)
|
|
14
|
-
.join(",");
|
|
15
|
-
export const calculateParametersHash = (parameters = []) => md5(stringifyRetryParameters(parameters));
|
|
16
|
-
export const calculateRetryHash = (testCaseId, parametersHash, environmentId) => {
|
|
17
|
-
if (!testCaseId) {
|
|
18
|
-
return undefined;
|
|
19
|
-
}
|
|
20
|
-
return md5(`${testCaseId}:${parametersHash}:${environmentId ?? "default"}`);
|
|
21
|
-
};
|
|
22
8
|
export class RetrySubstore {
|
|
23
9
|
constructor() {
|
|
24
10
|
_RetrySubstore_instances.add(this);
|
package/dist/store/store.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AllureCheckResult, type AllureHistory, type AllurePerformanceResult, type AttachmentLink, type DefaultLabelsConfig, type EnvironmentIdentity, type EnvironmentsConfig, type GlobalAttachmentLink, type HistoryDataPoint, type HistoryTestResult, type ResolutionIssue, type ResolutionsConfig, type MetricSample, type PerformanceConfig, type ReportVariables, type Statistic, type TestCase, type TestEnvGroup, type TestError, type TestFixtureResult, type TestResult } from "@allurereport/core-api";
|
|
1
|
+
import { type AllureCheckResult, type AllureHistory, type AllurePerformanceResult, type AttachmentLink, type DefaultLabelsConfig, type EnvironmentIdentity, type EnvironmentsConfig, type FlakyDetectionConfig, type GlobalAttachmentLink, type HistoryDataPoint, type HistoryTestResult, type ResolutionIssue, type ResolutionsConfig, type MetricSample, type PerformanceConfig, 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>;
|
|
@@ -7,12 +7,13 @@ export declare class DefaultAllureStore implements AllureStore, ResultsVisitor {
|
|
|
7
7
|
#private;
|
|
8
8
|
readonly indexTestResultByTestCase: Map<string, TestResult[]>;
|
|
9
9
|
readonly indexTestResultByEnvironmentId: Map<string, TestResult[]>;
|
|
10
|
-
readonly
|
|
10
|
+
readonly indexTestResultByRetryHash: Map<string, TestResult[]>;
|
|
11
11
|
readonly indexAttachmentByTestResult: Map<string, AttachmentLink[]>;
|
|
12
12
|
readonly indexAttachmentByFixture: Map<string, AttachmentLink[]>;
|
|
13
13
|
readonly indexFixturesByTestResult: Map<string, TestFixtureResult[]>;
|
|
14
14
|
constructor(params?: {
|
|
15
15
|
history?: AllureHistory;
|
|
16
|
+
flakyDetection?: FlakyDetectionConfig;
|
|
16
17
|
resolutionsConfig?: ResolutionsConfig;
|
|
17
18
|
realtimeDispatcher?: RealtimeEventsDispatcher;
|
|
18
19
|
realtimeSubscriber?: RealtimeSubscriber;
|
|
@@ -24,6 +25,7 @@ export declare class DefaultAllureStore implements AllureStore, ResultsVisitor {
|
|
|
24
25
|
performance?: PerformanceConfig;
|
|
25
26
|
});
|
|
26
27
|
readHistory(): Promise<HistoryDataPoint[]>;
|
|
28
|
+
updateHistoryFlags(testResults?: Iterable<TestResult>): void;
|
|
27
29
|
appendHistory(history: HistoryDataPoint): Promise<void>;
|
|
28
30
|
addCheckResult(result: AllureCheckResult): Promise<void>;
|
|
29
31
|
allCheckResults(): Promise<AllureCheckResult[]>;
|