@allurereport/web-commons 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/charts/accessors/coverageDiffTreeMapAccessor.js +37 -24
- package/dist/charts/generateDurationDynamicsChart.js +1 -1
- package/dist/charts/generateStabilityDistributionChart.d.ts +1 -1
- package/dist/charts/generateStabilityDistributionChart.js +6 -4
- package/dist/charts/generateStatusAgePyramid.js +35 -44
- package/dist/charts/generateStatusTransitionsChart.js +11 -4
- package/dist/charts/generateTestBaseGrowthDynamicsChart.js +15 -5
- package/dist/charts/generators.js +12 -63
- package/dist/strings.d.ts +1 -0
- package/dist/strings.js +8 -5
- package/package.json +5 -5
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHistoryTestResultLookup, } from "@allurereport/core-api";
|
|
1
2
|
import { createTreeByLabels, md5 } from "@allurereport/plugin-api";
|
|
2
3
|
import { isChildrenLeavesOnly } from "../chart-utils.js";
|
|
3
4
|
import { convertTreeDataToTreeMapNode, transformTreeMapNode } from "../treeMapUtils.js";
|
|
@@ -35,22 +36,20 @@ const calculateColorValue = (metrics) => {
|
|
|
35
36
|
};
|
|
36
37
|
const isSkipped = (tr) => tr.status === "skipped";
|
|
37
38
|
const getNewTestResults = (trs, closestHtrs) => {
|
|
38
|
-
return trs.filter((tr) => !closestHtrs[tr.
|
|
39
|
+
return trs.filter((tr) => !closestHtrs[tr.retryHash]);
|
|
39
40
|
};
|
|
40
|
-
const getRemovedTestResults = (
|
|
41
|
-
|
|
42
|
-
const testResultsAsDictionary = Object.fromEntries(trs.map((tr) => [tr.historyId, tr]));
|
|
43
|
-
return historyPointTestResultsAsArray.filter((htr) => !testResultsAsDictionary[htr.historyId]);
|
|
41
|
+
const getRemovedTestResults = (historyTestResults, matchedHistoryTestResults) => {
|
|
42
|
+
return historyTestResults.filter((htr) => !matchedHistoryTestResults.has(htr));
|
|
44
43
|
};
|
|
45
44
|
const getEnabledTestResults = (trs, closestHtrs) => {
|
|
46
45
|
return trs.filter((tr) => {
|
|
47
|
-
const historyPointTestResult = closestHtrs[tr.
|
|
46
|
+
const historyPointTestResult = closestHtrs[tr.retryHash];
|
|
48
47
|
return historyPointTestResult && isSkipped(historyPointTestResult) && !isSkipped(tr);
|
|
49
48
|
});
|
|
50
49
|
};
|
|
51
50
|
const getDisabledTestResults = (trs, closestHtrs) => {
|
|
52
51
|
return trs.filter((tr) => {
|
|
53
|
-
const historyPointTestResult = closestHtrs[tr.
|
|
52
|
+
const historyPointTestResult = closestHtrs[tr.retryHash];
|
|
54
53
|
return historyPointTestResult && !isSkipped(historyPointTestResult) && isSkipped(tr);
|
|
55
54
|
});
|
|
56
55
|
};
|
|
@@ -80,33 +79,33 @@ const calculateSubtreeMetrics = (node) => {
|
|
|
80
79
|
}
|
|
81
80
|
return { totalTests, newCount, deletedCount, disabledCount, enabledCount };
|
|
82
81
|
};
|
|
83
|
-
const createCoverageDiffTreeMap = (trs, closestHtrs) => {
|
|
82
|
+
const createCoverageDiffTreeMap = (trs, closestHtrs, historyTestResults = [], matchedHistoryTestResults = new Set()) => {
|
|
84
83
|
const newTrs = getNewTestResults(trs, closestHtrs);
|
|
85
|
-
const removedHtrs = getRemovedTestResults(
|
|
84
|
+
const removedHtrs = getRemovedTestResults(historyTestResults, matchedHistoryTestResults);
|
|
86
85
|
const enabledTrs = getEnabledTestResults(trs, closestHtrs);
|
|
87
86
|
const disabledTrs = getDisabledTestResults(trs, closestHtrs);
|
|
88
|
-
const newTestsById = new Map(newTrs.map((tr) => [tr.
|
|
89
|
-
const deletedTestsById = new Map(removedHtrs.map((htr) => [htr.
|
|
90
|
-
const enabledTestsById = new Map(enabledTrs.map((tr) => [tr.
|
|
91
|
-
const disabledTestsById = new Map(disabledTrs.map((tr) => [tr.
|
|
87
|
+
const newTestsById = new Map(newTrs.map((tr) => [tr.retryHash, tr]));
|
|
88
|
+
const deletedTestsById = new Map(removedHtrs.map((htr) => [htr.retryHash, htr]));
|
|
89
|
+
const enabledTestsById = new Map(enabledTrs.map((tr) => [tr.retryHash, tr]));
|
|
90
|
+
const disabledTestsById = new Map(disabledTrs.map((tr) => [tr.retryHash, tr]));
|
|
92
91
|
const allTests = [...trs, ...removedHtrs];
|
|
93
|
-
const getChangeType = (
|
|
94
|
-
if (newTestsById.has(
|
|
92
|
+
const getChangeType = (retryHash) => {
|
|
93
|
+
if (newTestsById.has(retryHash)) {
|
|
95
94
|
return "new";
|
|
96
95
|
}
|
|
97
|
-
if (deletedTestsById.has(
|
|
96
|
+
if (deletedTestsById.has(retryHash)) {
|
|
98
97
|
return "deleted";
|
|
99
98
|
}
|
|
100
|
-
if (enabledTestsById.has(
|
|
99
|
+
if (enabledTestsById.has(retryHash)) {
|
|
101
100
|
return "enabled";
|
|
102
101
|
}
|
|
103
|
-
if (disabledTestsById.has(
|
|
102
|
+
if (disabledTestsById.has(retryHash)) {
|
|
104
103
|
return "disabled";
|
|
105
104
|
}
|
|
106
105
|
return "unchanged";
|
|
107
106
|
};
|
|
108
107
|
const leafFactoryFnWithMaps = (test) => {
|
|
109
|
-
const changeType = getChangeType(test.
|
|
108
|
+
const changeType = getChangeType(test.retryHash);
|
|
110
109
|
return {
|
|
111
110
|
nodeId: test.id,
|
|
112
111
|
name: test.name,
|
|
@@ -169,15 +168,29 @@ const createCoverageDiffTreeMap = (trs, closestHtrs) => {
|
|
|
169
168
|
});
|
|
170
169
|
};
|
|
171
170
|
export const coverageDiffTreeMapAccessor = {
|
|
172
|
-
getTreeMap: ({ testResults, historyDataPoints }) => {
|
|
171
|
+
getTreeMap: ({ testResults, historyDataPoints, allTestResults }) => {
|
|
172
|
+
const lookupHistoryTestResult = createHistoryTestResultLookup(allTestResults ?? testResults);
|
|
173
173
|
const testsWithBehaviorLabels = filterTestsWithBehaviorLabels(testResults);
|
|
174
174
|
if (!historyDataPoints || historyDataPoints.length === 0) {
|
|
175
175
|
return createCoverageDiffTreeMap(testsWithBehaviorLabels, {});
|
|
176
176
|
}
|
|
177
177
|
const closestHdp = historyDataPoints[0];
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
178
|
+
const closestHtrsWithBehaviorLabels = filterTestsWithBehaviorLabels(Object.values(closestHdp.testResults)).filter((tr) => {
|
|
179
|
+
const selected = lookupHistoryTestResult(closestHdp, tr);
|
|
180
|
+
return !selected || selected === tr;
|
|
181
|
+
});
|
|
182
|
+
const selectedHtrsByCurrentRetryHash = {};
|
|
183
|
+
const matchedHistoryTestResults = new Set();
|
|
184
|
+
for (const testResult of testsWithBehaviorLabels) {
|
|
185
|
+
if (!testResult.retryHash) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const historicalTestResult = lookupHistoryTestResult(closestHdp, testResult);
|
|
189
|
+
if (historicalTestResult) {
|
|
190
|
+
selectedHtrsByCurrentRetryHash[testResult.retryHash] = historicalTestResult;
|
|
191
|
+
matchedHistoryTestResults.add(historicalTestResult);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return createCoverageDiffTreeMap(testsWithBehaviorLabels, selectedHtrsByCurrentRetryHash, closestHtrsWithBehaviorLabels, matchedHistoryTestResults);
|
|
182
195
|
},
|
|
183
196
|
};
|
|
@@ -63,7 +63,7 @@ export const generateDurationDynamicsChart = (props) => {
|
|
|
63
63
|
...limitedHistoryPoints,
|
|
64
64
|
{
|
|
65
65
|
testResults: testResults.reduce((acc, testResult) => {
|
|
66
|
-
acc[testResult.
|
|
66
|
+
acc[testResult.retryHash ?? testResult.id] = testResult;
|
|
67
67
|
return acc;
|
|
68
68
|
}, {}),
|
|
69
69
|
uuid: "current",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AllureChartsStoreData, StabilityDistributionChartData, StabilityDistributionChartOptions } from "@allurereport/charts-api";
|
|
2
|
-
import type
|
|
2
|
+
import { type TestStatus } from "@allurereport/core-api";
|
|
3
3
|
export declare const getStabilityScore: (statuses: TestStatus[], historyDepth: number, stabilizationPeriod: number) => number | undefined;
|
|
4
4
|
export declare const generateStabilityDistributionChart: (props: {
|
|
5
5
|
options: StabilityDistributionChartOptions;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ChartType } from "@allurereport/charts-api";
|
|
2
|
+
import { createHistoryTestResultLookup, } from "@allurereport/core-api";
|
|
2
3
|
import { createHashStorage, createMapWithDefault } from "./utils.js";
|
|
3
4
|
const DEFAULT_LIMIT = 10;
|
|
4
5
|
const DEFAULT_STABILIZATION_PERIOD = 5;
|
|
@@ -79,10 +80,10 @@ export const getStabilityScore = (statuses, historyDepth, stabilizationPeriod) =
|
|
|
79
80
|
}
|
|
80
81
|
return instabilitySumNumerator / denominator;
|
|
81
82
|
};
|
|
82
|
-
const getStatusSequence = (historyDataPoints, tr) => {
|
|
83
|
+
const getStatusSequence = (historyDataPoints, tr, lookupHistoryTestResult) => {
|
|
83
84
|
let block = [];
|
|
84
85
|
for (const hdp of historyDataPoints) {
|
|
85
|
-
const htr = hdp
|
|
86
|
+
const htr = lookupHistoryTestResult(hdp, tr);
|
|
86
87
|
if (!htr) {
|
|
87
88
|
block = [];
|
|
88
89
|
continue;
|
|
@@ -100,6 +101,7 @@ export const generateStabilityDistributionChart = (props) => {
|
|
|
100
101
|
const { options, storeData } = props;
|
|
101
102
|
const { title, limit = DEFAULT_LIMIT, stabilizationPeriod = DEFAULT_STABILIZATION_PERIOD, threshold = DEFAULT_THRESHOLD, skipStatuses: skipStatusesList = NON_SIGNIFICANT_STATUSES, groupBy = DEFAULT_GROUP_BY, groupValues = [], } = options;
|
|
102
103
|
const { testResults, historyDataPoints } = storeData;
|
|
104
|
+
const lookupHistoryTestResult = createHistoryTestResultLookup(storeData.allTestResults ?? testResults);
|
|
103
105
|
const effectiveStabilizationPeriod = Math.min(stabilizationPeriod, limit);
|
|
104
106
|
if (historyDataPoints.length < effectiveStabilizationPeriod) {
|
|
105
107
|
return {
|
|
@@ -120,7 +122,7 @@ export const generateStabilityDistributionChart = (props) => {
|
|
|
120
122
|
const hashes = createHashStorage();
|
|
121
123
|
const skipStatuses = new Set(skipStatusesList);
|
|
122
124
|
for (const tr of testResults) {
|
|
123
|
-
if (!tr.
|
|
125
|
+
if (!tr.retryHash) {
|
|
124
126
|
continue;
|
|
125
127
|
}
|
|
126
128
|
if (!isSignificantStatus(tr.status)) {
|
|
@@ -133,7 +135,7 @@ export const generateStabilityDistributionChart = (props) => {
|
|
|
133
135
|
if (!labelValue || (groupValuesSet.size > 0 && !groupValuesSet.has(labelValue))) {
|
|
134
136
|
continue;
|
|
135
137
|
}
|
|
136
|
-
const statusSequence = getStatusSequence(limitedHistoryDataPoints, tr);
|
|
138
|
+
const statusSequence = getStatusSequence(limitedHistoryDataPoints, tr, lookupHistoryTestResult);
|
|
137
139
|
const stabilityScore = getStabilityScore(statusSequence, limit, effectiveStabilizationPeriod);
|
|
138
140
|
if (stabilityScore === undefined) {
|
|
139
141
|
continue;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ChartType, DEFAULT_CHART_HISTORY_LIMIT } from "@allurereport/charts-api";
|
|
2
|
+
import { createHistoryTestResultLookup } from "@allurereport/core-api";
|
|
2
3
|
import { limitHistoryDataPoints } from "./chart-utils.js";
|
|
3
4
|
const createEmptyStats = () => {
|
|
4
5
|
return STATUSES.reduce((acc, status) => {
|
|
@@ -12,6 +13,7 @@ export const generateStatusAgePyramid = (props) => {
|
|
|
12
13
|
const { options, storeData } = props;
|
|
13
14
|
const { limit = DEFAULT_CHART_HISTORY_LIMIT } = options;
|
|
14
15
|
const { historyDataPoints, testResults } = storeData;
|
|
16
|
+
const lookupHistoryTestResult = createHistoryTestResultLookup(storeData.allTestResults ?? testResults);
|
|
15
17
|
const currentReportTimestamp = testResults.reduce((acc, testResult) => Math.max(acc, testResult.stop ?? 0), 0);
|
|
16
18
|
const limitedHistoryPoints = limitHistoryDataPoints(historyDataPoints, limit).sort((a, b) => a.timestamp - b.timestamp);
|
|
17
19
|
if (limitedHistoryPoints.length === 0) {
|
|
@@ -28,59 +30,48 @@ export const generateStatusAgePyramid = (props) => {
|
|
|
28
30
|
statuses: STATUSES,
|
|
29
31
|
};
|
|
30
32
|
}
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (!
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
const isInCurrentRun = currTrIds.has(testResult.historyId);
|
|
39
|
-
if (isInCurrentRun) {
|
|
40
|
-
acc[testResult.historyId] = testResult;
|
|
33
|
+
const data = limitedHistoryPoints.map((historyDataPoint, index) => {
|
|
34
|
+
const stats = createEmptyStats();
|
|
35
|
+
for (const testResult of testResults) {
|
|
36
|
+
const historicalTestResult = lookupHistoryTestResult(historyDataPoint, testResult);
|
|
37
|
+
if (!historicalTestResult) {
|
|
38
|
+
continue;
|
|
41
39
|
}
|
|
42
|
-
|
|
43
|
-
}, {}),
|
|
44
|
-
}));
|
|
45
|
-
const dataPoints = [
|
|
46
|
-
...hdps.map((hdp) => ({
|
|
47
|
-
...hdp,
|
|
48
|
-
...createEmptyStats(),
|
|
49
|
-
})),
|
|
50
|
-
{
|
|
51
|
-
testResults: testResults.reduce((acc, testResult) => {
|
|
52
|
-
acc[testResult.historyId ?? testResult.id] = testResult;
|
|
53
|
-
return acc;
|
|
54
|
-
}, {}),
|
|
55
|
-
uuid: "current",
|
|
56
|
-
timestamp: currentReportTimestamp,
|
|
57
|
-
...createEmptyStats(),
|
|
58
|
-
},
|
|
59
|
-
];
|
|
60
|
-
dataPoints.forEach((dp, index, dps) => {
|
|
61
|
-
const { testResults: trs } = dp;
|
|
62
|
-
const historyAfter = dps.slice(index, dps.length - 1);
|
|
63
|
-
const currentTrs = Object.values(trs);
|
|
64
|
-
for (const cTr of currentTrs) {
|
|
65
|
-
const currentTrStatus = cTr.status;
|
|
40
|
+
const currentTrStatus = historicalTestResult.status;
|
|
66
41
|
if (!isFBSUStatus(currentTrStatus)) {
|
|
67
42
|
continue;
|
|
68
43
|
}
|
|
69
|
-
const historyAfterTrsStatuses =
|
|
44
|
+
const historyAfterTrsStatuses = limitedHistoryPoints
|
|
45
|
+
.slice(index)
|
|
46
|
+
.map((historyAfterPoint) => lookupHistoryTestResult(historyAfterPoint, testResult)?.status);
|
|
70
47
|
if (historyAfterTrsStatuses.some((status) => status !== currentTrStatus)) {
|
|
71
48
|
continue;
|
|
72
49
|
}
|
|
73
|
-
|
|
50
|
+
stats[currentTrStatus]++;
|
|
74
51
|
}
|
|
52
|
+
return {
|
|
53
|
+
id: historyDataPoint.uuid,
|
|
54
|
+
timestamp: historyDataPoint.timestamp,
|
|
55
|
+
failed: stats.failed,
|
|
56
|
+
broken: stats.broken,
|
|
57
|
+
skipped: stats.skipped,
|
|
58
|
+
unknown: stats.unknown,
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
const currentStats = createEmptyStats();
|
|
62
|
+
for (const testResult of testResults) {
|
|
63
|
+
if (isFBSUStatus(testResult.status)) {
|
|
64
|
+
currentStats[testResult.status]++;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
data.push({
|
|
68
|
+
id: "current",
|
|
69
|
+
timestamp: currentReportTimestamp,
|
|
70
|
+
failed: currentStats.failed,
|
|
71
|
+
broken: currentStats.broken,
|
|
72
|
+
skipped: currentStats.skipped,
|
|
73
|
+
unknown: currentStats.unknown,
|
|
75
74
|
});
|
|
76
|
-
const data = dataPoints.map(({ uuid, timestamp, ...stats }) => ({
|
|
77
|
-
id: uuid,
|
|
78
|
-
timestamp,
|
|
79
|
-
failed: stats.failed ?? 0,
|
|
80
|
-
broken: stats.broken ?? 0,
|
|
81
|
-
skipped: stats.skipped ?? 0,
|
|
82
|
-
unknown: stats.unknown ?? 0,
|
|
83
|
-
}));
|
|
84
75
|
return {
|
|
85
76
|
type: ChartType.StatusAgePyramid,
|
|
86
77
|
title: options.title,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ChartType, DEFAULT_CHART_HISTORY_LIMIT, } from "@allurereport/charts-api";
|
|
2
|
-
import {
|
|
2
|
+
import { createHistoryTestResultLookup, } from "@allurereport/core-api";
|
|
3
3
|
import { limitHistoryDataPoints } from "./chart-utils.js";
|
|
4
4
|
const getLastSignificantStatus = (history = []) => {
|
|
5
5
|
const significantHtr = [...history]
|
|
@@ -31,6 +31,7 @@ export const generateStatusTransitionsChart = (props) => {
|
|
|
31
31
|
const { options, storeData } = props;
|
|
32
32
|
const { limit = DEFAULT_CHART_HISTORY_LIMIT } = options;
|
|
33
33
|
const { historyDataPoints, testResults } = storeData;
|
|
34
|
+
const lookupHistoryTestResult = createHistoryTestResultLookup(storeData.allTestResults ?? testResults);
|
|
34
35
|
const limitedHdps = limitHistoryDataPoints(historyDataPoints, limit).sort((a, b) => a.timestamp - b.timestamp);
|
|
35
36
|
const currentReportTimestamp = testResults.reduce((acc, testResult) => Math.max(acc, testResult.stop ?? 0), 0);
|
|
36
37
|
if (limitedHdps.length === 0) {
|
|
@@ -55,7 +56,7 @@ export const generateStatusTransitionsChart = (props) => {
|
|
|
55
56
|
...hdps,
|
|
56
57
|
{
|
|
57
58
|
testResults: testResults.reduce((acc, testResult) => {
|
|
58
|
-
acc[testResult.
|
|
59
|
+
acc[testResult.retryHash ?? testResult.id] = testResult;
|
|
59
60
|
return acc;
|
|
60
61
|
}, {}),
|
|
61
62
|
uuid: "current",
|
|
@@ -73,9 +74,15 @@ export const generateStatusTransitionsChart = (props) => {
|
|
|
73
74
|
malfunctioned: 0,
|
|
74
75
|
};
|
|
75
76
|
data.push(newDataItem);
|
|
76
|
-
const cTrs = Object.values(trs)
|
|
77
|
+
const cTrs = Object.values(trs).filter((tr) => {
|
|
78
|
+
const selected = lookupHistoryTestResult({ testResults: trs }, tr);
|
|
79
|
+
return !selected || selected === tr;
|
|
80
|
+
});
|
|
77
81
|
for (const cTr of cTrs) {
|
|
78
|
-
const htrs =
|
|
82
|
+
const htrs = hpsPriorToCurrent.flatMap((historyDataPoint) => {
|
|
83
|
+
const historicalTestResult = lookupHistoryTestResult(historyDataPoint, cTr);
|
|
84
|
+
return historicalTestResult ? [historicalTestResult] : [];
|
|
85
|
+
});
|
|
79
86
|
const transition = getStatusTransition(cTr, htrs);
|
|
80
87
|
if (!transition || transition === "new") {
|
|
81
88
|
continue;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ChartType, DEFAULT_CHART_HISTORY_LIMIT } from "@allurereport/charts-api";
|
|
2
|
-
import {
|
|
2
|
+
import { createHistoryTestResultLookup, statusesList, } from "@allurereport/core-api";
|
|
3
3
|
import { limitHistoryDataPoints } from "./chart-utils.js";
|
|
4
4
|
const createEmptyStats = (statuses) => {
|
|
5
5
|
return statuses.reduce((acc, status) => {
|
|
@@ -13,6 +13,7 @@ export const generateTestBaseGrowthDynamicsChart = (props) => {
|
|
|
13
13
|
const { options, storeData } = props;
|
|
14
14
|
const { limit = DEFAULT_CHART_HISTORY_LIMIT, statuses = DEFAULT_STATUSES } = options;
|
|
15
15
|
const { historyDataPoints, testResults } = storeData;
|
|
16
|
+
const lookupHistoryTestResult = createHistoryTestResultLookup(storeData.allTestResults ?? testResults);
|
|
16
17
|
const currentReportTimestamp = testResults.reduce((acc, testResult) => Math.max(acc, testResult.stop ?? 0), 0);
|
|
17
18
|
const statusList = statuses.length > 0 ? statuses : DEFAULT_STATUSES;
|
|
18
19
|
const limitedHistoryPoints = limitHistoryDataPoints(historyDataPoints, limit).sort((a, b) => a.timestamp - b.timestamp);
|
|
@@ -38,7 +39,7 @@ export const generateTestBaseGrowthDynamicsChart = (props) => {
|
|
|
38
39
|
})),
|
|
39
40
|
{
|
|
40
41
|
testResults: testResults.reduce((acc, testResult) => {
|
|
41
|
-
acc[testResult.
|
|
42
|
+
acc[testResult.retryHash ?? testResult.id] = testResult;
|
|
42
43
|
return acc;
|
|
43
44
|
}, {}),
|
|
44
45
|
uuid: "current",
|
|
@@ -51,19 +52,28 @@ export const generateTestBaseGrowthDynamicsChart = (props) => {
|
|
|
51
52
|
const isLast = index === dataPoints.length - 1;
|
|
52
53
|
const hpsPriorToCurrent = isFirst ? [earliestHdp] : dataPoints.slice(0, index);
|
|
53
54
|
const hpsAfterCurrent = dataPoints.slice(index + 1);
|
|
54
|
-
const currentTrs = Object.values(trs)
|
|
55
|
+
const currentTrs = Object.values(trs).filter((tr) => {
|
|
56
|
+
const selected = lookupHistoryTestResult({ testResults: trs }, tr);
|
|
57
|
+
return !selected || selected === tr;
|
|
58
|
+
});
|
|
55
59
|
for (const cTr of currentTrs) {
|
|
56
60
|
if (!statusList.includes(cTr.status)) {
|
|
57
61
|
continue;
|
|
58
62
|
}
|
|
59
|
-
const htrsPriortoCurr =
|
|
63
|
+
const htrsPriortoCurr = hpsPriorToCurrent.flatMap((historyDataPoint) => {
|
|
64
|
+
const historicalTestResult = lookupHistoryTestResult(historyDataPoint, cTr);
|
|
65
|
+
return historicalTestResult ? [historicalTestResult] : [];
|
|
66
|
+
});
|
|
60
67
|
if (htrsPriortoCurr.length === 0) {
|
|
61
68
|
stats[`new:${cTr.status}`]++;
|
|
62
69
|
}
|
|
63
70
|
if (isLast) {
|
|
64
71
|
continue;
|
|
65
72
|
}
|
|
66
|
-
const htrsAfterCurrent =
|
|
73
|
+
const htrsAfterCurrent = hpsAfterCurrent.flatMap((historyDataPoint) => {
|
|
74
|
+
const historicalTestResult = lookupHistoryTestResult(historyDataPoint, cTr);
|
|
75
|
+
return historicalTestResult ? [historicalTestResult] : [];
|
|
76
|
+
});
|
|
67
77
|
if (htrsAfterCurrent.length === 0) {
|
|
68
78
|
stats[`removed:${cTr.status}`]++;
|
|
69
79
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ChartType, } from "@allurereport/charts-api";
|
|
2
|
-
import { DEFAULT_ENVIRONMENT, emptyStatistic,
|
|
2
|
+
import { DEFAULT_ENVIRONMENT, emptyStatistic, incrementStatistic, } from "@allurereport/core-api";
|
|
3
3
|
import { generateCurrentStatusChart } from "./generateCurrentStatusChart.js";
|
|
4
4
|
import { generateDurationDynamicsChart } from "./generateDurationDynamicsChart.js";
|
|
5
5
|
import { generateDurationsChart } from "./generateDurationsChart.js";
|
|
@@ -12,60 +12,6 @@ import { generateTestingPyramidChart } from "./generateTestingPyramidChart.js";
|
|
|
12
12
|
import { generateTrSeveritiesChart } from "./generateTrSeveritiesChart.js";
|
|
13
13
|
import { generateHeatMapChart } from "./heatMap.js";
|
|
14
14
|
import { generateTreeMapChart } from "./treeMap.js";
|
|
15
|
-
const buildFallbackHistoryAliases = (testResults) => {
|
|
16
|
-
const aliases = new Map();
|
|
17
|
-
const ambiguousAliases = new Set();
|
|
18
|
-
for (const testResult of testResults) {
|
|
19
|
-
if (!testResult.historyId) {
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
const fallbackHistoryId = getFallbackHistoryId(testResult);
|
|
23
|
-
if (!fallbackHistoryId || fallbackHistoryId === testResult.historyId) {
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
const existingAlias = aliases.get(fallbackHistoryId);
|
|
27
|
-
if (existingAlias && existingAlias !== testResult.historyId) {
|
|
28
|
-
aliases.delete(fallbackHistoryId);
|
|
29
|
-
ambiguousAliases.add(fallbackHistoryId);
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
if (!ambiguousAliases.has(fallbackHistoryId)) {
|
|
33
|
-
aliases.set(fallbackHistoryId, testResult.historyId);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return aliases;
|
|
37
|
-
};
|
|
38
|
-
const normalizeHistoryDataPointsByAliases = (historyDataPoints, aliases) => {
|
|
39
|
-
if (aliases.size === 0) {
|
|
40
|
-
return historyDataPoints;
|
|
41
|
-
}
|
|
42
|
-
return historyDataPoints.map((historyDataPoint) => {
|
|
43
|
-
let testResults = historyDataPoint.testResults;
|
|
44
|
-
for (const [legacyHistoryId, primaryHistoryId] of aliases) {
|
|
45
|
-
if (!Object.prototype.hasOwnProperty.call(testResults, legacyHistoryId)) {
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
if (Object.prototype.hasOwnProperty.call(testResults, primaryHistoryId)) {
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
if (testResults === historyDataPoint.testResults) {
|
|
52
|
-
testResults = { ...testResults };
|
|
53
|
-
}
|
|
54
|
-
testResults[primaryHistoryId] = {
|
|
55
|
-
...testResults[legacyHistoryId],
|
|
56
|
-
historyId: primaryHistoryId,
|
|
57
|
-
};
|
|
58
|
-
delete testResults[legacyHistoryId];
|
|
59
|
-
}
|
|
60
|
-
if (testResults === historyDataPoint.testResults) {
|
|
61
|
-
return historyDataPoint;
|
|
62
|
-
}
|
|
63
|
-
return {
|
|
64
|
-
...historyDataPoint,
|
|
65
|
-
testResults,
|
|
66
|
-
};
|
|
67
|
-
});
|
|
68
|
-
};
|
|
69
15
|
const generateChartData = async (props) => {
|
|
70
16
|
const { envId, chartsOptions, store, generateUuid, filter } = props;
|
|
71
17
|
const result = {};
|
|
@@ -116,14 +62,17 @@ const generateChartData = async (props) => {
|
|
|
116
62
|
}
|
|
117
63
|
return statistic;
|
|
118
64
|
};
|
|
119
|
-
const storeData = await Promise.all([
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
65
|
+
const storeData = await Promise.all([
|
|
66
|
+
getHistoryDataPoints(),
|
|
67
|
+
getTrs(),
|
|
68
|
+
getStatistic(),
|
|
69
|
+
store.allTestResults({ includeRetries: true }),
|
|
70
|
+
]).then(([historyDataPoints, testResults, statistic, allTestResults]) => ({
|
|
71
|
+
historyDataPoints,
|
|
72
|
+
testResults,
|
|
73
|
+
statistic,
|
|
74
|
+
allTestResults,
|
|
75
|
+
}));
|
|
127
76
|
for (const chartOption of chartsOptions) {
|
|
128
77
|
const chartId = generateUuid();
|
|
129
78
|
switch (chartOption.type) {
|
package/dist/strings.d.ts
CHANGED
|
@@ -10,5 +10,6 @@ export interface AnsiToHtmlConfig {
|
|
|
10
10
|
}
|
|
11
11
|
export declare const isAnsi: (text?: string) => boolean;
|
|
12
12
|
export declare const ansiSemanticColors: Record<number, string>;
|
|
13
|
+
export declare const normalizeEscapedAnsiSequences: (text: string) => string;
|
|
13
14
|
export declare const normalizeAnsiForegroundColors: (text: string) => string;
|
|
14
15
|
export declare const ansiToHTML: (text: string, config?: AnsiToHtmlConfig) => string;
|
package/dist/strings.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import AnsiToHtml from "ansi-to-html";
|
|
2
2
|
const ansiRegex = /\x1B\[[0-9;?]*[ -/]*[@-~]/g;
|
|
3
|
+
const ansiEscape = "\u001B";
|
|
4
|
+
const ansiControlSequencePattern = new RegExp(`${ansiEscape}\\[([0-9;]*)m`, "g");
|
|
3
5
|
export const isAnsi = (text) => typeof text === "string" && new RegExp(ansiRegex).test(text);
|
|
4
6
|
const semanticAnsiColor = {
|
|
5
7
|
primary: 256,
|
|
@@ -81,7 +83,8 @@ const getXtermColorRgb = (colorIndex) => {
|
|
|
81
83
|
}
|
|
82
84
|
};
|
|
83
85
|
const isValidColorPart = (value) => Number.isInteger(value) && value >= 0 && value <= 255;
|
|
84
|
-
export const
|
|
86
|
+
export const normalizeEscapedAnsiSequences = (text) => text.replace(/\\u001b(?=\[)/giu, ansiEscape).replace(/\\x1b(?=\[)/giu, ansiEscape);
|
|
87
|
+
export const normalizeAnsiForegroundColors = (text) => text.replace(ansiControlSequencePattern, (match, sequence) => {
|
|
85
88
|
const codes = sequence.length === 0 ? [0] : sequence.split(";").map(Number);
|
|
86
89
|
if (codes.some((code) => !Number.isInteger(code))) {
|
|
87
90
|
return match;
|
|
@@ -114,8 +117,6 @@ export const normalizeAnsiForegroundColors = (text) => text.replace(/\x1b\[([0-9
|
|
|
114
117
|
continue;
|
|
115
118
|
}
|
|
116
119
|
if (code === 48 && codes[index + 1] === 5 && isValidColorPart(codes[index + 2])) {
|
|
117
|
-
flushDisplayCodes();
|
|
118
|
-
fragments.push(`\x1b[48;5;${codes[index + 2]}m`);
|
|
119
120
|
index += 3;
|
|
120
121
|
continue;
|
|
121
122
|
}
|
|
@@ -124,11 +125,13 @@ export const normalizeAnsiForegroundColors = (text) => text.replace(/\x1b\[([0-9
|
|
|
124
125
|
isValidColorPart(codes[index + 2]) &&
|
|
125
126
|
isValidColorPart(codes[index + 3]) &&
|
|
126
127
|
isValidColorPart(codes[index + 4])) {
|
|
127
|
-
flushDisplayCodes();
|
|
128
|
-
fragments.push(`\x1b[48;2;${codes[index + 2]};${codes[index + 3]};${codes[index + 4]}m`);
|
|
129
128
|
index += 5;
|
|
130
129
|
continue;
|
|
131
130
|
}
|
|
131
|
+
if ((code >= 40 && code <= 47) || code === 49 || (code >= 100 && code <= 107)) {
|
|
132
|
+
index += 1;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
132
135
|
displayCodes.push(code);
|
|
133
136
|
index += 1;
|
|
134
137
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/web-commons",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.19.1",
|
|
4
4
|
"description": "Collection of utilities used across the web Allure reports",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure",
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"lint:fix": "oxlint --import-plugin --fix src test features stories"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@allurereport/aql": "3.
|
|
30
|
-
"@allurereport/charts-api": "3.
|
|
31
|
-
"@allurereport/core-api": "3.
|
|
32
|
-
"@allurereport/plugin-api": "3.
|
|
29
|
+
"@allurereport/aql": "3.19.1",
|
|
30
|
+
"@allurereport/charts-api": "3.19.1",
|
|
31
|
+
"@allurereport/core-api": "3.19.1",
|
|
32
|
+
"@allurereport/plugin-api": "3.19.1",
|
|
33
33
|
"@preact/signals": "^2.6.1",
|
|
34
34
|
"@preact/signals-core": "^1.12.2",
|
|
35
35
|
"ansi-to-html": "^0.7.2",
|