@allurereport/plugin-awesome 3.0.0-beta.8 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -8
- package/dist/converters.d.ts +4 -4
- package/dist/converters.js +4 -0
- package/dist/environments.d.ts +3 -0
- package/dist/environments.js +8 -0
- package/dist/generateTimeline.d.ts +7 -0
- package/dist/generateTimeline.js +40 -0
- package/dist/generators.d.ts +32 -13
- package/dist/generators.js +192 -48
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -2
- package/dist/model.d.ts +17 -8
- package/dist/plugin.d.ts +6 -5
- package/dist/plugin.js +95 -24
- package/dist/writer.d.ts +9 -9
- package/dist/writer.js +14 -10
- package/package.json +9 -8
- package/dist/charts.d.ts +0 -14
- package/dist/charts.js +0 -26
package/README.md
CHANGED
|
@@ -47,11 +47,13 @@ export default defineConfig({
|
|
|
47
47
|
|
|
48
48
|
The plugin accepts the following options:
|
|
49
49
|
|
|
50
|
-
| Option
|
|
51
|
-
|
|
52
|
-
| `reportName`
|
|
53
|
-
| `singleFile`
|
|
54
|
-
| `logo`
|
|
55
|
-
| `theme`
|
|
56
|
-
| `reportLanguage` | Default language of the report
|
|
57
|
-
| `ci`
|
|
50
|
+
| Option | Description | Type | Default |
|
|
51
|
+
|----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------|-------------------------------|
|
|
52
|
+
| `reportName` | Name of the report | `string` | `Allure Report` |
|
|
53
|
+
| `singleFile` | Writes the report as a single `index.html` file | `boolean` | `false` |
|
|
54
|
+
| `logo` | Path to the logo image | `string` | `null` |
|
|
55
|
+
| `theme` | Default color theme of the report | `light \| dark \| auto` | `auto` OS theme |
|
|
56
|
+
| `reportLanguage` | Default language of the report | `string` | OS language |
|
|
57
|
+
| `ci` | CI data which will be rendered in the report | `{ type: "github" \| "jenkins", url: string, name: string }` | `undefined` |
|
|
58
|
+
| `groupBy` | Grouping tests by labels or combining labels. By default, tests are grouped using the `titlePath` provided by the test framework. | `string` | `[]`(Grouping by `titlepath`) |
|
|
59
|
+
| `appendTitlePath`| Special marker for `groupBy`. Forces a final grouping by `titlePath` after all label-based groups. | `boolean` | `false` |
|
package/dist/converters.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TestFixtureResult, TestResult, TestStepResult } from "@allurereport/core-api";
|
|
2
|
-
import type {
|
|
3
|
-
export declare const convertTestResult: (tr: TestResult) =>
|
|
4
|
-
export declare const convertTestStepResult: (tsr: TestStepResult) =>
|
|
5
|
-
export declare const convertFixtureResult: (fr: TestFixtureResult) =>
|
|
2
|
+
import type { AwesomeFixtureResult, AwesomeTestResult, AwesomeTestStepResult } from "@allurereport/web-awesome";
|
|
3
|
+
export declare const convertTestResult: (tr: TestResult) => AwesomeTestResult;
|
|
4
|
+
export declare const convertTestStepResult: (tsr: TestStepResult) => AwesomeTestStepResult;
|
|
5
|
+
export declare const convertFixtureResult: (fr: TestFixtureResult) => AwesomeFixtureResult;
|
package/dist/converters.js
CHANGED
|
@@ -27,12 +27,16 @@ export const convertTestResult = (tr) => {
|
|
|
27
27
|
links: tr.links,
|
|
28
28
|
steps: tr.steps,
|
|
29
29
|
error: tr.error,
|
|
30
|
+
testCase: tr.testCase,
|
|
31
|
+
environment: tr.environment,
|
|
30
32
|
setup: [],
|
|
31
33
|
teardown: [],
|
|
32
34
|
history: [],
|
|
33
35
|
retries: [],
|
|
34
36
|
breadcrumbs: [],
|
|
35
37
|
retry: false,
|
|
38
|
+
transition: tr.transition,
|
|
39
|
+
titlePath: tr.titlePath || [],
|
|
36
40
|
};
|
|
37
41
|
};
|
|
38
42
|
export const convertTestStepResult = (tsr) => {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AllureStore } from "@allurereport/plugin-api";
|
|
2
|
+
import type { AwesomeOptions } from "./model.js";
|
|
3
|
+
type Writer = {
|
|
4
|
+
writeWidget(fileName: string, data: any): Promise<void>;
|
|
5
|
+
};
|
|
6
|
+
export declare const generateTimeline: (writer: Writer, store: AllureStore, options: AwesomeOptions) => Promise<void>;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { hasLabels } from "@allurereport/web-commons";
|
|
2
|
+
const DEFAULT_MIN_DURATION = 1;
|
|
3
|
+
const HOST_LABEL = "host";
|
|
4
|
+
const THREAD_LABEL = "thread";
|
|
5
|
+
const DEFAULT_TIMELINE_OPTIONS = {
|
|
6
|
+
minDuration: DEFAULT_MIN_DURATION,
|
|
7
|
+
};
|
|
8
|
+
export const generateTimeline = async (writer, store, options) => {
|
|
9
|
+
const { timeline = DEFAULT_TIMELINE_OPTIONS } = options;
|
|
10
|
+
const { minDuration = DEFAULT_MIN_DURATION } = timeline;
|
|
11
|
+
const testResults = await store.allTestResults({ includeHidden: true });
|
|
12
|
+
const result = [];
|
|
13
|
+
for (const test of testResults) {
|
|
14
|
+
const hasStart = Number.isInteger(test.start);
|
|
15
|
+
const hasStop = Number.isInteger(test.stop);
|
|
16
|
+
if (!hasStart || !hasStop) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
const duration = test.duration ?? test.stop - test.start;
|
|
20
|
+
if (duration < minDuration) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (!hasLabels(test, [HOST_LABEL, THREAD_LABEL])) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
result.push({
|
|
27
|
+
id: test.id,
|
|
28
|
+
historyId: test.historyId,
|
|
29
|
+
name: test.name,
|
|
30
|
+
status: test.status,
|
|
31
|
+
hidden: test.hidden,
|
|
32
|
+
labels: test.labels,
|
|
33
|
+
environment: test.environment,
|
|
34
|
+
start: test.start,
|
|
35
|
+
stop: test.stop,
|
|
36
|
+
duration,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
await writer.writeWidget("timeline.json", result);
|
|
40
|
+
};
|
package/dist/generators.d.ts
CHANGED
|
@@ -1,20 +1,39 @@
|
|
|
1
|
-
import { type AttachmentLink, type EnvironmentItem, type Statistic } from "@allurereport/core-api";
|
|
2
|
-
import {
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
1
|
+
import { type AttachmentLink, type EnvironmentItem, type Statistic, type TestEnvGroup, type TestError, type TestResult } from "@allurereport/core-api";
|
|
2
|
+
import type { AllureStore, ExitCode, PluginContext, QualityGateValidationResult, ReportFiles, ResultFile, TestResultFilter } from "@allurereport/plugin-api";
|
|
3
|
+
import type { AwesomeTestResult } from "@allurereport/web-awesome";
|
|
4
|
+
import type { AwesomeOptions, TemplateManifest } from "./model.js";
|
|
5
|
+
import type { AwesomeDataWriter, ReportFile } from "./writer.js";
|
|
6
6
|
export declare const readTemplateManifest: (singleFileMode?: boolean) => Promise<TemplateManifest>;
|
|
7
|
-
export declare const generateTestResults: (writer:
|
|
8
|
-
export declare const
|
|
9
|
-
export declare const
|
|
10
|
-
export declare const
|
|
11
|
-
export declare const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
export declare const
|
|
7
|
+
export declare const generateTestResults: (writer: AwesomeDataWriter, store: AllureStore, trs: TestResult[], filter?: TestResultFilter) => Promise<AwesomeTestResult[]>;
|
|
8
|
+
export declare const generateTestCases: (writer: AwesomeDataWriter, trs: AwesomeTestResult[]) => Promise<void>;
|
|
9
|
+
export declare const generateTestEnvGroups: (writer: AwesomeDataWriter, groups: TestEnvGroup[]) => Promise<void>;
|
|
10
|
+
export declare const generateNav: (writer: AwesomeDataWriter, trs: AwesomeTestResult[], filename?: string) => Promise<void>;
|
|
11
|
+
export declare const generateTree: (writer: AwesomeDataWriter, treeFilename: string, labels: string[], tests: AwesomeTestResult[], options?: {
|
|
12
|
+
appendTitlePath?: boolean;
|
|
13
|
+
}) => Promise<void>;
|
|
14
|
+
export declare const generateEnvironmentJson: (writer: AwesomeDataWriter, env: EnvironmentItem[]) => Promise<void>;
|
|
15
|
+
export declare const generateEnvirontmentsList: (writer: AwesomeDataWriter, store: AllureStore) => Promise<void>;
|
|
16
|
+
export declare const generateVariables: (writer: AwesomeDataWriter, store: AllureStore) => Promise<void>;
|
|
17
|
+
export declare const generateStatistic: (writer: AwesomeDataWriter, data: {
|
|
18
|
+
stats: Statistic;
|
|
19
|
+
statsByEnv: Map<string, Statistic>;
|
|
20
|
+
envs: string[];
|
|
21
|
+
}) => Promise<void>;
|
|
22
|
+
export declare const generateAttachmentsFiles: (writer: AwesomeDataWriter, attachmentLinks: AttachmentLink[], contentFunction: (id: string) => Promise<ResultFile | undefined>) => Promise<Map<string, string> | undefined>;
|
|
23
|
+
export declare const generateHistoryDataPoints: (writer: AwesomeDataWriter, store: AllureStore) => Promise<Map<string, string>>;
|
|
24
|
+
export declare const generateGlobals: (writer: AwesomeDataWriter, payload: {
|
|
25
|
+
globalExitCode?: ExitCode;
|
|
26
|
+
globalAttachments?: AttachmentLink[];
|
|
27
|
+
globalErrors?: TestError[];
|
|
28
|
+
contentFunction: (id: string) => Promise<ResultFile | undefined>;
|
|
29
|
+
}) => Promise<void>;
|
|
30
|
+
export declare const generateQualityGateResults: (writer: AwesomeDataWriter, qualityGateResults?: QualityGateValidationResult[]) => Promise<void>;
|
|
31
|
+
export declare const generateStaticFiles: (payload: AwesomeOptions & {
|
|
32
|
+
id: string;
|
|
15
33
|
allureVersion: string;
|
|
16
34
|
reportFiles: ReportFiles;
|
|
17
35
|
reportDataFiles: ReportFile[];
|
|
18
36
|
reportUuid: string;
|
|
19
37
|
reportName: string;
|
|
20
38
|
}) => Promise<void>;
|
|
39
|
+
export declare const generateAllCharts: (writer: AwesomeDataWriter, store: AllureStore, options: AwesomeOptions, context: PluginContext) => Promise<void>;
|
package/dist/generators.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { createTreeByLabels, sortTree, transformTree } from "@allurereport/plugin-api";
|
|
4
|
-
import {
|
|
1
|
+
import { defaultChartsConfig } from "@allurereport/charts-api";
|
|
2
|
+
import { compareBy, createBaseUrlScript, createFontLinkTag, createReportDataScript, createScriptTag, createStylesLinkTag, incrementStatistic, nullsLast, ordinal, } from "@allurereport/core-api";
|
|
3
|
+
import { createTreeByLabels, createTreeByLabelsAndTitlePath, createTreeByTitlePath, filterTree, preciseTreeLabels, sortTree, transformTree, } from "@allurereport/plugin-api";
|
|
4
|
+
import { generateCharts, getPieChartValues } from "@allurereport/web-commons";
|
|
5
5
|
import Handlebars from "handlebars";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
6
7
|
import { readFile } from "node:fs/promises";
|
|
7
8
|
import { createRequire } from "node:module";
|
|
8
9
|
import { basename, join } from "node:path";
|
|
9
|
-
import { getChartData } from "./charts.js";
|
|
10
10
|
import { convertFixtureResult, convertTestResult } from "./converters.js";
|
|
11
11
|
const require = createRequire(import.meta.url);
|
|
12
12
|
const template = `<!DOCTYPE html>
|
|
@@ -14,7 +14,7 @@ const template = `<!DOCTYPE html>
|
|
|
14
14
|
<head>
|
|
15
15
|
<meta charset="utf-8">
|
|
16
16
|
<title> {{ reportName }} </title>
|
|
17
|
-
<link rel="icon" href="
|
|
17
|
+
<link rel="icon" href="data:image/svg+xml,%3Csvg width='32' height='32' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M22.232 4.662a3.6 3.6 0 0 1 5.09.035c2.855 2.894 4.662 6.885 4.662 11.295a3.6 3.6 0 0 1-7.2 0c0-2.406-.981-4.61-2.587-6.24a3.6 3.6 0 0 1 .035-5.09Z' fill='url(%23a)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M12.392 3.6a3.6 3.6 0 0 1 3.6-3.6c4.41 0 8.401 1.807 11.296 4.662a3.6 3.6 0 1 1-5.056 5.126C20.602 8.18 18.398 7.2 15.992 7.2a3.6 3.6 0 0 1-3.6-3.6Z' fill='url(%23b)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 15.992C0 7.157 7.157 0 15.992 0a3.6 3.6 0 0 1 0 7.2A8.789 8.789 0 0 0 7.2 15.992c0 2.406.981 4.61 2.588 6.24a3.6 3.6 0 0 1-5.126 5.056C1.807 24.393 0 20.402 0 15.992Z' fill='url(%23c)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4.661 22.232a3.6 3.6 0 0 1 5.091-.035c1.63 1.606 3.834 2.587 6.24 2.587a3.6 3.6 0 0 1 0 7.2c-4.41 0-8.401-1.807-11.295-4.661a3.6 3.6 0 0 1-.036-5.091Z' fill='url(%23d)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M28.384 12.392a3.6 3.6 0 0 1 3.6 3.6c0 8.835-7.157 15.992-15.992 15.992a3.6 3.6 0 0 1 0-7.2 8.789 8.789 0 0 0 8.792-8.792 3.6 3.6 0 0 1 3.6-3.6Z' fill='url(%23e)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M28.385 12.392a3.6 3.6 0 0 1 3.6 3.6v12.392a3.6 3.6 0 0 1-7.2 0V15.992a3.6 3.6 0 0 1 3.6-3.6Z' fill='url(%23f)'/%3E%3Cg clip-path='url(%23g)'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M22.232 4.662a3.6 3.6 0 0 1 5.091.035c2.855 2.894 4.662 6.885 4.662 11.295a3.6 3.6 0 0 1-7.2 0c0-2.406-.982-4.61-2.588-6.24a3.6 3.6 0 0 1 .035-5.09Z' fill='url(%23h)'/%3E%3C/g%3E%3Cdefs%3E%3ClinearGradient id='a' x1='26.4' y1='9.6' x2='28.8' y2='15' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%237E22CE'/%3E%3Cstop offset='1' stop-color='%238B5CF6'/%3E%3C/linearGradient%3E%3ClinearGradient id='b' x1='26.8' y1='9.4' x2='17.8' y2='3.6' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23EF4444'/%3E%3Cstop offset='1' stop-color='%23DC2626'/%3E%3C/linearGradient%3E%3ClinearGradient id='c' x1='3.6' y1='14' x2='5.4' y2='24.8' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%2322C55E'/%3E%3Cstop offset='1' stop-color='%2315803D'/%3E%3C/linearGradient%3E%3ClinearGradient id='d' x1='4.8' y1='22.2' x2='14.4' y2='29.2' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%2394A3B8'/%3E%3Cstop offset='.958' stop-color='%2364748B'/%3E%3Cstop offset='1' stop-color='%2364748B'/%3E%3C/linearGradient%3E%3ClinearGradient id='e' x1='28.4' y1='22.173' x2='22.188' y2='28.384' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23D97706'/%3E%3Cstop offset='1' stop-color='%23FBBF24'/%3E%3C/linearGradient%3E%3ClinearGradient id='f' x1='29.2' y1='54.4' x2='30.626' y2='54.256' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23FBBF24'/%3E%3Cstop offset='1' stop-color='%23FBBF24'/%3E%3C/linearGradient%3E%3ClinearGradient id='h' x1='26.4' y1='9.6' x2='28.8' y2='15' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%237E22CE'/%3E%3Cstop offset='1' stop-color='%238B5CF6'/%3E%3C/linearGradient%3E%3CclipPath id='g'%3E%3Cpath fill='%23fff' transform='translate(24.8 12)' d='M0 0h7.2v8H0z'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E" />
|
|
18
18
|
{{{ headTags }}}
|
|
19
19
|
</head>
|
|
20
20
|
<body>
|
|
@@ -73,16 +73,17 @@ const createBreadcrumbs = (convertedTr) => {
|
|
|
73
73
|
return acc;
|
|
74
74
|
}, []);
|
|
75
75
|
};
|
|
76
|
-
export const generateTestResults = async (writer, store) => {
|
|
77
|
-
const allTr =
|
|
76
|
+
export const generateTestResults = async (writer, store, trs, filter) => {
|
|
77
|
+
const allTr = trs.filter((tr) => (filter ? filter(tr) : true));
|
|
78
78
|
let convertedTrs = [];
|
|
79
79
|
for (const tr of allTr) {
|
|
80
80
|
const trFixtures = await store.fixturesByTrId(tr.id);
|
|
81
81
|
const convertedTrFixtures = trFixtures.map(convertFixtureResult);
|
|
82
82
|
const convertedTr = convertTestResult(tr);
|
|
83
|
-
convertedTr.history = await store.historyByTrId(tr.id);
|
|
83
|
+
convertedTr.history = (await store.historyByTrId(tr.id)) ?? [];
|
|
84
84
|
convertedTr.retries = await store.retriesByTrId(tr.id);
|
|
85
|
-
convertedTr.
|
|
85
|
+
convertedTr.retriesCount = convertedTr.retries.length;
|
|
86
|
+
convertedTr.retry = convertedTr.retriesCount > 0;
|
|
86
87
|
convertedTr.setup = convertedTrFixtures.filter((f) => f.type === "before");
|
|
87
88
|
convertedTr.teardown = convertedTrFixtures.filter((f) => f.type === "after");
|
|
88
89
|
convertedTr.attachments = (await store.attachmentsByTrId(tr.id)).map((attachment) => ({
|
|
@@ -99,38 +100,133 @@ export const generateTestResults = async (writer, store) => {
|
|
|
99
100
|
for (const convertedTr of convertedTrs) {
|
|
100
101
|
await writer.writeTestCase(convertedTr);
|
|
101
102
|
}
|
|
102
|
-
await writer.writeWidget("nav.json", convertedTrs.filter(({ hidden }) => !hidden).map(({ id }) => id));
|
|
103
103
|
return convertedTrs;
|
|
104
104
|
};
|
|
105
|
-
export const
|
|
105
|
+
export const generateTestCases = async (writer, trs) => {
|
|
106
|
+
for (const tr of trs) {
|
|
107
|
+
await writer.writeTestCase(tr);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
export const generateTestEnvGroups = async (writer, groups) => {
|
|
111
|
+
for (const group of groups) {
|
|
112
|
+
const src = join("test-env-groups", `${group.id}.json`);
|
|
113
|
+
await writer.writeData(src, group);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
export const generateNav = async (writer, trs, filename = "nav.json") => {
|
|
117
|
+
await writer.writeWidget(filename, trs.filter(({ hidden }) => !hidden).map(({ id }) => id));
|
|
118
|
+
};
|
|
119
|
+
export const generateTree = async (writer, treeFilename, labels, tests, options) => {
|
|
106
120
|
const visibleTests = tests.filter((test) => !test.hidden);
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
incrementStatistic(group.statistic, leaf.status);
|
|
119
|
-
});
|
|
121
|
+
const { appendTitlePath } = options || {};
|
|
122
|
+
let tree;
|
|
123
|
+
if (labels.length === 0) {
|
|
124
|
+
tree = buildTreeByTitlePath(visibleTests);
|
|
125
|
+
}
|
|
126
|
+
else if (appendTitlePath && labels.length) {
|
|
127
|
+
tree = buildTreeByLabelsAndTitlePathCombined(visibleTests, labels);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
tree = buildTreeByLabels(visibleTests, labels);
|
|
131
|
+
}
|
|
120
132
|
filterTree(tree, (leaf) => !leaf.hidden);
|
|
121
133
|
sortTree(tree, nullsLast(compareBy("start", ordinal())));
|
|
122
134
|
transformTree(tree, (leaf, idx) => ({ ...leaf, groupOrder: idx + 1 }));
|
|
123
|
-
await writer.writeWidget(
|
|
135
|
+
await writer.writeWidget(treeFilename, tree);
|
|
136
|
+
};
|
|
137
|
+
const buildTreeByLabels = (tests, labels) => {
|
|
138
|
+
return createTreeByLabels(tests, labels, leafFactory, undefined, (group, leaf) => incrementStatistic(group.statistic, leaf.status));
|
|
139
|
+
};
|
|
140
|
+
const buildTreeByTitlePath = (tests) => {
|
|
141
|
+
const testsWithTitlePath = [];
|
|
142
|
+
const testsWithoutTitlePath = [];
|
|
143
|
+
for (const test of tests) {
|
|
144
|
+
if (Array.isArray(test.titlePath) && test.titlePath.length > 0) {
|
|
145
|
+
testsWithTitlePath.push(test);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
testsWithoutTitlePath.push(test);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const treeByTitlePath = createTreeByTitlePath(testsWithTitlePath, leafFactory, undefined, (group, leaf) => incrementStatistic(group.statistic, leaf.status));
|
|
152
|
+
if (!testsWithoutTitlePath.length) {
|
|
153
|
+
return treeByTitlePath;
|
|
154
|
+
}
|
|
155
|
+
const defaultLabels = preciseTreeLabels(["parentSuite", "suite", "subSuite"], testsWithoutTitlePath, ({ labels }) => labels.map(({ name }) => name));
|
|
156
|
+
let treeByDefaultLabels = null;
|
|
157
|
+
if (defaultLabels.length) {
|
|
158
|
+
treeByDefaultLabels = createTreeByLabelsAndTitlePath(testsWithoutTitlePath, defaultLabels, leafFactory, undefined, (group, leaf) => incrementStatistic(group.statistic, leaf.status));
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
for (const test of testsWithoutTitlePath) {
|
|
162
|
+
const leaf = leafFactory(test);
|
|
163
|
+
treeByTitlePath.leavesById[leaf.nodeId] = leaf;
|
|
164
|
+
if (!treeByTitlePath.root.leaves) {
|
|
165
|
+
treeByTitlePath.root.leaves = [];
|
|
166
|
+
}
|
|
167
|
+
treeByTitlePath.root.leaves.push(leaf.nodeId);
|
|
168
|
+
}
|
|
169
|
+
return treeByTitlePath;
|
|
170
|
+
}
|
|
171
|
+
const mergedLeavesById = {
|
|
172
|
+
...treeByTitlePath.leavesById,
|
|
173
|
+
...treeByDefaultLabels.leavesById,
|
|
174
|
+
};
|
|
175
|
+
const mergedGroupsById = {
|
|
176
|
+
...treeByTitlePath.groupsById,
|
|
177
|
+
...treeByDefaultLabels.groupsById,
|
|
178
|
+
};
|
|
179
|
+
const mergedRootLeaves = Array.from(new Set([...(treeByTitlePath.root.leaves ?? []), ...(treeByDefaultLabels.root.leaves ?? [])]));
|
|
180
|
+
const mergedRootGroups = Array.from(new Set([...(treeByTitlePath.root.groups ?? []), ...(treeByDefaultLabels.root.groups ?? [])]));
|
|
181
|
+
return {
|
|
182
|
+
root: {
|
|
183
|
+
leaves: mergedRootLeaves,
|
|
184
|
+
groups: mergedRootGroups,
|
|
185
|
+
},
|
|
186
|
+
leavesById: mergedLeavesById,
|
|
187
|
+
groupsById: mergedGroupsById,
|
|
188
|
+
};
|
|
124
189
|
};
|
|
190
|
+
const buildTreeByLabelsAndTitlePathCombined = (tests, labels) => createTreeByLabelsAndTitlePath(tests, labels, leafFactory, undefined, (group, leaf) => incrementStatistic(group.statistic, leaf.status));
|
|
191
|
+
const leafFactory = ({ id, name, status, duration, flaky, start, transition, retry, retriesCount, }) => ({
|
|
192
|
+
nodeId: id,
|
|
193
|
+
name,
|
|
194
|
+
status,
|
|
195
|
+
duration,
|
|
196
|
+
flaky,
|
|
197
|
+
start,
|
|
198
|
+
retry,
|
|
199
|
+
retriesCount,
|
|
200
|
+
transition,
|
|
201
|
+
});
|
|
125
202
|
export const generateEnvironmentJson = async (writer, env) => {
|
|
126
203
|
await writer.writeWidget("allure_environment.json", env);
|
|
127
204
|
};
|
|
128
|
-
export const
|
|
129
|
-
await
|
|
205
|
+
export const generateEnvirontmentsList = async (writer, store) => {
|
|
206
|
+
const environments = await store.allEnvironments();
|
|
207
|
+
await writer.writeWidget("environments.json", environments);
|
|
130
208
|
};
|
|
131
|
-
export const
|
|
132
|
-
const
|
|
133
|
-
await
|
|
209
|
+
export const generateVariables = async (writer, store) => {
|
|
210
|
+
const reportVariables = await store.allVariables();
|
|
211
|
+
const environments = await store.allEnvironments();
|
|
212
|
+
await writer.writeWidget("variables.json", reportVariables);
|
|
213
|
+
for (const env of environments) {
|
|
214
|
+
const envVariables = await store.envVariables(env);
|
|
215
|
+
await writer.writeWidget(join(env, "variables.json"), envVariables);
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
export const generateStatistic = async (writer, data) => {
|
|
219
|
+
const { stats, statsByEnv, envs } = data;
|
|
220
|
+
await writer.writeWidget("statistic.json", stats);
|
|
221
|
+
await writer.writeWidget("pie_chart.json", getPieChartValues(stats));
|
|
222
|
+
for (const env of envs) {
|
|
223
|
+
const envStats = statsByEnv.get(env);
|
|
224
|
+
if (!envStats) {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
await writer.writeWidget(join(env, "statistic.json"), envStats);
|
|
228
|
+
await writer.writeWidget(join(env, "pie_chart.json"), envStats);
|
|
229
|
+
}
|
|
134
230
|
};
|
|
135
231
|
export const generateAttachmentsFiles = async (writer, attachmentLinks, contentFunction) => {
|
|
136
232
|
const result = new Map();
|
|
@@ -157,12 +253,36 @@ export const generateHistoryDataPoints = async (writer, store) => {
|
|
|
157
253
|
}
|
|
158
254
|
return result;
|
|
159
255
|
};
|
|
256
|
+
export const generateGlobals = async (writer, payload) => {
|
|
257
|
+
const { globalExitCode, globalAttachments = [], globalErrors = [], contentFunction } = payload;
|
|
258
|
+
const globals = {
|
|
259
|
+
errors: globalErrors,
|
|
260
|
+
attachments: [],
|
|
261
|
+
};
|
|
262
|
+
if (globalExitCode) {
|
|
263
|
+
globals.exitCode = globalExitCode;
|
|
264
|
+
}
|
|
265
|
+
for (const attachment of globalAttachments) {
|
|
266
|
+
const src = `${attachment.id}${attachment.ext}`;
|
|
267
|
+
const content = await contentFunction(attachment.id);
|
|
268
|
+
if (!content) {
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
await writer.writeAttachment(src, content);
|
|
272
|
+
globals.attachments.push(attachment);
|
|
273
|
+
}
|
|
274
|
+
await writer.writeWidget("globals.json", globals);
|
|
275
|
+
};
|
|
276
|
+
export const generateQualityGateResults = async (writer, qualityGateResults = []) => {
|
|
277
|
+
await writer.writeWidget("quality-gate.json", qualityGateResults);
|
|
278
|
+
};
|
|
160
279
|
export const generateStaticFiles = async (payload) => {
|
|
161
|
-
const { reportName = "Allure Report", reportLanguage = "en", singleFile, logo = "", theme = "
|
|
280
|
+
const { id, reportName = "Allure Report", reportLanguage = "en", singleFile, logo = "", theme = "auto", groupBy, reportFiles, reportDataFiles, reportUuid, allureVersion, layout = "base", defaultSection = "", ci, } = payload;
|
|
162
281
|
const compile = Handlebars.compile(template);
|
|
163
282
|
const manifest = await readTemplateManifest(payload.singleFile);
|
|
164
283
|
const headTags = [];
|
|
165
284
|
const bodyTags = [];
|
|
285
|
+
const sections = ["charts", "timeline"];
|
|
166
286
|
if (!payload.singleFile) {
|
|
167
287
|
for (const key in manifest) {
|
|
168
288
|
const fileName = manifest[key];
|
|
@@ -186,28 +306,52 @@ export const generateStaticFiles = async (payload) => {
|
|
|
186
306
|
else {
|
|
187
307
|
const mainJs = manifest["main.js"];
|
|
188
308
|
const mainJsSource = require.resolve(`@allurereport/web-awesome/dist/single/${mainJs}`);
|
|
189
|
-
const
|
|
190
|
-
bodyTags.push(createScriptTag(`data:text/javascript;base64,${
|
|
309
|
+
const mainJsContent = await readFile(mainJsSource);
|
|
310
|
+
bodyTags.push(createScriptTag(`data:text/javascript;base64,${mainJsContent.toString("base64")}`));
|
|
191
311
|
}
|
|
312
|
+
const now = Date.now();
|
|
192
313
|
const reportOptions = {
|
|
314
|
+
id,
|
|
193
315
|
reportName,
|
|
194
316
|
logo,
|
|
195
317
|
theme,
|
|
196
318
|
reportLanguage,
|
|
197
|
-
createdAt:
|
|
319
|
+
createdAt: now,
|
|
198
320
|
reportUuid,
|
|
199
|
-
groupBy: groupBy?.length ? groupBy : [
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
bodyTags: bodyTags.join("\n"),
|
|
204
|
-
reportFilesScript: createReportDataScript(reportDataFiles),
|
|
205
|
-
reportOptions: JSON.stringify(reportOptions),
|
|
206
|
-
analyticsEnable: true,
|
|
321
|
+
groupBy: groupBy?.length ? groupBy : [],
|
|
322
|
+
cacheKey: now.toString(),
|
|
323
|
+
ci,
|
|
324
|
+
layout,
|
|
207
325
|
allureVersion,
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
326
|
+
sections,
|
|
327
|
+
defaultSection,
|
|
328
|
+
};
|
|
329
|
+
try {
|
|
330
|
+
const html = compile({
|
|
331
|
+
headTags: headTags.join("\n"),
|
|
332
|
+
bodyTags: bodyTags.join("\n"),
|
|
333
|
+
reportFilesScript: createReportDataScript(reportDataFiles),
|
|
334
|
+
reportOptions: JSON.stringify(reportOptions),
|
|
335
|
+
analyticsEnable: true,
|
|
336
|
+
allureVersion,
|
|
337
|
+
reportUuid,
|
|
338
|
+
reportName,
|
|
339
|
+
singleFile: payload.singleFile,
|
|
340
|
+
});
|
|
341
|
+
await reportFiles.addFile("index.html", Buffer.from(html, "utf8"));
|
|
342
|
+
}
|
|
343
|
+
catch (err) {
|
|
344
|
+
if (err instanceof RangeError) {
|
|
345
|
+
console.error("The report is too large to be generated in the single file mode!");
|
|
346
|
+
process.exit(1);
|
|
347
|
+
}
|
|
348
|
+
throw err;
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
export const generateAllCharts = async (writer, store, options, context) => {
|
|
352
|
+
const { charts = defaultChartsConfig } = options;
|
|
353
|
+
const generatedChartsData = await generateCharts(charts, store, context.reportName, randomUUID);
|
|
354
|
+
if (Object.keys(generatedChartsData.general).length > 0) {
|
|
355
|
+
await writer.writeWidget("charts.json", generatedChartsData);
|
|
356
|
+
}
|
|
213
357
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export default
|
|
1
|
+
export type { AwesomePluginOptions } from "./model.js";
|
|
2
|
+
export { AwesomePlugin as default } from "./plugin.js";
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export default AllureAwesomePlugin;
|
|
1
|
+
export { AwesomePlugin as default } from "./plugin.js";
|
package/dist/model.d.ts
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ChartOptions } from "@allurereport/charts-api";
|
|
2
|
+
import type { CiDescriptor, EnvironmentsConfig, TestResult } from "@allurereport/core-api";
|
|
3
|
+
export type AwesomeOptions = {
|
|
2
4
|
reportName?: string;
|
|
3
5
|
singleFile?: boolean;
|
|
4
6
|
logo?: string;
|
|
5
|
-
theme?: "light" | "dark";
|
|
6
|
-
reportLanguage?: "en"
|
|
7
|
+
theme?: "light" | "dark" | "auto";
|
|
8
|
+
reportLanguage?: "en";
|
|
7
9
|
groupBy?: string[];
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
layout?: "base" | "split";
|
|
11
|
+
environments?: Record<string, EnvironmentsConfig>;
|
|
12
|
+
ci?: CiDescriptor;
|
|
13
|
+
filter?: (testResult: TestResult) => boolean;
|
|
14
|
+
charts?: ChartOptions[];
|
|
15
|
+
timeline?: {
|
|
16
|
+
minDuration?: number;
|
|
12
17
|
};
|
|
18
|
+
sections?: string[];
|
|
19
|
+
defaultSection?: string;
|
|
20
|
+
publish?: boolean;
|
|
21
|
+
appendTitlePath?: boolean;
|
|
13
22
|
};
|
|
14
23
|
export type TemplateManifest = Record<string, string>;
|
|
15
|
-
export type
|
|
24
|
+
export type AwesomePluginOptions = AwesomeOptions;
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type {
|
|
3
|
-
export declare class
|
|
1
|
+
import { type AllureStore, type Plugin, type PluginContext, type PluginSummary } from "@allurereport/plugin-api";
|
|
2
|
+
import type { AwesomePluginOptions } from "./model.js";
|
|
3
|
+
export declare class AwesomePlugin implements Plugin {
|
|
4
4
|
#private;
|
|
5
|
-
readonly options:
|
|
6
|
-
constructor(options?:
|
|
5
|
+
readonly options: AwesomePluginOptions;
|
|
6
|
+
constructor(options?: AwesomePluginOptions);
|
|
7
7
|
start: (context: PluginContext) => Promise<void>;
|
|
8
8
|
update: (context: PluginContext, store: AllureStore) => Promise<void>;
|
|
9
9
|
done: (context: PluginContext, store: AllureStore) => Promise<void>;
|
|
10
|
+
info(context: PluginContext, store: AllureStore): Promise<PluginSummary>;
|
|
10
11
|
}
|
package/dist/plugin.js
CHANGED
|
@@ -9,62 +9,133 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
10
10
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
11
|
};
|
|
12
|
-
var
|
|
12
|
+
var _AwesomePlugin_writer, _AwesomePlugin_generate;
|
|
13
|
+
import { getWorstStatus } from "@allurereport/core-api";
|
|
14
|
+
import { convertToSummaryTestResult, } from "@allurereport/plugin-api";
|
|
13
15
|
import { preciseTreeLabels } from "@allurereport/plugin-api";
|
|
14
|
-
import {
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { filterEnv } from "./environments.js";
|
|
18
|
+
import { generateTimeline } from "./generateTimeline.js";
|
|
19
|
+
import { generateAllCharts, generateAttachmentsFiles, generateEnvironmentJson, generateEnvirontmentsList, generateGlobals, generateHistoryDataPoints, generateNav, generateQualityGateResults, generateStaticFiles, generateStatistic, generateTestCases, generateTestEnvGroups, generateTestResults, generateTree, generateVariables, } from "./generators.js";
|
|
15
20
|
import { InMemoryReportDataWriter, ReportFileDataWriter } from "./writer.js";
|
|
16
|
-
export class
|
|
21
|
+
export class AwesomePlugin {
|
|
17
22
|
constructor(options = {}) {
|
|
18
23
|
this.options = options;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const { singleFile, groupBy = [] } = this.options ?? {};
|
|
24
|
+
_AwesomePlugin_writer.set(this, void 0);
|
|
25
|
+
_AwesomePlugin_generate.set(this, async (context, store) => {
|
|
26
|
+
const { singleFile, groupBy = [], filter, appendTitlePath } = this.options ?? {};
|
|
22
27
|
const environmentItems = await store.metadataByKey("allure_environment");
|
|
23
|
-
const
|
|
28
|
+
const reportEnvironments = await store.allEnvironments();
|
|
24
29
|
const attachments = await store.allAttachments();
|
|
25
|
-
await
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
const allTrs = await store.allTestResults({ includeHidden: true });
|
|
31
|
+
const statistics = await store.testsStatistic(filter);
|
|
32
|
+
const environments = await store.allEnvironments();
|
|
33
|
+
const envStatistics = new Map();
|
|
34
|
+
const allTestEnvGroups = await store.allTestEnvGroups();
|
|
35
|
+
const globalAttachments = await store.allGlobalAttachments();
|
|
36
|
+
const globalExitCode = await store.globalExitCode();
|
|
37
|
+
const globalErrors = await store.allGlobalErrors();
|
|
38
|
+
const qualityGateResults = await store.qualityGateResults();
|
|
39
|
+
for (const env of environments) {
|
|
40
|
+
envStatistics.set(env, await store.testsStatistic(filterEnv(env, filter)));
|
|
41
|
+
}
|
|
42
|
+
await generateStatistic(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), {
|
|
43
|
+
stats: statistics,
|
|
44
|
+
statsByEnv: envStatistics,
|
|
45
|
+
envs: environments,
|
|
46
|
+
});
|
|
47
|
+
await generateAllCharts(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), store, this.options, context);
|
|
48
|
+
await generateTimeline(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), store, this.options);
|
|
49
|
+
const convertedTrs = await generateTestResults(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), store, allTrs, this.options.filter);
|
|
50
|
+
const hasGroupBy = groupBy.length > 0;
|
|
51
|
+
const treeLabels = hasGroupBy
|
|
52
|
+
? preciseTreeLabels(groupBy, convertedTrs, ({ labels }) => labels.map(({ name }) => name))
|
|
53
|
+
: [];
|
|
54
|
+
await generateHistoryDataPoints(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), store);
|
|
55
|
+
await generateTestCases(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), convertedTrs);
|
|
56
|
+
await generateTree(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), "tree.json", treeLabels, convertedTrs, { appendTitlePath });
|
|
57
|
+
await generateNav(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), convertedTrs, "nav.json");
|
|
58
|
+
await generateTestEnvGroups(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), allTestEnvGroups);
|
|
59
|
+
for (const reportEnvironment of reportEnvironments) {
|
|
60
|
+
const envConvertedTrs = convertedTrs.filter(({ environment }) => environment === reportEnvironment);
|
|
61
|
+
await generateTree(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), join(reportEnvironment, "tree.json"), treeLabels, envConvertedTrs, {
|
|
62
|
+
appendTitlePath,
|
|
63
|
+
});
|
|
64
|
+
await generateNav(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), envConvertedTrs, join(reportEnvironment, "nav.json"));
|
|
65
|
+
}
|
|
66
|
+
await generateEnvirontmentsList(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), store);
|
|
67
|
+
await generateVariables(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), store);
|
|
31
68
|
if (environmentItems?.length) {
|
|
32
|
-
await generateEnvironmentJson(__classPrivateFieldGet(this,
|
|
69
|
+
await generateEnvironmentJson(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), environmentItems);
|
|
33
70
|
}
|
|
34
71
|
if (attachments?.length) {
|
|
35
|
-
await generateAttachmentsFiles(__classPrivateFieldGet(this,
|
|
72
|
+
await generateAttachmentsFiles(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), attachments, (id) => store.attachmentContentById(id));
|
|
36
73
|
}
|
|
37
|
-
|
|
74
|
+
await generateQualityGateResults(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), qualityGateResults);
|
|
75
|
+
await generateGlobals(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), {
|
|
76
|
+
globalAttachments,
|
|
77
|
+
globalErrors,
|
|
78
|
+
globalExitCode,
|
|
79
|
+
contentFunction: (id) => store.attachmentContentById(id),
|
|
80
|
+
});
|
|
81
|
+
const reportDataFiles = singleFile ? __classPrivateFieldGet(this, _AwesomePlugin_writer, "f").reportFiles() : [];
|
|
38
82
|
await generateStaticFiles({
|
|
39
83
|
...this.options,
|
|
84
|
+
id: context.id,
|
|
40
85
|
allureVersion: context.allureVersion,
|
|
41
86
|
reportFiles: context.reportFiles,
|
|
42
|
-
reportDataFiles,
|
|
43
87
|
reportUuid: context.reportUuid,
|
|
44
88
|
reportName: context.reportName,
|
|
89
|
+
ci: context.ci,
|
|
90
|
+
reportDataFiles,
|
|
45
91
|
});
|
|
46
92
|
});
|
|
47
93
|
this.start = async (context) => {
|
|
48
94
|
const { singleFile } = this.options;
|
|
49
95
|
if (singleFile) {
|
|
50
|
-
__classPrivateFieldSet(this,
|
|
96
|
+
__classPrivateFieldSet(this, _AwesomePlugin_writer, new InMemoryReportDataWriter(), "f");
|
|
51
97
|
return;
|
|
52
98
|
}
|
|
53
|
-
__classPrivateFieldSet(this,
|
|
99
|
+
__classPrivateFieldSet(this, _AwesomePlugin_writer, new ReportFileDataWriter(context.reportFiles), "f");
|
|
54
100
|
await Promise.resolve();
|
|
55
101
|
};
|
|
56
102
|
this.update = async (context, store) => {
|
|
57
|
-
if (!__classPrivateFieldGet(this,
|
|
103
|
+
if (!__classPrivateFieldGet(this, _AwesomePlugin_writer, "f")) {
|
|
58
104
|
throw new Error("call start first");
|
|
59
105
|
}
|
|
60
|
-
await __classPrivateFieldGet(this,
|
|
106
|
+
await __classPrivateFieldGet(this, _AwesomePlugin_generate, "f").call(this, context, store);
|
|
61
107
|
};
|
|
62
108
|
this.done = async (context, store) => {
|
|
63
|
-
if (!__classPrivateFieldGet(this,
|
|
109
|
+
if (!__classPrivateFieldGet(this, _AwesomePlugin_writer, "f")) {
|
|
64
110
|
throw new Error("call start first");
|
|
65
111
|
}
|
|
66
|
-
await __classPrivateFieldGet(this,
|
|
112
|
+
await __classPrivateFieldGet(this, _AwesomePlugin_generate, "f").call(this, context, store);
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
async info(context, store) {
|
|
116
|
+
const allTrs = (await store.allTestResults()).filter((tr) => this.options.filter ? this.options.filter(tr) : true);
|
|
117
|
+
const newTrs = await store.allNewTestResults();
|
|
118
|
+
const retryTrs = allTrs.filter((tr) => !!tr?.retries?.length);
|
|
119
|
+
const flakyTrs = allTrs.filter((tr) => !!tr?.flaky);
|
|
120
|
+
const duration = allTrs.reduce((acc, { duration: trDuration = 0 }) => acc + trDuration, 0);
|
|
121
|
+
const worstStatus = getWorstStatus(allTrs.map(({ status }) => status));
|
|
122
|
+
const createdAt = allTrs.reduce((acc, { stop }) => Math.max(acc, stop || 0), 0);
|
|
123
|
+
return {
|
|
124
|
+
name: this.options.reportName || context.reportName,
|
|
125
|
+
stats: await store.testsStatistic(this.options.filter),
|
|
126
|
+
status: worstStatus ?? "passed",
|
|
127
|
+
duration,
|
|
128
|
+
createdAt,
|
|
129
|
+
plugin: "Awesome",
|
|
130
|
+
newTests: newTrs.map(convertToSummaryTestResult),
|
|
131
|
+
flakyTests: flakyTrs.map(convertToSummaryTestResult),
|
|
132
|
+
retryTests: retryTrs.map(convertToSummaryTestResult),
|
|
133
|
+
meta: {
|
|
134
|
+
reportId: context.reportUuid,
|
|
135
|
+
singleFile: this.options.singleFile ?? false,
|
|
136
|
+
withTestResultsLinks: true,
|
|
137
|
+
},
|
|
67
138
|
};
|
|
68
139
|
}
|
|
69
140
|
}
|
|
70
|
-
|
|
141
|
+
_AwesomePlugin_writer = new WeakMap(), _AwesomePlugin_generate = new WeakMap();
|
package/dist/writer.d.ts
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
import type { ReportFiles, ResultFile } from "@allurereport/plugin-api";
|
|
2
|
-
import type {
|
|
2
|
+
import type { AwesomeTestResult } from "@allurereport/web-awesome";
|
|
3
3
|
export interface ReportFile {
|
|
4
4
|
name: string;
|
|
5
5
|
value: string;
|
|
6
6
|
}
|
|
7
|
-
export interface
|
|
7
|
+
export interface AwesomeDataWriter {
|
|
8
8
|
writeData(fileName: string, data: any): Promise<void>;
|
|
9
9
|
writeWidget(fileName: string, data: any): Promise<void>;
|
|
10
|
-
writeTestCase(test:
|
|
10
|
+
writeTestCase(test: AwesomeTestResult): Promise<void>;
|
|
11
11
|
writeAttachment(source: string, file: ResultFile): Promise<void>;
|
|
12
12
|
}
|
|
13
|
-
export declare class FileSystemReportDataWriter implements
|
|
13
|
+
export declare class FileSystemReportDataWriter implements AwesomeDataWriter {
|
|
14
14
|
private readonly output;
|
|
15
15
|
constructor(output: string);
|
|
16
16
|
writeData(fileName: string, data: any): Promise<void>;
|
|
17
17
|
writeWidget(fileName: string, data: any): Promise<void>;
|
|
18
|
-
writeTestCase(test:
|
|
18
|
+
writeTestCase(test: AwesomeTestResult): Promise<void>;
|
|
19
19
|
writeAttachment(source: string, file: ResultFile): Promise<void>;
|
|
20
20
|
}
|
|
21
|
-
export declare class InMemoryReportDataWriter implements
|
|
21
|
+
export declare class InMemoryReportDataWriter implements AwesomeDataWriter {
|
|
22
22
|
#private;
|
|
23
23
|
writeData(fileName: string, data: any): Promise<void>;
|
|
24
24
|
writeWidget(fileName: string, data: any): Promise<void>;
|
|
25
|
-
writeTestCase(test:
|
|
25
|
+
writeTestCase(test: AwesomeTestResult): Promise<void>;
|
|
26
26
|
writeAttachment(fileName: string, file: ResultFile): Promise<void>;
|
|
27
27
|
reportFiles(): ReportFile[];
|
|
28
28
|
}
|
|
29
|
-
export declare class ReportFileDataWriter implements
|
|
29
|
+
export declare class ReportFileDataWriter implements AwesomeDataWriter {
|
|
30
30
|
readonly reportFiles: ReportFiles;
|
|
31
31
|
constructor(reportFiles: ReportFiles);
|
|
32
32
|
writeData(fileName: string, data: any): Promise<void>;
|
|
33
33
|
writeWidget(fileName: string, data: any): Promise<void>;
|
|
34
34
|
writeAttachment(source: string, file: ResultFile): Promise<void>;
|
|
35
|
-
writeTestCase(test:
|
|
35
|
+
writeTestCase(test: AwesomeTestResult): Promise<void>;
|
|
36
36
|
}
|
package/dist/writer.js
CHANGED
|
@@ -5,7 +5,8 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
5
5
|
};
|
|
6
6
|
var _InMemoryReportDataWriter_data;
|
|
7
7
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
8
|
-
import {
|
|
8
|
+
import { resolve } from "node:path";
|
|
9
|
+
import { join as joinPosix } from "node:path/posix";
|
|
9
10
|
export class FileSystemReportDataWriter {
|
|
10
11
|
constructor(output) {
|
|
11
12
|
this.output = output;
|
|
@@ -36,26 +37,29 @@ export class InMemoryReportDataWriter {
|
|
|
36
37
|
_InMemoryReportDataWriter_data.set(this, {});
|
|
37
38
|
}
|
|
38
39
|
async writeData(fileName, data) {
|
|
39
|
-
const dist =
|
|
40
|
+
const dist = joinPosix("data", fileName);
|
|
40
41
|
__classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")[dist] = Buffer.from(JSON.stringify(data), "utf-8");
|
|
41
42
|
}
|
|
42
43
|
async writeWidget(fileName, data) {
|
|
43
|
-
const dist =
|
|
44
|
+
const dist = joinPosix("widgets", fileName);
|
|
44
45
|
__classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")[dist] = Buffer.from(JSON.stringify(data), "utf-8");
|
|
45
46
|
}
|
|
46
47
|
async writeTestCase(test) {
|
|
47
|
-
const dist =
|
|
48
|
+
const dist = joinPosix("data", "test-results", `${test.id}.json`);
|
|
48
49
|
__classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")[dist] = Buffer.from(JSON.stringify(test), "utf-8");
|
|
49
50
|
}
|
|
50
51
|
async writeAttachment(fileName, file) {
|
|
51
|
-
const dist =
|
|
52
|
+
const dist = joinPosix("data", "attachments", fileName);
|
|
52
53
|
const content = await file.asBuffer();
|
|
53
54
|
if (content) {
|
|
54
55
|
__classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")[dist] = content;
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
reportFiles() {
|
|
58
|
-
return Object.keys(__classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")).map((key) => ({
|
|
59
|
+
return Object.keys(__classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")).map((key) => ({
|
|
60
|
+
name: key,
|
|
61
|
+
value: __classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")[key].toString("base64"),
|
|
62
|
+
}));
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
_InMemoryReportDataWriter_data = new WeakMap();
|
|
@@ -64,19 +68,19 @@ export class ReportFileDataWriter {
|
|
|
64
68
|
this.reportFiles = reportFiles;
|
|
65
69
|
}
|
|
66
70
|
async writeData(fileName, data) {
|
|
67
|
-
await this.reportFiles.addFile(
|
|
71
|
+
await this.reportFiles.addFile(joinPosix("data", fileName), Buffer.from(JSON.stringify(data), "utf-8"));
|
|
68
72
|
}
|
|
69
73
|
async writeWidget(fileName, data) {
|
|
70
|
-
await this.reportFiles.addFile(
|
|
74
|
+
await this.reportFiles.addFile(joinPosix("widgets", fileName), Buffer.from(JSON.stringify(data), "utf-8"));
|
|
71
75
|
}
|
|
72
76
|
async writeAttachment(source, file) {
|
|
73
77
|
const contentBuffer = await file.asBuffer();
|
|
74
78
|
if (!contentBuffer) {
|
|
75
79
|
return;
|
|
76
80
|
}
|
|
77
|
-
await this.reportFiles.addFile(
|
|
81
|
+
await this.reportFiles.addFile(joinPosix("data", "attachments", source), contentBuffer);
|
|
78
82
|
}
|
|
79
83
|
async writeTestCase(test) {
|
|
80
|
-
await this.reportFiles.addFile(
|
|
84
|
+
await this.reportFiles.addFile(joinPosix("data", "test-results", `${test.id}.json`), Buffer.from(JSON.stringify(test), "utf8"));
|
|
81
85
|
}
|
|
82
86
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/plugin-awesome",
|
|
3
|
-
"version": "3.0.0
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Allure Awesome Plugin – brand new HTML report with modern design and new features",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure",
|
|
@@ -30,10 +30,11 @@
|
|
|
30
30
|
"test": "rimraf ./out && vitest run"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@allurereport/
|
|
34
|
-
"@allurereport/
|
|
35
|
-
"@allurereport/
|
|
36
|
-
"@allurereport/web-
|
|
33
|
+
"@allurereport/charts-api": "3.0.0",
|
|
34
|
+
"@allurereport/core-api": "3.0.0",
|
|
35
|
+
"@allurereport/plugin-api": "3.0.0",
|
|
36
|
+
"@allurereport/web-awesome": "3.0.0",
|
|
37
|
+
"@allurereport/web-commons": "3.0.0",
|
|
37
38
|
"d3-shape": "^3.2.0",
|
|
38
39
|
"handlebars": "^4.7.8"
|
|
39
40
|
},
|
|
@@ -44,8 +45,8 @@
|
|
|
44
45
|
"@types/node": "^20.17.9",
|
|
45
46
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
46
47
|
"@typescript-eslint/parser": "^8.0.0",
|
|
47
|
-
"@vitest/runner": "^2.1.
|
|
48
|
-
"allure-vitest": "^3.
|
|
48
|
+
"@vitest/runner": "^2.1.9",
|
|
49
|
+
"allure-vitest": "^3.3.3",
|
|
49
50
|
"eslint": "^8.57.0",
|
|
50
51
|
"eslint-config-prettier": "^9.1.0",
|
|
51
52
|
"eslint-plugin-import": "^2.29.1",
|
|
@@ -55,6 +56,6 @@
|
|
|
55
56
|
"eslint-plugin-prefer-arrow": "^1.2.3",
|
|
56
57
|
"rimraf": "^6.0.1",
|
|
57
58
|
"typescript": "^5.6.3",
|
|
58
|
-
"vitest": "^2.1.
|
|
59
|
+
"vitest": "^2.1.9"
|
|
59
60
|
}
|
|
60
61
|
}
|
package/dist/charts.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { Statistic, TestStatus } from "@allurereport/core-api";
|
|
2
|
-
import type { PieArcDatum } from "d3-shape";
|
|
3
|
-
export type TestResultSlice = {
|
|
4
|
-
status: TestStatus;
|
|
5
|
-
count: number;
|
|
6
|
-
};
|
|
7
|
-
export type TestResultChartData = {
|
|
8
|
-
percentage: number;
|
|
9
|
-
slices: TestResultSlice[];
|
|
10
|
-
};
|
|
11
|
-
export declare const d3Arc: import("d3-shape").Arc<any, PieArcDatum<TestResultSlice>>;
|
|
12
|
-
export declare const d3Pie: import("d3-shape").Pie<any, TestResultSlice>;
|
|
13
|
-
export declare const getPercentage: (value: number, total: number) => number;
|
|
14
|
-
export declare const getChartData: (stats: Statistic) => TestResultChartData;
|
package/dist/charts.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { statusesList } from "@allurereport/core-api";
|
|
2
|
-
import { arc, pie } from "d3-shape";
|
|
3
|
-
export const d3Arc = arc().innerRadius(40).outerRadius(50).cornerRadius(2).padAngle(0.03);
|
|
4
|
-
export const d3Pie = pie()
|
|
5
|
-
.value((d) => d.count)
|
|
6
|
-
.padAngle(0.03)
|
|
7
|
-
.sortValues((a, b) => a - b);
|
|
8
|
-
export const getPercentage = (value, total) => Math.floor((value / total) * 10000) / 100;
|
|
9
|
-
export const getChartData = (stats) => {
|
|
10
|
-
const convertedStatuses = statusesList
|
|
11
|
-
.filter((status) => !!stats?.[status])
|
|
12
|
-
.map((status) => ({
|
|
13
|
-
status,
|
|
14
|
-
count: stats[status],
|
|
15
|
-
}));
|
|
16
|
-
const arcsData = d3Pie(convertedStatuses);
|
|
17
|
-
const slices = arcsData.map((arcData) => ({
|
|
18
|
-
d: d3Arc(arcData),
|
|
19
|
-
...arcData.data,
|
|
20
|
-
}));
|
|
21
|
-
const percentage = getPercentage(stats.passed ?? 0, stats.total);
|
|
22
|
-
return {
|
|
23
|
-
slices,
|
|
24
|
-
percentage,
|
|
25
|
-
};
|
|
26
|
-
};
|