@allurereport/plugin-allure2 3.15.0 → 3.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -11
- package/dist/categories.js +9 -6
- package/dist/converters.d.ts +2 -1
- package/dist/converters.js +111 -43
- package/dist/generators.d.ts +10 -15
- package/dist/generators.js +163 -123
- package/dist/model.d.ts +37 -2
- package/dist/model.js +1 -1
- package/dist/plugin.js +18 -3
- package/dist/static/report.tar +0 -0
- package/dist/tree.d.ts +1 -0
- package/dist/tree.js +1 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +11 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Allure 2 Plugin
|
|
2
2
|
|
|
3
3
|
[<img src="https://allurereport.org/public/img/allure-report.svg" height="85px" alt="Allure Report logo" align="right" />](https://allurereport.org "Allure Report")
|
|
4
4
|
|
|
@@ -12,16 +12,17 @@
|
|
|
12
12
|
|
|
13
13
|
## Overview
|
|
14
14
|
|
|
15
|
-
The plugin generates
|
|
15
|
+
The plugin generates an Allure 2-compatible report using the Allure 2.46.0 UI built from
|
|
16
|
+
the checked-in `@allurereport/web-allure2` sources and embedded in the plugin package.
|
|
16
17
|
|
|
17
18
|
## Install
|
|
18
19
|
|
|
19
20
|
Use your favorite package manager to install the package:
|
|
20
21
|
|
|
21
22
|
```shell
|
|
22
|
-
npm add @allurereport/plugin-
|
|
23
|
-
yarn add @allurereport/plugin-
|
|
24
|
-
pnpm add @allurereport/plugin-
|
|
23
|
+
npm add @allurereport/plugin-allure2
|
|
24
|
+
yarn add @allurereport/plugin-allure2
|
|
25
|
+
pnpm add @allurereport/plugin-allure2
|
|
25
26
|
```
|
|
26
27
|
|
|
27
28
|
Then, add the plugin to the Allure configuration file:
|
|
@@ -34,7 +35,7 @@ export default defineConfig({
|
|
|
34
35
|
output: "./allure-report",
|
|
35
36
|
historyPath: "./history.jsonl",
|
|
36
37
|
plugins: {
|
|
37
|
-
+
|
|
38
|
+
+ allure2: {
|
|
38
39
|
+ options: {
|
|
39
40
|
+ reportName: "HelloWorld",
|
|
40
41
|
+ },
|
|
@@ -47,8 +48,8 @@ export default defineConfig({
|
|
|
47
48
|
|
|
48
49
|
The plugin accepts the following options:
|
|
49
50
|
|
|
50
|
-
| Option | Description | Type
|
|
51
|
-
|
|
52
|
-
| `reportName` | Name of the report | `string`
|
|
53
|
-
| `singleFile` | Writes the report as a single `index.html` file | `boolean`
|
|
54
|
-
| `reportLanguage` | Default language of the report | `string`
|
|
51
|
+
| Option | Description | Type | Default |
|
|
52
|
+
| ---------------- | ----------------------------------------------- | --------- | --------------- |
|
|
53
|
+
| `reportName` | Name of the report | `string` | `Allure Report` |
|
|
54
|
+
| `singleFile` | Writes the report as a single `index.html` file | `boolean` | `false` |
|
|
55
|
+
| `reportLanguage` | Default language of the report | `string` | OS language |
|
package/dist/categories.js
CHANGED
|
@@ -7,14 +7,17 @@ const testDefects = {
|
|
|
7
7
|
matchedStatuses: ["broken"],
|
|
8
8
|
};
|
|
9
9
|
export const matchCategories = (categories, result) => {
|
|
10
|
-
const matched = categories.
|
|
11
|
-
if (matched
|
|
12
|
-
matched
|
|
10
|
+
const matched = categories.find((category) => categoryMatch(category, result));
|
|
11
|
+
if (matched) {
|
|
12
|
+
return [matched];
|
|
13
13
|
}
|
|
14
|
-
if (
|
|
15
|
-
|
|
14
|
+
if (categoryMatch(productDefects, result)) {
|
|
15
|
+
return [productDefects];
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
if (categoryMatch(testDefects, result)) {
|
|
18
|
+
return [testDefects];
|
|
19
|
+
}
|
|
20
|
+
return [];
|
|
18
21
|
};
|
|
19
22
|
const categoryMatch = (category, result) => {
|
|
20
23
|
const { status, statusMessage, statusTrace, flaky } = result;
|
package/dist/converters.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { HistoryTestResult, TestFixtureResult, TestResult } from "@allurereport/core-api";
|
|
2
|
-
import type { Allure2Category, Allure2TestResult } from "./model.js";
|
|
2
|
+
import type { Allure2Category, Allure2HistoryData, Allure2TestResult } from "./model.js";
|
|
3
3
|
type ConvertContext = {
|
|
4
4
|
attachmentMap: Map<string, string>;
|
|
5
5
|
fixtures: TestFixtureResult[];
|
|
6
6
|
categories: Allure2Category[];
|
|
7
7
|
retries: TestResult[];
|
|
8
8
|
history: HistoryTestResult[];
|
|
9
|
+
legacyHistory?: Allure2HistoryData;
|
|
9
10
|
};
|
|
10
11
|
export declare const convertTestResult: (context: ConvertContext, test: TestResult) => Allure2TestResult;
|
|
11
12
|
export {};
|
package/dist/converters.js
CHANGED
|
@@ -1,31 +1,70 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isStep, redactParameters } from "@allurereport/core-api";
|
|
2
2
|
import { matchCategories } from "./categories.js";
|
|
3
3
|
import { severityValues } from "./model.js";
|
|
4
|
-
import { updateStatistic } from "./utils.js";
|
|
4
|
+
import { createStatistic, updateStatistic } from "./utils.js";
|
|
5
5
|
const sortByTime = (a, b) => a.time.start !== undefined && b.time.start !== undefined ? a.time.start - b.time.start : 0;
|
|
6
6
|
const convertStatus = (status) => status;
|
|
7
|
+
const getTopLevelAttachmentCount = (result) => {
|
|
8
|
+
if (result.sourceMetadata.readerId !== "allure2") {
|
|
9
|
+
return 0;
|
|
10
|
+
}
|
|
11
|
+
const value = result.sourceMetadata.metadata.allure2_top_level_attachment_count;
|
|
12
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : 0;
|
|
13
|
+
};
|
|
14
|
+
const hasMessage = (step, message) => step.statusMessage === message || step.steps.some((child) => hasMessage(child, message));
|
|
15
|
+
const summarize = (name, statusMessage, steps, attachments, parametersCount) => {
|
|
16
|
+
const stepsCount = steps.reduce((count, step) => count + 1 + step.stepsCount, 0);
|
|
17
|
+
const attachmentsCount = attachments.length + steps.reduce((count, step) => count + step.attachmentsCount, 0);
|
|
18
|
+
const shouldDisplayMessage = !!statusMessage && !steps.some((step) => hasMessage(step, statusMessage));
|
|
19
|
+
return {
|
|
20
|
+
stepsCount,
|
|
21
|
+
attachmentsCount,
|
|
22
|
+
shouldDisplayMessage,
|
|
23
|
+
hasContent: steps.length + attachments.length + parametersCount > 0 || shouldDisplayMessage,
|
|
24
|
+
attachmentStep: stepsCount === 0 && attachmentsCount === 1 && name !== undefined && name === attachments[0]?.name,
|
|
25
|
+
};
|
|
26
|
+
};
|
|
7
27
|
const convertStageResult = (context, result) => {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
28
|
+
const topLevelAttachmentCount = Math.min(getTopLevelAttachmentCount(result), result.steps.length);
|
|
29
|
+
const attachmentStart = result.steps.length - topLevelAttachmentCount;
|
|
30
|
+
const attachmentCandidates = result.steps.slice(attachmentStart);
|
|
31
|
+
const stageSteps = [
|
|
32
|
+
...result.steps.slice(0, attachmentStart),
|
|
33
|
+
...attachmentCandidates.filter((step) => isStep(step)),
|
|
34
|
+
];
|
|
35
|
+
const attachments = attachmentCandidates
|
|
36
|
+
.filter((step) => !isStep(step))
|
|
37
|
+
.map((step) => convertAttachment(context, step));
|
|
38
|
+
const steps = stageSteps.map((step) => convertStep(context, step));
|
|
39
|
+
const name = "type" in result ? result.name : undefined;
|
|
40
|
+
const statusMessage = result.error?.message;
|
|
41
|
+
const summary = summarize(name, statusMessage, steps, attachments, 0);
|
|
42
|
+
return {
|
|
43
|
+
...(name === undefined ? {} : { name }),
|
|
44
|
+
time: {
|
|
45
|
+
start: result.start,
|
|
46
|
+
stop: result.stop,
|
|
47
|
+
duration: result.duration,
|
|
48
|
+
},
|
|
14
49
|
status: result.status,
|
|
50
|
+
statusMessage,
|
|
51
|
+
statusTrace: result.error?.trace,
|
|
52
|
+
steps,
|
|
53
|
+
attachments,
|
|
15
54
|
parameters: [],
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
return testStage;
|
|
55
|
+
...summary,
|
|
56
|
+
};
|
|
19
57
|
};
|
|
20
58
|
const convertStep = (context, step) => {
|
|
21
59
|
if (isStep(step)) {
|
|
22
60
|
const name = step.name;
|
|
23
|
-
const steps = step.steps.map((child) => convertStep(context, child));
|
|
24
|
-
const
|
|
61
|
+
const steps = step.steps.filter((child) => isStep(child)).map((child) => convertStep(context, child));
|
|
62
|
+
const attachments = step.steps
|
|
63
|
+
.filter((child) => !isStep(child))
|
|
64
|
+
.map((child) => convertAttachment(context, child));
|
|
25
65
|
const parameters = redactParameters(step.parameters);
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const shouldDisplayMessage = !!statusMessage || steps.findIndex((s) => s.statusMessage === statusMessage) > 0;
|
|
66
|
+
const statusMessage = step.error?.message ?? step.message;
|
|
67
|
+
const summary = summarize(name, statusMessage, steps, attachments, parameters.length);
|
|
29
68
|
return {
|
|
30
69
|
name,
|
|
31
70
|
time: {
|
|
@@ -35,15 +74,11 @@ const convertStep = (context, step) => {
|
|
|
35
74
|
},
|
|
36
75
|
status: step.status,
|
|
37
76
|
statusMessage,
|
|
38
|
-
statusTrace: step.error?.trace,
|
|
77
|
+
statusTrace: step.error?.trace ?? step.trace,
|
|
39
78
|
steps,
|
|
40
|
-
attachments
|
|
79
|
+
attachments,
|
|
41
80
|
parameters,
|
|
42
|
-
|
|
43
|
-
attachmentsCount: 0,
|
|
44
|
-
hasContent: stepsCount + parametersCount > 0 || shouldDisplayMessage,
|
|
45
|
-
shouldDisplayMessage,
|
|
46
|
-
attachmentStep: false,
|
|
81
|
+
...summary,
|
|
47
82
|
};
|
|
48
83
|
}
|
|
49
84
|
const stepName = step.link.name;
|
|
@@ -87,8 +122,30 @@ const extractSeverity = (test) => {
|
|
|
87
122
|
return (maybeSeverity ? severityValues.find((value) => value === maybeSeverity) : undefined) ?? "normal";
|
|
88
123
|
};
|
|
89
124
|
const importantStatuses = ["failed", "broken", "passed"];
|
|
125
|
+
const isImportantStatus = (status) => importantStatuses.includes(status);
|
|
126
|
+
const getAllure2Links = (test) => {
|
|
127
|
+
if (test.sourceMetadata.readerId !== "allure2") {
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
const links = test.sourceMetadata.metadata.allure2_links;
|
|
131
|
+
if (!Array.isArray(links)) {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
return links.map((link) => ({
|
|
135
|
+
name: typeof link?.name === "string" ? link.name : undefined,
|
|
136
|
+
url: typeof link?.url === "string" ? link.url : undefined,
|
|
137
|
+
type: typeof link?.type === "string" ? link.type : undefined,
|
|
138
|
+
}));
|
|
139
|
+
};
|
|
140
|
+
const isFlakyFromHistory = (currentStatus, historyItems) => {
|
|
141
|
+
if (currentStatus !== "failed" && currentStatus !== "broken") {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
const statuses = historyItems.slice(0, 5).map(({ status }) => status);
|
|
145
|
+
return statuses.includes("passed") && statuses.indexOf("passed") < statuses.lastIndexOf("failed");
|
|
146
|
+
};
|
|
90
147
|
export const convertTestResult = (context, test) => {
|
|
91
|
-
const testStage = convertStageResult(context, test);
|
|
148
|
+
const testStage = test.steps.length > 0 ? convertStageResult(context, test) : null;
|
|
92
149
|
const beforeStages = context.fixtures
|
|
93
150
|
.filter((value) => value.type === "before")
|
|
94
151
|
.map((fixture) => convertStageResult(context, fixture))
|
|
@@ -103,8 +160,6 @@ export const convertTestResult = (context, test) => {
|
|
|
103
160
|
const status = convertStatus(test.status);
|
|
104
161
|
const statusMessage = test.error?.message;
|
|
105
162
|
const statusTrace = test.error?.trace;
|
|
106
|
-
const flaky = false;
|
|
107
|
-
const categories = matchCategories(context.categories, { statusMessage, statusTrace, status, flaky });
|
|
108
163
|
const retries = context.retries.map((retry) => ({
|
|
109
164
|
uid: retry.id,
|
|
110
165
|
status: convertStatus(retry.status),
|
|
@@ -115,25 +170,38 @@ export const convertTestResult = (context, test) => {
|
|
|
115
170
|
duration: retry.duration,
|
|
116
171
|
},
|
|
117
172
|
}));
|
|
118
|
-
const retriesStatusChange = status
|
|
119
|
-
retries.find((
|
|
120
|
-
const
|
|
173
|
+
const retriesStatusChange = isImportantStatus(status) &&
|
|
174
|
+
retries.find((retry) => isImportantStatus(retry.status) && retry.status !== status) !== undefined;
|
|
175
|
+
const historyItems = context.legacyHistory
|
|
176
|
+
? context.legacyHistory.items.map((item) => ({
|
|
177
|
+
uid: item.uid,
|
|
178
|
+
status: item.status,
|
|
179
|
+
reportUrl: item.reportUrl,
|
|
180
|
+
statusDetails: item.statusDetails,
|
|
181
|
+
time: { ...item.time },
|
|
182
|
+
}))
|
|
183
|
+
: context.history.map((historyTestResult) => ({
|
|
184
|
+
uid: historyTestResult.id,
|
|
185
|
+
status: convertStatus(historyTestResult.status),
|
|
186
|
+
reportUrl: historyTestResult.url,
|
|
187
|
+
statusDetails: historyTestResult.error?.message,
|
|
188
|
+
time: {
|
|
189
|
+
start: historyTestResult.start,
|
|
190
|
+
stop: historyTestResult.stop,
|
|
191
|
+
duration: historyTestResult.duration,
|
|
192
|
+
},
|
|
193
|
+
}));
|
|
194
|
+
const lastHistoryStatus = historyItems.find(({ status: historyStatus }) => isImportantStatus(historyStatus))?.status;
|
|
121
195
|
const newFailed = lastHistoryStatus === "passed" && test.status === "failed";
|
|
122
196
|
const newBroken = lastHistoryStatus === "passed" && test.status === "broken";
|
|
123
197
|
const newPassed = lastHistoryStatus !== undefined && lastHistoryStatus !== "passed" && test.status === "passed";
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
stop: htr.stop,
|
|
132
|
-
duration: htr.duration,
|
|
133
|
-
},
|
|
134
|
-
}));
|
|
135
|
-
const statistic = { total: 0 };
|
|
136
|
-
historyItems.forEach((historyItem) => updateStatistic(statistic, historyItem));
|
|
198
|
+
const flaky = test.flaky || isFlakyFromHistory(status, historyItems);
|
|
199
|
+
const categories = matchCategories(context.categories, { statusMessage, statusTrace, status, flaky });
|
|
200
|
+
const statistic = createStatistic(context.legacyHistory?.statistic);
|
|
201
|
+
if (!context.legacyHistory) {
|
|
202
|
+
historyItems.forEach((historyItem) => updateStatistic(statistic, historyItem));
|
|
203
|
+
}
|
|
204
|
+
updateStatistic(statistic, test);
|
|
137
205
|
const history = {
|
|
138
206
|
statistic,
|
|
139
207
|
items: historyItems,
|
|
@@ -155,7 +223,7 @@ export const convertTestResult = (context, test) => {
|
|
|
155
223
|
statusMessage,
|
|
156
224
|
statusTrace,
|
|
157
225
|
labels: test.labels,
|
|
158
|
-
links: test.links,
|
|
226
|
+
links: getAllure2Links(test) ?? test.links,
|
|
159
227
|
parameters: redactParameters(test.parameters),
|
|
160
228
|
afterStages,
|
|
161
229
|
beforeStages,
|
package/dist/generators.d.ts
CHANGED
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
import type { AttachmentLink, HistoryDataPoint } from "@allurereport/core-api";
|
|
1
|
+
import type { AttachmentLink, GlobalAttachmentLink, HistoryDataPoint, TestError } from "@allurereport/core-api";
|
|
2
2
|
import type { ReportFiles, ResultFile } from "@allurereport/plugin-api";
|
|
3
|
-
import type {
|
|
3
|
+
import type { ReportStaticManifest } from "@allurereport/plugin-api/static-assets";
|
|
4
|
+
import type { Allure2CategoriesTrendItem, Allure2DurationTrendItem, Allure2ExecutorInfo, Allure2LegacyHistoryTrendItem, Allure2RetryTrendItem, Allure2TestResult } from "./model.js";
|
|
4
5
|
import type { Allure2DataWriter, ReportFile } from "./writer.js";
|
|
5
|
-
export type TemplateManifest =
|
|
6
|
-
export declare const
|
|
7
|
-
export declare const readTemplateManifest: (packageRoot: string, singleFileMode?: boolean) => Promise<TemplateManifest>;
|
|
8
|
-
export declare const readManifestEntry: (options: {
|
|
9
|
-
fileName: string;
|
|
10
|
-
singleFile?: boolean;
|
|
11
|
-
mimeType: string;
|
|
12
|
-
reportFiles: ReportFiles;
|
|
13
|
-
inserter: (content: string) => string;
|
|
14
|
-
packageRoot: string;
|
|
15
|
-
}) => Promise<string>;
|
|
6
|
+
export type TemplateManifest = ReportStaticManifest;
|
|
7
|
+
export declare const readTemplateManifest: () => Promise<TemplateManifest>;
|
|
16
8
|
export declare const generateStaticFiles: (payload: {
|
|
17
9
|
allureVersion: string;
|
|
18
10
|
reportName: string;
|
|
@@ -34,6 +26,9 @@ export declare const generateEnvironmentJson: (writer: Allure2DataWriter, env: {
|
|
|
34
26
|
}[]) => Promise<void>;
|
|
35
27
|
export declare const generateExecutorJson: (writer: Allure2DataWriter, executor?: Partial<Allure2ExecutorInfo>) => Promise<void>;
|
|
36
28
|
export declare const generateDefaultWidgetData: (writer: Allure2DataWriter, tests: Allure2TestResult[], ...fileNames: string[]) => Promise<void>;
|
|
37
|
-
export declare const
|
|
38
|
-
export declare const
|
|
29
|
+
export declare const generateHistoryTrendData: (writer: Allure2DataWriter, reportName: string, tests: Allure2TestResult[], historyDataPoints: HistoryDataPoint[], legacyHistory?: Allure2LegacyHistoryTrendItem[], executor?: Partial<Allure2ExecutorInfo>) => Promise<void>;
|
|
30
|
+
export declare const generateDurationTrendData: (writer: Allure2DataWriter, tests: Allure2TestResult[], history?: Allure2DurationTrendItem[], executor?: Partial<Allure2ExecutorInfo>) => Promise<void>;
|
|
31
|
+
export declare const generateRetryTrendData: (writer: Allure2DataWriter, tests: Allure2TestResult[], history?: Allure2RetryTrendItem[], executor?: Partial<Allure2ExecutorInfo>) => Promise<void>;
|
|
32
|
+
export declare const generateCategoriesTrendData: (writer: Allure2DataWriter, tests: Allure2TestResult[], history?: Allure2CategoriesTrendItem[], executor?: Partial<Allure2ExecutorInfo>) => Promise<void>;
|
|
39
33
|
export declare const generateAttachmentsData: (writer: Allure2DataWriter, attachmentLinks: AttachmentLink[], contentFunction: (id: string) => Promise<ResultFile | undefined>) => Promise<Map<string, string>>;
|
|
34
|
+
export declare const generateGlobalsData: (writer: Allure2DataWriter, globalErrors: TestError[], globalAttachments: GlobalAttachmentLink[], attachmentMap: Map<string, string>, attachmentTimestamps?: Record<string, number>, errorTimestamps?: Array<number | undefined>) => Promise<void>;
|
package/dist/generators.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { createBaseUrlScript, createFaviconLinkTag, createReportDataScript, stringifyForInlineScript, createScriptTag, createStylesLinkTag, } from "@allurereport/core-api";
|
|
5
|
-
import { findUp } from "find-up";
|
|
1
|
+
import { createBaseUrlScript, createScriptTag, createStylesLinkTag } from "@allurereport/core-api";
|
|
2
|
+
import { copyReportStaticAssets, getReportStaticAsset, readReportStaticAssets, } from "@allurereport/plugin-api/static-assets";
|
|
6
3
|
import Handlebars from "handlebars";
|
|
7
4
|
import { byLabels, collapseTree, createTree, createWidget } from "./tree.js";
|
|
8
|
-
import { updateStatistic, updateTime } from "./utils.js";
|
|
5
|
+
import { createStatistic, updateStatistic, updateTime } from "./utils.js";
|
|
6
|
+
const reportStaticArchive = new URL("../dist/static/report.tar", import.meta.url);
|
|
9
7
|
const writeConcurrently = async (items, write, concurrency = 64) => {
|
|
10
8
|
for (let i = 0; i < items.length; i += concurrency) {
|
|
11
9
|
await Promise.all(items.slice(i, i + concurrency).map(write));
|
|
@@ -15,14 +13,11 @@ const template = `<!DOCTYPE html>
|
|
|
15
13
|
<html dir="ltr" lang="{{reportLanguage}}">
|
|
16
14
|
<head>
|
|
17
15
|
<meta charset="utf-8">
|
|
16
|
+
<meta name="allure-report-uuid" content="{{reportUuid}}">
|
|
18
17
|
<title>{{reportName}}</title>
|
|
19
18
|
{{{ headTags }}}
|
|
20
|
-
<script>
|
|
21
|
-
window.allureReportOptions = {{{ reportOptions }}};
|
|
22
|
-
</script>
|
|
23
19
|
</head>
|
|
24
20
|
<body>
|
|
25
|
-
<svg id="__SVG_SPRITE_NODE__" aria-hidden="true" style="position: absolute; width: 0; height: 0"></svg>
|
|
26
21
|
<div id="alert"></div>
|
|
27
22
|
<div id="content">
|
|
28
23
|
<span class="spinner">
|
|
@@ -30,19 +25,29 @@ const template = `<!DOCTYPE html>
|
|
|
30
25
|
</span>
|
|
31
26
|
</div>
|
|
32
27
|
<div id="popup"></div>
|
|
28
|
+
<script>
|
|
29
|
+
window.__allureCoreLoaded = new Promise(function (resolve, reject) {
|
|
30
|
+
window.__allureResolveCoreLoaded = resolve;
|
|
31
|
+
window.__allureRejectCoreLoaded = reject;
|
|
32
|
+
});
|
|
33
|
+
</script>
|
|
33
34
|
{{{ bodyTags }}}
|
|
35
|
+
<script>
|
|
36
|
+
if (typeof window.__allureResolveCoreLoaded === "function") {
|
|
37
|
+
window.__allureResolveCoreLoaded([]);
|
|
38
|
+
}
|
|
39
|
+
</script>
|
|
34
40
|
${createBaseUrlScript()}
|
|
35
41
|
{{#if analyticsEnable}}
|
|
36
|
-
<script async src="https://www.googletagmanager.com/gtag/js?id=G-
|
|
42
|
+
<script async src="https://www.googletagmanager.com/gtag/js?id=G-FVWC4GKEYS"></script>
|
|
37
43
|
<script>
|
|
38
44
|
window.dataLayer = window.dataLayer || [];
|
|
39
45
|
function gtag(){dataLayer.push(arguments);}
|
|
40
46
|
gtag('js', new Date());
|
|
41
|
-
gtag('config', 'G-
|
|
47
|
+
gtag('config', 'G-FVWC4GKEYS', {
|
|
42
48
|
'allureVersion': '{{allureVersion}}',
|
|
43
|
-
'report':'classic',
|
|
44
49
|
'reportUuid': '{{reportUuid}}',
|
|
45
|
-
'single_file':
|
|
50
|
+
'single_file': {{singleFile}}
|
|
46
51
|
});
|
|
47
52
|
</script>
|
|
48
53
|
{{/if}}
|
|
@@ -51,90 +56,62 @@ const template = `<!DOCTYPE html>
|
|
|
51
56
|
</html>
|
|
52
57
|
`;
|
|
53
58
|
const compiledTemplate = Handlebars.compile(template);
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
const createEmbeddedReportDataScript = (reportFiles) => {
|
|
60
|
+
const reportFilesDeclaration = reportFiles
|
|
61
|
+
.map(({ name, value }) => `d(${JSON.stringify(name)},${JSON.stringify(value)})`)
|
|
62
|
+
.join(",");
|
|
63
|
+
return `
|
|
64
|
+
<script>
|
|
65
|
+
window.reportDataReady = false;
|
|
66
|
+
window.reportData = window.reportData || {};
|
|
67
|
+
|
|
68
|
+
function d(name, value) {
|
|
69
|
+
return new Promise(function (resolve) {
|
|
70
|
+
window.reportData[name] = value;
|
|
71
|
+
resolve(true);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
</script>
|
|
75
|
+
<script>
|
|
76
|
+
Promise.allSettled([${reportFilesDeclaration}]).then(function () {
|
|
77
|
+
window.reportDataReady = true;
|
|
78
|
+
});
|
|
79
|
+
</script>
|
|
80
|
+
`;
|
|
64
81
|
};
|
|
65
|
-
export const
|
|
66
|
-
const {
|
|
67
|
-
|
|
68
|
-
const scriptContentBuffer = await readFile(filePath);
|
|
69
|
-
if (singleFile) {
|
|
70
|
-
return inserter(`data:${mimeType};base64,${scriptContentBuffer.toString("base64")}`);
|
|
71
|
-
}
|
|
72
|
-
await reportFiles.addFile(fileName, scriptContentBuffer);
|
|
73
|
-
return inserter(fileName);
|
|
82
|
+
export const readTemplateManifest = async () => {
|
|
83
|
+
const { manifest } = await readReportStaticAssets(reportStaticArchive);
|
|
84
|
+
return manifest;
|
|
74
85
|
};
|
|
75
86
|
export const generateStaticFiles = async (payload) => {
|
|
76
|
-
const packageRoot = await getPackageRoot();
|
|
77
87
|
const { reportName, reportLanguage, singleFile, reportFiles, reportDataFiles, reportUuid, allureVersion } = payload;
|
|
78
|
-
const
|
|
88
|
+
const staticAssets = await readReportStaticAssets(reportStaticArchive);
|
|
89
|
+
const { manifest } = staticAssets;
|
|
90
|
+
const mainJs = manifest["main.js"];
|
|
91
|
+
const mainCss = manifest["main.css"];
|
|
79
92
|
const headTags = [];
|
|
80
93
|
const bodyTags = [];
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const tag = await readManifestEntry({
|
|
85
|
-
fileName,
|
|
86
|
-
singleFile,
|
|
87
|
-
reportFiles,
|
|
88
|
-
inserter: createFaviconLinkTag,
|
|
89
|
-
mimeType: "image/x-icon",
|
|
90
|
-
packageRoot,
|
|
91
|
-
});
|
|
92
|
-
headTags.push(tag);
|
|
93
|
-
continue;
|
|
94
|
+
if (!singleFile) {
|
|
95
|
+
if (mainCss) {
|
|
96
|
+
headTags.push(createStylesLinkTag(mainCss));
|
|
94
97
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
packageRoot,
|
|
103
|
-
});
|
|
104
|
-
headTags.push(tag);
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
if (key === "main.js") {
|
|
108
|
-
const tag = await readManifestEntry({
|
|
109
|
-
fileName,
|
|
110
|
-
singleFile,
|
|
111
|
-
reportFiles,
|
|
112
|
-
inserter: createScriptTag,
|
|
113
|
-
mimeType: "text/javascript",
|
|
114
|
-
packageRoot,
|
|
115
|
-
});
|
|
116
|
-
bodyTags.push(tag);
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
if (singleFile) {
|
|
120
|
-
continue;
|
|
98
|
+
bodyTags.push(createScriptTag(mainJs));
|
|
99
|
+
await copyReportStaticAssets(staticAssets, reportFiles);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
if (mainCss) {
|
|
103
|
+
const mainCssContent = getReportStaticAsset(staticAssets, mainCss);
|
|
104
|
+
headTags.push(createStylesLinkTag(`data:text/css;base64,${mainCssContent.toString("base64")}`));
|
|
121
105
|
}
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
await reportFiles.addFile(basename(filePath), fileContent);
|
|
106
|
+
const mainJsContent = getReportStaticAsset(staticAssets, mainJs);
|
|
107
|
+
bodyTags.push(createScriptTag(`data:text/javascript;base64,${mainJsContent.toString("base64")}`));
|
|
125
108
|
}
|
|
126
|
-
const reportOptions = {
|
|
127
|
-
reportName: reportName ?? "Allure Report",
|
|
128
|
-
reportLanguage: reportLanguage ?? "en",
|
|
129
|
-
createdAt: Date.now(),
|
|
130
|
-
};
|
|
131
109
|
try {
|
|
132
110
|
const html = compiledTemplate({
|
|
133
111
|
headTags: headTags.join("\n"),
|
|
134
112
|
bodyTags: bodyTags.join("\n"),
|
|
135
|
-
reportFilesScript:
|
|
136
|
-
|
|
137
|
-
analyticsEnable: true,
|
|
113
|
+
reportFilesScript: singleFile ? createEmbeddedReportDataScript(reportDataFiles) : "",
|
|
114
|
+
analyticsEnable: process.env.ALLURE_NO_ANALYTICS?.toLowerCase() !== "true",
|
|
138
115
|
allureVersion,
|
|
139
116
|
reportLanguage,
|
|
140
117
|
reportUuid,
|
|
@@ -198,7 +175,7 @@ export const generateTestResults = async (writer, tests) => {
|
|
|
198
175
|
await writeConcurrently(tests, (test) => writer.writeTestCase(test));
|
|
199
176
|
};
|
|
200
177
|
export const generateSummaryJson = async (writer, reportName, tests) => {
|
|
201
|
-
const statistic =
|
|
178
|
+
const statistic = createStatistic();
|
|
202
179
|
const time = {};
|
|
203
180
|
tests
|
|
204
181
|
.filter((test) => !test.isRetry)
|
|
@@ -235,50 +212,85 @@ export const generateDefaultWidgetData = async (writer, tests, ...fileNames) =>
|
|
|
235
212
|
await writer.writeWidget(fileName, statusChartData);
|
|
236
213
|
}
|
|
237
214
|
};
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
]);
|
|
247
|
-
}
|
|
248
|
-
};
|
|
249
|
-
export const generateTrendData = async (writer, reportName, tests, historyDataPoints) => {
|
|
250
|
-
const statistic = { total: 0 };
|
|
215
|
+
const trendIdentity = (executor) => ({
|
|
216
|
+
buildOrder: executor?.buildOrder,
|
|
217
|
+
reportName: executor?.reportName,
|
|
218
|
+
reportUrl: executor?.reportUrl,
|
|
219
|
+
});
|
|
220
|
+
const prependTrendItem = (current, previous) => [current, ...previous].slice(0, 20);
|
|
221
|
+
export const generateHistoryTrendData = async (writer, reportName, tests, historyDataPoints, legacyHistory = [], executor) => {
|
|
222
|
+
const statistic = createStatistic();
|
|
251
223
|
tests
|
|
252
224
|
.filter((test) => !test.isRetry)
|
|
253
225
|
.forEach((test) => {
|
|
254
226
|
updateStatistic(statistic, test);
|
|
255
227
|
});
|
|
256
|
-
const history =
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
228
|
+
const history = legacyHistory.length
|
|
229
|
+
? legacyHistory.map(({ data, statistic: legacyStatistic, ...item }) => ({
|
|
230
|
+
...item,
|
|
231
|
+
data: createStatistic(data ?? legacyStatistic),
|
|
232
|
+
}))
|
|
233
|
+
: historyDataPoints
|
|
234
|
+
.map((point) => {
|
|
235
|
+
const stat = createStatistic();
|
|
236
|
+
Object.values(point.testResults).forEach((testResult) => {
|
|
237
|
+
updateStatistic(stat, testResult);
|
|
238
|
+
});
|
|
239
|
+
return {
|
|
240
|
+
data: stat,
|
|
241
|
+
reportName: point.name,
|
|
242
|
+
reportUrl: point.url,
|
|
243
|
+
timestamp: point.timestamp,
|
|
244
|
+
};
|
|
245
|
+
})
|
|
246
|
+
.sort((left, right) => right.timestamp - left.timestamp)
|
|
247
|
+
.map(({ timestamp: _timestamp, ...item }, index, values) => ({
|
|
248
|
+
...item,
|
|
249
|
+
buildOrder: values.length - index,
|
|
250
|
+
}));
|
|
251
|
+
const current = {
|
|
252
|
+
data: statistic,
|
|
253
|
+
...(executor
|
|
254
|
+
? trendIdentity(executor)
|
|
255
|
+
: {
|
|
256
|
+
buildOrder: history.length + 1,
|
|
257
|
+
reportName,
|
|
258
|
+
}),
|
|
259
|
+
};
|
|
260
|
+
await writer.writeWidget("history-trend.json", prependTrendItem(current, history));
|
|
261
|
+
};
|
|
262
|
+
export const generateDurationTrendData = async (writer, tests, history = [], executor) => {
|
|
263
|
+
const time = {};
|
|
264
|
+
tests.forEach((test) => updateTime(time, test));
|
|
265
|
+
const current = {
|
|
266
|
+
data: { duration: time.duration ?? 0 },
|
|
267
|
+
...trendIdentity(executor),
|
|
268
|
+
};
|
|
269
|
+
await writer.writeWidget("duration-trend.json", prependTrendItem(current, history));
|
|
270
|
+
};
|
|
271
|
+
export const generateRetryTrendData = async (writer, tests, history = [], executor) => {
|
|
272
|
+
const current = {
|
|
273
|
+
data: {
|
|
274
|
+
run: tests.filter((test) => !test.isRetry).length,
|
|
275
|
+
retry: tests.filter((test) => test.isRetry).length,
|
|
276
|
+
},
|
|
277
|
+
...trendIdentity(executor),
|
|
278
|
+
};
|
|
279
|
+
await writer.writeWidget("retry-trend.json", prependTrendItem(current, history));
|
|
280
|
+
};
|
|
281
|
+
export const generateCategoriesTrendData = async (writer, tests, history = [], executor) => {
|
|
282
|
+
const categories = {};
|
|
283
|
+
tests.forEach((test) => {
|
|
284
|
+
const testCategories = test.extra.categories ?? [];
|
|
285
|
+
testCategories.forEach(({ name }) => {
|
|
286
|
+
categories[name] = (categories[name] ?? 0) + 1;
|
|
260
287
|
});
|
|
261
|
-
return {
|
|
262
|
-
data: stat,
|
|
263
|
-
timestamp: point.timestamp,
|
|
264
|
-
reportName: point.name,
|
|
265
|
-
};
|
|
266
|
-
});
|
|
267
|
-
history
|
|
268
|
-
.sort((a, b) => b.timestamp - a.timestamp)
|
|
269
|
-
.forEach((element, index) => {
|
|
270
|
-
element.buildOrder = history.length - index;
|
|
271
288
|
});
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
reportName: reportName,
|
|
278
|
-
},
|
|
279
|
-
...history,
|
|
280
|
-
];
|
|
281
|
-
await writer.writeWidget("history-trend.json", data);
|
|
289
|
+
const current = {
|
|
290
|
+
data: categories,
|
|
291
|
+
...trendIdentity(executor),
|
|
292
|
+
};
|
|
293
|
+
await writer.writeWidget("categories-trend.json", prependTrendItem(current, history));
|
|
282
294
|
};
|
|
283
295
|
export const generateAttachmentsData = async (writer, attachmentLinks, contentFunction) => {
|
|
284
296
|
const result = new Map();
|
|
@@ -296,3 +308,31 @@ export const generateAttachmentsData = async (writer, attachmentLinks, contentFu
|
|
|
296
308
|
}
|
|
297
309
|
return result;
|
|
298
310
|
};
|
|
311
|
+
export const generateGlobalsData = async (writer, globalErrors, globalAttachments, attachmentMap, attachmentTimestamps = {}, errorTimestamps = []) => {
|
|
312
|
+
const data = {
|
|
313
|
+
errors: globalErrors.map(({ message, trace, actual, expected }, index) => ({
|
|
314
|
+
message,
|
|
315
|
+
trace,
|
|
316
|
+
actual,
|
|
317
|
+
expected,
|
|
318
|
+
timestamp: errorTimestamps[index],
|
|
319
|
+
})),
|
|
320
|
+
attachments: globalAttachments.flatMap((attachment) => {
|
|
321
|
+
const source = attachmentMap.get(attachment.id);
|
|
322
|
+
if (!source) {
|
|
323
|
+
return [];
|
|
324
|
+
}
|
|
325
|
+
return [
|
|
326
|
+
{
|
|
327
|
+
uid: attachment.id,
|
|
328
|
+
name: attachment.name,
|
|
329
|
+
source,
|
|
330
|
+
type: attachment.contentType ?? "application/octet-stream",
|
|
331
|
+
size: !attachment.missed ? attachment.contentLength : undefined,
|
|
332
|
+
timestamp: attachment.originalFileName ? attachmentTimestamps[attachment.originalFileName] : undefined,
|
|
333
|
+
},
|
|
334
|
+
];
|
|
335
|
+
}),
|
|
336
|
+
};
|
|
337
|
+
await writer.writeWidget("globals.json", data);
|
|
338
|
+
};
|
package/dist/model.d.ts
CHANGED
|
@@ -25,6 +25,22 @@ export interface Allure2Attachment {
|
|
|
25
25
|
type?: string;
|
|
26
26
|
size?: number;
|
|
27
27
|
}
|
|
28
|
+
export interface Allure2GlobalError {
|
|
29
|
+
timestamp?: number;
|
|
30
|
+
message?: string;
|
|
31
|
+
trace?: string;
|
|
32
|
+
actual?: string;
|
|
33
|
+
expected?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface Allure2GlobalAttachment extends Allure2Attachment {
|
|
36
|
+
source: string;
|
|
37
|
+
type: string;
|
|
38
|
+
timestamp?: number;
|
|
39
|
+
}
|
|
40
|
+
export interface Allure2GlobalsData {
|
|
41
|
+
errors: Allure2GlobalError[];
|
|
42
|
+
attachments: Allure2GlobalAttachment[];
|
|
43
|
+
}
|
|
28
44
|
export interface Allure2Step {
|
|
29
45
|
name: string;
|
|
30
46
|
time: Allure2Time;
|
|
@@ -60,7 +76,7 @@ export interface Allure2TestResult {
|
|
|
60
76
|
retriesCount: number;
|
|
61
77
|
retriesStatusChange: boolean;
|
|
62
78
|
beforeStages: Allure2StageResult[];
|
|
63
|
-
testStage: Allure2StageResult;
|
|
79
|
+
testStage: Allure2StageResult | null;
|
|
64
80
|
afterStages: Allure2StageResult[];
|
|
65
81
|
labels: Allure2Label[];
|
|
66
82
|
parameters: Allure2Parameter[];
|
|
@@ -113,7 +129,7 @@ export interface Allure2RetryItem {
|
|
|
113
129
|
}
|
|
114
130
|
export interface Allure2HistoryItem {
|
|
115
131
|
uid: string;
|
|
116
|
-
reportUrl
|
|
132
|
+
reportUrl?: string;
|
|
117
133
|
status: Allure2Status;
|
|
118
134
|
statusDetails?: string;
|
|
119
135
|
time: Allure2Time;
|
|
@@ -128,6 +144,25 @@ export interface Allure2HistoryTrendItem {
|
|
|
128
144
|
reportUrl?: string;
|
|
129
145
|
reportName?: string;
|
|
130
146
|
}
|
|
147
|
+
export interface Allure2LegacyHistoryTrendItem extends Omit<Allure2HistoryTrendItem, "data"> {
|
|
148
|
+
data?: Statistic;
|
|
149
|
+
statistic?: Statistic;
|
|
150
|
+
}
|
|
151
|
+
export interface Allure2TrendItem<T extends Record<string, number> = Record<string, number>> {
|
|
152
|
+
data: T;
|
|
153
|
+
buildOrder?: number;
|
|
154
|
+
reportUrl?: string;
|
|
155
|
+
reportName?: string;
|
|
156
|
+
}
|
|
157
|
+
export type Allure2DurationTrendItem = Allure2TrendItem<{
|
|
158
|
+
duration: number;
|
|
159
|
+
}>;
|
|
160
|
+
export type Allure2RetryTrendItem = Allure2TrendItem<{
|
|
161
|
+
run: number;
|
|
162
|
+
retry: number;
|
|
163
|
+
}>;
|
|
164
|
+
export type Allure2CategoriesTrendItem = Allure2TrendItem<Record<string, number>>;
|
|
165
|
+
export type Allure2LegacyHistory = Record<string, Allure2HistoryData>;
|
|
131
166
|
export type Allure2Options = {
|
|
132
167
|
reportName?: string;
|
|
133
168
|
singleFile?: boolean;
|
package/dist/model.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const statisticKeys = ["failed", "broken", "
|
|
1
|
+
export const statisticKeys = ["failed", "broken", "skipped", "passed", "unknown", "total"];
|
|
2
2
|
export const severityValues = ["blocker", "critical", "normal", "minor", "trivial"];
|
package/dist/plugin.js
CHANGED
|
@@ -6,7 +6,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
6
6
|
var _Allure2Plugin_generate;
|
|
7
7
|
import { createPluginSummary, preciseTreeLabels, } from "@allurereport/plugin-api";
|
|
8
8
|
import { convertTestResult } from "./converters.js";
|
|
9
|
-
import { generateAttachmentsData, generateCategoriesData, generateDefaultWidgetData,
|
|
9
|
+
import { generateAttachmentsData, generateCategoriesData, generateCategoriesTrendData, generateDefaultWidgetData, generateDurationTrendData, generateEnvironmentJson, generateExecutorJson, generateGlobalsData, generateHistoryTrendData, generatePackagesData, generateRetryTrendData, generateStaticFiles, generateSummaryJson, generateTestResults, generateTimelineData, generateTree, } from "./generators.js";
|
|
10
10
|
import { InMemoryReportDataWriter, ReportFileDataWriter } from "./writer.js";
|
|
11
11
|
export class Allure2Plugin {
|
|
12
12
|
constructor(options = {}) {
|
|
@@ -16,7 +16,15 @@ export class Allure2Plugin {
|
|
|
16
16
|
const writer = singleFile ? new InMemoryReportDataWriter() : new ReportFileDataWriter(context.reportFiles);
|
|
17
17
|
const attachmentLinks = await store.allAttachments();
|
|
18
18
|
const attachmentMap = await generateAttachmentsData(writer, attachmentLinks, (id) => store.attachmentContentById(id));
|
|
19
|
+
const [globalErrors, globalAttachments] = await Promise.all([
|
|
20
|
+
store.allGlobalErrors(),
|
|
21
|
+
store.allGlobalAttachments(),
|
|
22
|
+
]);
|
|
23
|
+
const globalAttachmentTimestamps = (await store.metadataByKey("allure2_global_attachment_timestamps")) ?? {};
|
|
24
|
+
const globalErrorTimestamps = (await store.metadataByKey("allure2_global_error_timestamps")) ?? [];
|
|
25
|
+
await generateGlobalsData(writer, globalErrors, globalAttachments, attachmentMap, globalAttachmentTimestamps, globalErrorTimestamps);
|
|
19
26
|
const categories = (await store.metadataByKey("allure2_categories")) ?? [];
|
|
27
|
+
const legacyHistory = (await store.metadataByKey("allure2_history")) ?? {};
|
|
20
28
|
const environmentItems = (await store.metadataByKey("allure_environment")) ?? [];
|
|
21
29
|
const tests = await store.allTestResults({ includeRetries: true });
|
|
22
30
|
const related = await store.relatedByTestResultIds(tests.map(({ id }) => id));
|
|
@@ -31,6 +39,7 @@ export class Allure2Plugin {
|
|
|
31
39
|
categories,
|
|
32
40
|
retries,
|
|
33
41
|
history,
|
|
42
|
+
legacyHistory: value.historyId ? legacyHistory[value.historyId] : undefined,
|
|
34
43
|
}, value);
|
|
35
44
|
allTr.push(allure2TestResult);
|
|
36
45
|
}
|
|
@@ -51,10 +60,16 @@ export class Allure2Plugin {
|
|
|
51
60
|
await generateEnvironmentJson(writer, environmentItems);
|
|
52
61
|
const executor = await store.metadataByKey("allure2_executor");
|
|
53
62
|
const historyDataPoints = await store.allHistoryDataPoints();
|
|
63
|
+
const historyTrend = (await store.metadataByKey("allure2_history_trend")) ?? [];
|
|
64
|
+
const durationTrend = (await store.metadataByKey("allure2_duration_trend")) ?? [];
|
|
65
|
+
const retryTrend = (await store.metadataByKey("allure2_retry_trend")) ?? [];
|
|
66
|
+
const categoriesTrend = (await store.metadataByKey("allure2_categories_trend")) ?? [];
|
|
54
67
|
await generateExecutorJson(writer, executor);
|
|
55
68
|
await generateDefaultWidgetData(writer, displayedTr, "duration.json", "status-chart.json", "severity.json");
|
|
56
|
-
await
|
|
57
|
-
await
|
|
69
|
+
await generateHistoryTrendData(writer, reportName, displayedTr, historyDataPoints, historyTrend, executor);
|
|
70
|
+
await generateDurationTrendData(writer, displayedTr, durationTrend, executor);
|
|
71
|
+
await generateRetryTrendData(writer, allTr, retryTrend, executor);
|
|
72
|
+
await generateCategoriesTrendData(writer, allTr, categoriesTrend, executor);
|
|
58
73
|
const reportDataFiles = singleFile ? writer.reportFiles() : [];
|
|
59
74
|
await generateStaticFiles({
|
|
60
75
|
allureVersion: context.allureVersion,
|
|
Binary file
|
package/dist/tree.d.ts
CHANGED
package/dist/tree.js
CHANGED
|
@@ -15,6 +15,7 @@ const createLeaf = (endNode, test) => {
|
|
|
15
15
|
newPassed: test.newPassed,
|
|
16
16
|
retriesCount: test.retriesCount,
|
|
17
17
|
retriesStatusChange: test.retriesStatusChange,
|
|
18
|
+
retry: test.retry,
|
|
18
19
|
parameters: test.parameters.filter((p) => p.value).map((p) => p.value),
|
|
19
20
|
tags: test.extra.tags ?? [],
|
|
20
21
|
};
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Statistic } from "@allurereport/core-api";
|
|
2
2
|
import type { Allure2Status, Allure2TestResult, GroupTime } from "./model.js";
|
|
3
3
|
import type { TreeGroup } from "./tree.js";
|
|
4
|
+
export declare const createStatistic: (source?: Partial<Statistic>) => Statistic;
|
|
4
5
|
export declare const updateStatistic: (statistic: Statistic, test: {
|
|
5
6
|
status: Allure2Status;
|
|
6
7
|
}) => undefined;
|
package/dist/utils.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { statisticKeys } from "./model.js";
|
|
2
|
+
export const createStatistic = (source = {}) => ({
|
|
3
|
+
failed: 0,
|
|
4
|
+
broken: 0,
|
|
5
|
+
skipped: 0,
|
|
6
|
+
passed: 0,
|
|
7
|
+
unknown: 0,
|
|
8
|
+
...source,
|
|
9
|
+
total: source.total ??
|
|
10
|
+
(source.failed ?? 0) + (source.broken ?? 0) + (source.skipped ?? 0) + (source.passed ?? 0) + (source.unknown ?? 0),
|
|
11
|
+
});
|
|
2
12
|
export const updateStatistic = (statistic, test) => {
|
|
3
13
|
statistic[test.status] = (statistic[test.status] ?? 0) + 1;
|
|
4
14
|
statistic.total = (statistic.total ?? 0) + 1;
|
|
@@ -22,7 +32,7 @@ export const updateTime = (time, test) => {
|
|
|
22
32
|
}
|
|
23
33
|
};
|
|
24
34
|
export const calculateStatisticByLeafs = (treeGroup) => {
|
|
25
|
-
const current =
|
|
35
|
+
const current = createStatistic();
|
|
26
36
|
treeGroup.children.forEach((child) => {
|
|
27
37
|
if ("children" in child) {
|
|
28
38
|
const childGroup = child;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/plugin-allure2",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "The
|
|
3
|
+
"version": "3.16.1",
|
|
4
|
+
"description": "The Allure 2-compatible HTML report",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure",
|
|
7
7
|
"html",
|
|
@@ -23,19 +23,19 @@
|
|
|
23
23
|
".": "./dist/index.js"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
|
-
"build": "run clean && tsc --project ./tsconfig.json",
|
|
26
|
+
"build": "run clean && tsc --project ./tsconfig.json && node ../../scripts/pack-report-static.mjs ../web-allure2/dist/multi ./dist/static/report.tar",
|
|
27
27
|
"clean": "rimraf ./dist",
|
|
28
28
|
"test": "rimraf ./out && vitest run",
|
|
29
29
|
"lint": "oxlint --import-plugin src test features stories",
|
|
30
30
|
"lint:fix": "oxlint --import-plugin --fix src test features stories"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@allurereport/core-api": "3.
|
|
34
|
-
"@allurereport/plugin-api": "3.
|
|
35
|
-
"find-up": "^8.0.0",
|
|
33
|
+
"@allurereport/core-api": "3.16.1",
|
|
34
|
+
"@allurereport/plugin-api": "3.16.1",
|
|
36
35
|
"handlebars": "^4.7.9"
|
|
37
36
|
},
|
|
38
37
|
"devDependencies": {
|
|
38
|
+
"@allurereport/web-allure2": "3.16.1",
|
|
39
39
|
"@types/node": "^20",
|
|
40
40
|
"@vitest/runner": "^2",
|
|
41
41
|
"allure-js-commons": "^3",
|