@allurereport/plugin-api 3.0.0-beta.17 → 3.0.0-beta.18
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.d.ts +85 -0
- package/dist/charts.js +163 -0
- package/dist/config.d.ts +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -0
- package/dist/plugin.d.ts +30 -6
- package/dist/qualityGate.d.ts +28 -37
- package/dist/severityTrendAccessor.d.ts +3 -0
- package/dist/severityTrendAccessor.js +21 -0
- package/dist/statusTrendAccessor.d.ts +3 -0
- package/dist/statusTrendAccessor.js +19 -0
- package/dist/store.d.ts +7 -1
- package/package.json +3 -3
package/dist/charts.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { BaseTrendSliceMetadata, ChartId, ChartType, HistoryDataPoint, PieSlice, SeverityLevel, Statistic, TestResult, TestStatus, TrendPoint, TrendPointId, TrendSlice, TrendSliceId } from "@allurereport/core-api";
|
|
2
|
+
import { ChartDataType, ChartMode } from "@allurereport/core-api";
|
|
3
|
+
import type { PluginContext } from "./plugin.js";
|
|
4
|
+
export type ExecutionIdFn = (executionOrder: number) => string;
|
|
5
|
+
export type ExecutionNameFn = (executionOrder: number) => string;
|
|
6
|
+
export type TrendMetadataFnOverrides = {
|
|
7
|
+
executionIdAccessor?: ExecutionIdFn;
|
|
8
|
+
executionNameAccessor?: ExecutionNameFn;
|
|
9
|
+
};
|
|
10
|
+
export type TrendDataType = TestStatus | SeverityLevel;
|
|
11
|
+
export type TrendCalculationResult<T extends TrendDataType> = {
|
|
12
|
+
points: Record<TrendPointId, TrendPoint>;
|
|
13
|
+
series: Record<T, TrendPointId[]>;
|
|
14
|
+
};
|
|
15
|
+
export interface GenericTrendChartData<SeriesType extends string, Metadata extends BaseTrendSliceMetadata = BaseTrendSliceMetadata> {
|
|
16
|
+
type: ChartType.Trend;
|
|
17
|
+
dataType: ChartDataType;
|
|
18
|
+
mode: ChartMode;
|
|
19
|
+
title?: string;
|
|
20
|
+
points: Record<TrendPointId, TrendPoint>;
|
|
21
|
+
slices: Record<TrendSliceId, TrendSlice<Metadata>>;
|
|
22
|
+
series: Record<SeriesType, TrendPointId[]>;
|
|
23
|
+
min: number;
|
|
24
|
+
max: number;
|
|
25
|
+
}
|
|
26
|
+
export type StatusTrendChartData = GenericTrendChartData<TestStatus>;
|
|
27
|
+
export type SeverityTrendChartData = GenericTrendChartData<SeverityLevel>;
|
|
28
|
+
export type TrendChartData = StatusTrendChartData | SeverityTrendChartData;
|
|
29
|
+
export type GeneratedChartData = TrendChartData | PieChartData | ComingSoonChartData;
|
|
30
|
+
export type GeneratedChartsData = Record<ChartId, GeneratedChartData>;
|
|
31
|
+
export type TrendStats<T extends TrendDataType> = Record<T, number>;
|
|
32
|
+
export type TrendChartOptions = {
|
|
33
|
+
type: ChartType.Trend;
|
|
34
|
+
dataType: ChartDataType;
|
|
35
|
+
mode?: ChartMode;
|
|
36
|
+
title?: string;
|
|
37
|
+
limit?: number;
|
|
38
|
+
metadata?: TrendMetadataFnOverrides;
|
|
39
|
+
};
|
|
40
|
+
export type PieChartOptions = {
|
|
41
|
+
type: ChartType.Pie;
|
|
42
|
+
title?: string;
|
|
43
|
+
};
|
|
44
|
+
export type ComingSoonChartOptions = {
|
|
45
|
+
type: ChartType.HeatMap | ChartType.Bar | ChartType.Funnel | ChartType.TreeMap;
|
|
46
|
+
title?: string;
|
|
47
|
+
};
|
|
48
|
+
export type ChartOptions = TrendChartOptions | PieChartOptions | ComingSoonChartOptions;
|
|
49
|
+
export interface PieChartData {
|
|
50
|
+
type: ChartType.Pie;
|
|
51
|
+
title?: string;
|
|
52
|
+
slices: PieSlice[];
|
|
53
|
+
percentage: number;
|
|
54
|
+
}
|
|
55
|
+
export interface ComingSoonChartData {
|
|
56
|
+
type: ChartType.HeatMap | ChartType.Bar | ChartType.Funnel | ChartType.TreeMap;
|
|
57
|
+
title?: string;
|
|
58
|
+
}
|
|
59
|
+
export declare const createEmptySeries: <T extends TrendDataType>(items: readonly T[]) => Record<T, string[]>;
|
|
60
|
+
export declare const calculatePercentValues: <T extends TrendDataType>(stats: Record<T, number>, executionId: string, itemType: readonly T[]) => TrendCalculationResult<T>;
|
|
61
|
+
export declare const getTrendDataGeneric: <T extends TrendDataType, M extends BaseTrendSliceMetadata>(stats: Record<T, number>, reportName: string, executionOrder: number, itemType: readonly T[], chartOptions: TrendChartOptions) => GenericTrendChartData<T, M>;
|
|
62
|
+
export declare const createEmptyStats: <T extends TrendDataType>(items: readonly T[]) => TrendStats<T>;
|
|
63
|
+
export declare const normalizeStatistic: <T extends TrendDataType>(statistic: Partial<TrendStats<T>>, itemType: readonly T[]) => TrendStats<T>;
|
|
64
|
+
export declare const mergeTrendDataGeneric: <T extends TrendDataType, M extends BaseTrendSliceMetadata>(trendData: GenericTrendChartData<T, M>, trendDataPart: GenericTrendChartData<T, M>, itemType: readonly T[]) => GenericTrendChartData<T, M>;
|
|
65
|
+
export declare const DEFAULT_CHART_HISTORY_LIMIT = 10;
|
|
66
|
+
export declare const getPieChartData: (stats: Statistic, chartOptions: PieChartOptions) => PieChartData;
|
|
67
|
+
export declare const generatePieChart: (options: PieChartOptions, stores: {
|
|
68
|
+
statistic: Statistic;
|
|
69
|
+
}) => PieChartData;
|
|
70
|
+
export declare const generateComingSoonChart: (options: ComingSoonChartOptions) => ComingSoonChartData;
|
|
71
|
+
export interface TrendDataAccessor<T extends TrendDataType> {
|
|
72
|
+
getCurrentData: (trs: TestResult[], stats: Statistic) => TrendStats<T>;
|
|
73
|
+
getHistoricalData: (historyPoint: HistoryDataPoint) => TrendStats<T>;
|
|
74
|
+
getAllValues: () => readonly T[];
|
|
75
|
+
}
|
|
76
|
+
export declare const generateTrendChartGeneric: <T extends TrendDataType>(options: TrendChartOptions, stores: {
|
|
77
|
+
trs: TestResult[];
|
|
78
|
+
statistic: Statistic;
|
|
79
|
+
history: HistoryDataPoint[];
|
|
80
|
+
}, context: PluginContext, dataAccessor: TrendDataAccessor<T>) => GenericTrendChartData<T> | undefined;
|
|
81
|
+
export declare const generateTrendChart: (options: TrendChartOptions, stores: {
|
|
82
|
+
trs: TestResult[];
|
|
83
|
+
statistic: Statistic;
|
|
84
|
+
history: HistoryDataPoint[];
|
|
85
|
+
}, context: PluginContext) => TrendChartData | undefined;
|
package/dist/charts.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { ChartDataType, ChartMode, getPieChartValues } from "@allurereport/core-api";
|
|
2
|
+
import { severityTrendDataAccessor } from "./severityTrendAccessor.js";
|
|
3
|
+
import { statusTrendDataAccessor } from "./statusTrendAccessor.js";
|
|
4
|
+
export const createEmptySeries = (items) => items.reduce((acc, item) => ({ ...acc, [item]: [] }), {});
|
|
5
|
+
export const calculatePercentValues = (stats, executionId, itemType) => {
|
|
6
|
+
const points = {};
|
|
7
|
+
const series = createEmptySeries(itemType);
|
|
8
|
+
const values = Object.values(stats);
|
|
9
|
+
const total = values.reduce((sum, value) => sum + value, 0);
|
|
10
|
+
if (total === 0) {
|
|
11
|
+
return { points, series };
|
|
12
|
+
}
|
|
13
|
+
itemType.forEach((item) => {
|
|
14
|
+
const pointId = `${executionId}-${item}`;
|
|
15
|
+
const value = stats[item] ?? 0;
|
|
16
|
+
points[pointId] = {
|
|
17
|
+
x: executionId,
|
|
18
|
+
y: value / total,
|
|
19
|
+
};
|
|
20
|
+
series[item].push(pointId);
|
|
21
|
+
});
|
|
22
|
+
return { points, series };
|
|
23
|
+
};
|
|
24
|
+
const calculateRawValues = (stats, executionId, itemType) => {
|
|
25
|
+
const points = {};
|
|
26
|
+
const series = createEmptySeries(itemType);
|
|
27
|
+
itemType.forEach((item) => {
|
|
28
|
+
const pointId = `${executionId}-${item}`;
|
|
29
|
+
const value = stats[item] ?? 0;
|
|
30
|
+
points[pointId] = {
|
|
31
|
+
x: executionId,
|
|
32
|
+
y: value,
|
|
33
|
+
};
|
|
34
|
+
series[item].push(pointId);
|
|
35
|
+
});
|
|
36
|
+
return { points, series };
|
|
37
|
+
};
|
|
38
|
+
export const getTrendDataGeneric = (stats, reportName, executionOrder, itemType, chartOptions) => {
|
|
39
|
+
const { type, dataType, title, mode = ChartMode.Raw, metadata = {} } = chartOptions;
|
|
40
|
+
const { executionIdAccessor, executionNameAccessor } = metadata;
|
|
41
|
+
const executionId = executionIdAccessor ? executionIdAccessor(executionOrder) : `execution-${executionOrder}`;
|
|
42
|
+
const { points, series } = mode === ChartMode.Percent
|
|
43
|
+
? calculatePercentValues(stats, executionId, itemType)
|
|
44
|
+
: calculateRawValues(stats, executionId, itemType);
|
|
45
|
+
const slices = {};
|
|
46
|
+
const pointsAsArray = Object.values(points);
|
|
47
|
+
const pointsCount = pointsAsArray.length;
|
|
48
|
+
const values = pointsAsArray.map((point) => point.y);
|
|
49
|
+
const min = pointsCount ? Math.min(...values) : 0;
|
|
50
|
+
const max = pointsCount ? Math.max(...values) : 0;
|
|
51
|
+
if (pointsCount > 0) {
|
|
52
|
+
const executionName = executionNameAccessor ? executionNameAccessor(executionOrder) : reportName;
|
|
53
|
+
slices[executionId] = {
|
|
54
|
+
min,
|
|
55
|
+
max,
|
|
56
|
+
metadata: {
|
|
57
|
+
executionId,
|
|
58
|
+
executionName,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
type,
|
|
64
|
+
dataType,
|
|
65
|
+
mode,
|
|
66
|
+
title,
|
|
67
|
+
points,
|
|
68
|
+
slices,
|
|
69
|
+
series,
|
|
70
|
+
min,
|
|
71
|
+
max,
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
export const createEmptyStats = (items) => items.reduce((acc, item) => ({ ...acc, [item]: 0 }), {});
|
|
75
|
+
export const normalizeStatistic = (statistic, itemType) => {
|
|
76
|
+
return itemType.reduce((acc, item) => {
|
|
77
|
+
acc[item] = statistic[item] ?? 0;
|
|
78
|
+
return acc;
|
|
79
|
+
}, {});
|
|
80
|
+
};
|
|
81
|
+
export const mergeTrendDataGeneric = (trendData, trendDataPart, itemType) => {
|
|
82
|
+
return {
|
|
83
|
+
...trendData,
|
|
84
|
+
points: {
|
|
85
|
+
...trendData.points,
|
|
86
|
+
...trendDataPart.points,
|
|
87
|
+
},
|
|
88
|
+
slices: {
|
|
89
|
+
...trendData.slices,
|
|
90
|
+
...trendDataPart.slices,
|
|
91
|
+
},
|
|
92
|
+
series: Object.entries(trendDataPart.series).reduce((series, [group, pointIds]) => {
|
|
93
|
+
if (Array.isArray(pointIds)) {
|
|
94
|
+
return {
|
|
95
|
+
...series,
|
|
96
|
+
[group]: [...(trendData.series?.[group] || []), ...pointIds],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return series;
|
|
100
|
+
}, trendData.series || createEmptySeries(itemType)),
|
|
101
|
+
min: Math.min(trendData.min ?? Infinity, trendDataPart.min),
|
|
102
|
+
max: Math.max(trendData.max ?? -Infinity, trendDataPart.max),
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
export const DEFAULT_CHART_HISTORY_LIMIT = 10;
|
|
106
|
+
export const getPieChartData = (stats, chartOptions) => ({
|
|
107
|
+
type: chartOptions.type,
|
|
108
|
+
title: chartOptions?.title,
|
|
109
|
+
...getPieChartValues(stats),
|
|
110
|
+
});
|
|
111
|
+
export const generatePieChart = (options, stores) => {
|
|
112
|
+
const { statistic } = stores;
|
|
113
|
+
return getPieChartData(statistic, options);
|
|
114
|
+
};
|
|
115
|
+
export const generateComingSoonChart = (options) => {
|
|
116
|
+
return {
|
|
117
|
+
type: options.type,
|
|
118
|
+
title: options.title,
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
export const generateTrendChartGeneric = (options, stores, context, dataAccessor) => {
|
|
122
|
+
const { trs = [], statistic, history } = stores;
|
|
123
|
+
const { limit } = options;
|
|
124
|
+
const historyLimit = limit && limit > 0 ? Math.max(0, limit - 1) : undefined;
|
|
125
|
+
const currentData = dataAccessor.getCurrentData(trs, statistic);
|
|
126
|
+
const limitedHistoryPoints = historyLimit !== undefined ? history.slice(-historyLimit) : history;
|
|
127
|
+
const firstOriginalIndex = historyLimit !== undefined ? Math.max(0, history.length - historyLimit) : 0;
|
|
128
|
+
const convertedHistoryPoints = limitedHistoryPoints.map((point, index) => {
|
|
129
|
+
const originalIndex = firstOriginalIndex + index;
|
|
130
|
+
return {
|
|
131
|
+
name: point.name,
|
|
132
|
+
originalIndex,
|
|
133
|
+
statistic: dataAccessor.getHistoricalData(point),
|
|
134
|
+
};
|
|
135
|
+
});
|
|
136
|
+
const allValues = dataAccessor.getAllValues();
|
|
137
|
+
const currentTrendData = getTrendDataGeneric(normalizeStatistic(currentData, allValues), context.reportName, history.length + 1, allValues, options);
|
|
138
|
+
const historicalTrendData = convertedHistoryPoints.reduce((acc, historyPoint) => {
|
|
139
|
+
const trendDataPart = getTrendDataGeneric(normalizeStatistic(historyPoint.statistic, allValues), historyPoint.name, historyPoint.originalIndex + 1, allValues, options);
|
|
140
|
+
return mergeTrendDataGeneric(acc, trendDataPart, allValues);
|
|
141
|
+
}, {
|
|
142
|
+
type: options.type,
|
|
143
|
+
dataType: options.dataType,
|
|
144
|
+
mode: options.mode,
|
|
145
|
+
title: options.title,
|
|
146
|
+
points: {},
|
|
147
|
+
slices: {},
|
|
148
|
+
series: createEmptySeries(allValues),
|
|
149
|
+
min: Infinity,
|
|
150
|
+
max: -Infinity,
|
|
151
|
+
});
|
|
152
|
+
return mergeTrendDataGeneric(historicalTrendData, currentTrendData, allValues);
|
|
153
|
+
};
|
|
154
|
+
export const generateTrendChart = (options, stores, context) => {
|
|
155
|
+
const newOptions = { limit: DEFAULT_CHART_HISTORY_LIMIT, ...options };
|
|
156
|
+
const { dataType } = newOptions;
|
|
157
|
+
if (dataType === ChartDataType.Status) {
|
|
158
|
+
return generateTrendChartGeneric(newOptions, stores, context, statusTrendDataAccessor);
|
|
159
|
+
}
|
|
160
|
+
else if (dataType === ChartDataType.Severity) {
|
|
161
|
+
return generateTrendChartGeneric(newOptions, stores, context, severityTrendDataAccessor);
|
|
162
|
+
}
|
|
163
|
+
};
|
package/dist/config.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ export interface Config {
|
|
|
10
10
|
environments?: EnvironmentsConfig;
|
|
11
11
|
variables?: ReportVariables;
|
|
12
12
|
plugins?: Record<string, PluginDescriptor>;
|
|
13
|
-
qualityGate?: QualityGateConfig;
|
|
14
13
|
appendHistory?: boolean;
|
|
14
|
+
qualityGate?: QualityGateConfig;
|
|
15
15
|
allureService?: {
|
|
16
16
|
url?: string;
|
|
17
17
|
project?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export * from "./config.js";
|
|
2
2
|
export type * from "./plugin.js";
|
|
3
|
-
export type * from "./qualityGate.js";
|
|
4
3
|
export type * from "./store.js";
|
|
5
4
|
export type * from "./resultFile.js";
|
|
5
|
+
export type * from "./qualityGate.js";
|
|
6
6
|
export * from "./utils/misc.js";
|
|
7
7
|
export * from "./utils/tree.js";
|
|
8
8
|
export * from "./utils/summary.js";
|
|
9
|
+
export * from "./charts.js";
|
|
10
|
+
export * from "./severityTrendAccessor.js";
|
|
11
|
+
export * from "./statusTrendAccessor.js";
|
package/dist/index.js
CHANGED
package/dist/plugin.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { CiDescriptor, Statistic, TestResult, TestStatus } from "@allurereport/core-api";
|
|
1
|
+
import type { AttachmentLink, CiDescriptor, Statistic, TestError, TestResult, TestStatus } from "@allurereport/core-api";
|
|
2
|
+
import type { QualityGateValidationResult } from "./qualityGate.js";
|
|
3
|
+
import type { ResultFile } from "./resultFile.js";
|
|
2
4
|
import type { AllureStore } from "./store.js";
|
|
3
5
|
export interface PluginDescriptor {
|
|
4
6
|
import?: string;
|
|
@@ -39,16 +41,38 @@ export interface PluginSummary {
|
|
|
39
41
|
retryTests?: SummaryTestResult[];
|
|
40
42
|
createdAt?: number;
|
|
41
43
|
}
|
|
44
|
+
export interface ExitCode {
|
|
45
|
+
actual?: number;
|
|
46
|
+
original: number;
|
|
47
|
+
}
|
|
48
|
+
export interface PluginGlobals {
|
|
49
|
+
exitCode: ExitCode;
|
|
50
|
+
errors: TestError[];
|
|
51
|
+
attachments: AttachmentLink[];
|
|
52
|
+
}
|
|
42
53
|
export interface BatchOptions {
|
|
43
54
|
maxTimeout?: number;
|
|
44
55
|
}
|
|
45
|
-
export interface
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
56
|
+
export interface RealtimeSubscriber {
|
|
57
|
+
onGlobalAttachment(listener: (attachment: ResultFile) => Promise<void>): () => void;
|
|
58
|
+
onGlobalExitCode(listener: (payload: ExitCode) => Promise<void>): () => void;
|
|
59
|
+
onGlobalError(listener: (error: TestError) => Promise<void>): () => void;
|
|
60
|
+
onQualityGateResults(listener: (payload: QualityGateValidationResult[]) => Promise<void>): () => void;
|
|
61
|
+
onTestResults(listener: (trIds: string[]) => Promise<void>, options?: BatchOptions): () => void;
|
|
62
|
+
onTestFixtureResults(listener: (tfrIds: string[]) => Promise<void>, options?: BatchOptions): () => void;
|
|
63
|
+
onAttachmentFiles(listener: (afIds: string[]) => Promise<void>, options?: BatchOptions): () => void;
|
|
64
|
+
}
|
|
65
|
+
export interface RealtimeEventsDispatcher {
|
|
66
|
+
sendGlobalAttachment(attachment: ResultFile): void;
|
|
67
|
+
sendGlobalExitCode(payload: ExitCode): void;
|
|
68
|
+
sendGlobalError(error: TestError): void;
|
|
69
|
+
sendQualityGateResults(payload: QualityGateValidationResult[]): void;
|
|
70
|
+
sendTestResult(trId: string): void;
|
|
71
|
+
sendTestFixtureResult(tfrId: string): void;
|
|
72
|
+
sendAttachmentFile(afId: string): void;
|
|
49
73
|
}
|
|
50
74
|
export interface Plugin {
|
|
51
|
-
start?(context: PluginContext, store: AllureStore, realtime:
|
|
75
|
+
start?(context: PluginContext, store: AllureStore, realtime: RealtimeSubscriber): Promise<void>;
|
|
52
76
|
update?(context: PluginContext, store: AllureStore): Promise<void>;
|
|
53
77
|
done?(context: PluginContext, store: AllureStore): Promise<void>;
|
|
54
78
|
info?(context: PluginContext, store: AllureStore): Promise<PluginSummary>;
|
package/dist/qualityGate.d.ts
CHANGED
|
@@ -1,44 +1,35 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export type
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
value: string;
|
|
9
|
-
};
|
|
10
|
-
export type QualityGateParametersRulesMeta = QualityGateRulesBaseMeta<"parameter"> & {
|
|
11
|
-
name: string;
|
|
12
|
-
value: string;
|
|
13
|
-
};
|
|
14
|
-
export type QualityGateLabelsEnforceConfig = {
|
|
15
|
-
type: "label";
|
|
16
|
-
name: string;
|
|
17
|
-
value: string;
|
|
18
|
-
rules: QualityGateRules;
|
|
1
|
+
import type { KnownTestFailure, TestResult } from "@allurereport/core-api";
|
|
2
|
+
export type QualityGateValidationResult = {
|
|
3
|
+
success: boolean;
|
|
4
|
+
expected: any;
|
|
5
|
+
actual: any;
|
|
6
|
+
rule: string;
|
|
7
|
+
message: string;
|
|
19
8
|
};
|
|
20
|
-
export type
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
rules: QualityGateRules;
|
|
9
|
+
export type QualityGateRules = Record<string, any> & {
|
|
10
|
+
id?: string;
|
|
11
|
+
fastFail?: boolean;
|
|
12
|
+
filter?: (tr: TestResult) => boolean;
|
|
25
13
|
};
|
|
26
|
-
export type
|
|
27
|
-
export type QualityGateEnforceConfig = QualityGateLabelsEnforceConfig | QualityGateParametersEnforceConfig;
|
|
28
|
-
export type QualityGateValidationResult = {
|
|
14
|
+
export type QualityGateRuleResult = {
|
|
29
15
|
success: boolean;
|
|
16
|
+
expected: any;
|
|
17
|
+
actual: any;
|
|
18
|
+
};
|
|
19
|
+
export type QualityGateRule<T = any> = {
|
|
30
20
|
rule: string;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
21
|
+
message: (payload: {
|
|
22
|
+
expected: T;
|
|
23
|
+
actual: T;
|
|
24
|
+
}) => string;
|
|
25
|
+
validate: (payload: {
|
|
26
|
+
expected: T;
|
|
27
|
+
trs: TestResult[];
|
|
28
|
+
knownIssues: KnownTestFailure[];
|
|
29
|
+
state?: T;
|
|
30
|
+
}) => Promise<QualityGateRuleResult>;
|
|
35
31
|
};
|
|
36
|
-
export interface QualityGateValidator {
|
|
37
|
-
validate(store: AllureStore): Promise<QualityGateValidationResult>;
|
|
38
|
-
}
|
|
39
|
-
export type QualityGateValidatorConstructor = new (limit: number, meta?: QualityGateRulesMeta) => QualityGateValidator;
|
|
40
32
|
export type QualityGateConfig = {
|
|
41
|
-
rules?: QualityGateRules;
|
|
42
|
-
|
|
43
|
-
validators?: Record<string, QualityGateValidatorConstructor>;
|
|
33
|
+
rules?: QualityGateRules[];
|
|
34
|
+
use?: QualityGateRule[];
|
|
44
35
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { severityLabelName, severityLevels } from "@allurereport/core-api";
|
|
2
|
+
import { createEmptyStats } from "./charts.js";
|
|
3
|
+
const processTestResults = (testResults) => {
|
|
4
|
+
return testResults.reduce((acc, test) => {
|
|
5
|
+
const severityLabel = test.labels?.find((label) => label.name === severityLabelName);
|
|
6
|
+
const severity = severityLabel?.value?.toLowerCase();
|
|
7
|
+
if (severity) {
|
|
8
|
+
acc[severity] = (acc[severity] ?? 0) + 1;
|
|
9
|
+
}
|
|
10
|
+
return acc;
|
|
11
|
+
}, createEmptyStats(severityLevels));
|
|
12
|
+
};
|
|
13
|
+
export const severityTrendDataAccessor = {
|
|
14
|
+
getCurrentData: (trs) => {
|
|
15
|
+
return processTestResults(trs);
|
|
16
|
+
},
|
|
17
|
+
getHistoricalData: (historyPoint) => {
|
|
18
|
+
return processTestResults(Object.values(historyPoint.testResults));
|
|
19
|
+
},
|
|
20
|
+
getAllValues: () => severityLevels,
|
|
21
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { statusesList } from "@allurereport/core-api";
|
|
2
|
+
import { createEmptyStats } from "./charts.js";
|
|
3
|
+
export const statusTrendDataAccessor = {
|
|
4
|
+
getCurrentData: (trs, stats) => {
|
|
5
|
+
return {
|
|
6
|
+
...createEmptyStats(statusesList),
|
|
7
|
+
...stats,
|
|
8
|
+
};
|
|
9
|
+
},
|
|
10
|
+
getHistoricalData: (historyPoint) => {
|
|
11
|
+
return Object.values(historyPoint.testResults).reduce((stat, test) => {
|
|
12
|
+
if (test.status) {
|
|
13
|
+
stat[test.status] = (stat[test.status] ?? 0) + 1;
|
|
14
|
+
}
|
|
15
|
+
return stat;
|
|
16
|
+
}, createEmptyStats(statusesList));
|
|
17
|
+
},
|
|
18
|
+
getAllValues: () => statusesList,
|
|
19
|
+
};
|
package/dist/store.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { AttachmentLink, HistoryDataPoint, HistoryTestResult, KnownTestFailure, Statistic, TestCase, TestEnvGroup, TestFixtureResult, TestResult } from "@allurereport/core-api";
|
|
1
|
+
import type { AttachmentLink, HistoryDataPoint, HistoryTestResult, KnownTestFailure, Statistic, TestCase, TestEnvGroup, TestError, TestFixtureResult, TestResult } from "@allurereport/core-api";
|
|
2
|
+
import type { ExitCode } from "./plugin.js";
|
|
3
|
+
import type { QualityGateValidationResult } from "./qualityGate.js";
|
|
2
4
|
import type { ResultFile } from "./resultFile.js";
|
|
3
5
|
export type TestResultFilter = (testResult: TestResult) => boolean;
|
|
4
6
|
export interface AllureStore {
|
|
@@ -12,6 +14,10 @@ export interface AllureStore {
|
|
|
12
14
|
allHistoryDataPoints: () => Promise<HistoryDataPoint[]>;
|
|
13
15
|
allKnownIssues: () => Promise<KnownTestFailure[]>;
|
|
14
16
|
allNewTestResults: () => Promise<TestResult[]>;
|
|
17
|
+
qualityGateResults: () => Promise<QualityGateValidationResult[]>;
|
|
18
|
+
globalExitCode: () => Promise<ExitCode | undefined>;
|
|
19
|
+
allGlobalErrors: () => Promise<TestError[]>;
|
|
20
|
+
allGlobalAttachments: () => Promise<AttachmentLink[]>;
|
|
15
21
|
testCaseById: (tcId: string) => Promise<TestCase | undefined>;
|
|
16
22
|
testResultById: (trId: string) => Promise<TestResult | undefined>;
|
|
17
23
|
attachmentById: (attachmentId: string) => Promise<AttachmentLink | undefined>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/plugin-api",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.18",
|
|
4
4
|
"description": "Allure Plugin API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure"
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"test": "rimraf ./out && vitest run"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@allurereport/core-api": "3.0.0-beta.
|
|
29
|
+
"@allurereport/core-api": "3.0.0-beta.18"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@stylistic/eslint-plugin": "^2.6.1",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@typescript-eslint/parser": "^8.0.0",
|
|
37
37
|
"@vitest/runner": "^2.1.9",
|
|
38
38
|
"@vitest/snapshot": "^2.1.9",
|
|
39
|
-
"allure-vitest": "^3.3.
|
|
39
|
+
"allure-vitest": "^3.3.3",
|
|
40
40
|
"eslint": "^8.57.0",
|
|
41
41
|
"eslint-config-prettier": "^9.1.0",
|
|
42
42
|
"eslint-plugin-import": "^2.29.1",
|