@allurereport/plugin-awesome 3.0.0-beta.9 → 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 CHANGED
@@ -47,11 +47,13 @@ export default defineConfig({
47
47
 
48
48
  The plugin accepts the following options:
49
49
 
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` | 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` |
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` |
@@ -1,5 +1,5 @@
1
1
  import type { TestFixtureResult, TestResult, TestStepResult } from "@allurereport/core-api";
2
- import type { AllureAwesomeFixtureResult, AllureAwesomeTestResult, AllureAwesomeTestStepResult } from "@allurereport/web-awesome";
3
- export declare const convertTestResult: (tr: TestResult) => AllureAwesomeTestResult;
4
- export declare const convertTestStepResult: (tsr: TestStepResult) => AllureAwesomeTestStepResult;
5
- export declare const convertFixtureResult: (fr: TestFixtureResult) => AllureAwesomeFixtureResult;
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;
@@ -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,3 @@
1
+ import type { TestResult } from "@allurereport/core-api";
2
+ import type { TestResultFilter } from "@allurereport/plugin-api";
3
+ export declare const filterEnv: (env: string, filter?: TestResultFilter) => (testResult: TestResult) => boolean;
@@ -0,0 +1,8 @@
1
+ export const filterEnv = (env, filter) => {
2
+ return (testResult) => {
3
+ if (testResult.environment !== env) {
4
+ return false;
5
+ }
6
+ return filter ? filter(testResult) : true;
7
+ };
8
+ };
@@ -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
+ };
@@ -1,20 +1,39 @@
1
- import { type AttachmentLink, type EnvironmentItem, type Statistic } from "@allurereport/core-api";
2
- import { type AllureStore, type ReportFiles, type ResultFile } from "@allurereport/plugin-api";
3
- import type { AllureAwesomeTestResult } from "@allurereport/web-awesome";
4
- import type { AllureAwesomeOptions, TemplateManifest } from "./model.js";
5
- import type { AllureAwesomeDataWriter, ReportFile } from "./writer.js";
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: AllureAwesomeDataWriter, store: AllureStore) => Promise<AllureAwesomeTestResult[]>;
8
- export declare const generateTree: (writer: AllureAwesomeDataWriter, treeName: string, labels: string[], tests: AllureAwesomeTestResult[]) => Promise<void>;
9
- export declare const generateEnvironmentJson: (writer: AllureAwesomeDataWriter, env: EnvironmentItem[]) => Promise<void>;
10
- export declare const generateStatistic: (writer: AllureAwesomeDataWriter, statistic: Statistic) => Promise<void>;
11
- export declare const generatePieChart: (writer: AllureAwesomeDataWriter, statistic: Statistic) => Promise<void>;
12
- export declare const generateAttachmentsFiles: (writer: AllureAwesomeDataWriter, attachmentLinks: AttachmentLink[], contentFunction: (id: string) => Promise<ResultFile | undefined>) => Promise<Map<string, string> | undefined>;
13
- export declare const generateHistoryDataPoints: (writer: AllureAwesomeDataWriter, store: AllureStore) => Promise<Map<string, string>>;
14
- export declare const generateStaticFiles: (payload: AllureAwesomeOptions & {
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>;
@@ -1,12 +1,12 @@
1
- import { compareBy, incrementStatistic, nullsLast, ordinal, } from "@allurereport/core-api";
2
- import { filterTree } from "@allurereport/plugin-api";
3
- import { createTreeByLabels, sortTree, transformTree } from "@allurereport/plugin-api";
4
- import { createBaseUrlScript, createFontLinkTag, createReportDataScript, createScriptTag, createStylesLinkTag, } from "@allurereport/web-commons";
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="favicon.ico">
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 = await store.allTestResults({ includeHidden: true });
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.retry = convertedTr.retries.length > 0;
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 generateTree = async (writer, treeName, labels, tests) => {
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 tree = createTreeByLabels(visibleTests, labels, ({ id, name, status, duration, flaky, start, retries }) => {
108
- return {
109
- nodeId: id,
110
- retry: !!retries?.length,
111
- name,
112
- status,
113
- duration,
114
- flaky,
115
- start,
116
- };
117
- }, undefined, (group, leaf) => {
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(`${treeName}.json`, tree);
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 generateStatistic = async (writer, statistic) => {
129
- await writer.writeWidget("allure_statistic.json", statistic);
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 generatePieChart = async (writer, statistic) => {
132
- const chartData = getChartData(statistic);
133
- await writer.writeWidget("allure_pie_chart.json", chartData);
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 = "light", groupBy, reportFiles, reportDataFiles, reportUuid, allureVersion, } = payload;
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 mainJsContentBuffer = await readFile(mainJsSource);
190
- bodyTags.push(createScriptTag(`data:text/javascript;base64,${mainJsContentBuffer.toString("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: Date.now(),
319
+ createdAt: now,
198
320
  reportUuid,
199
- groupBy: groupBy?.length ? groupBy : ["parentSuite", "suite", "subSuite"],
200
- };
201
- const html = compile({
202
- headTags: headTags.join("\n"),
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
- reportUuid,
209
- reportName,
210
- singleFile: payload.singleFile,
211
- });
212
- await reportFiles.addFile("index.html", Buffer.from(html, "utf8"));
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
- import { AllureAwesomePlugin } from "./plugin.js";
2
- export default AllureAwesomePlugin;
1
+ export type { AwesomePluginOptions } from "./model.js";
2
+ export { AwesomePlugin as default } from "./plugin.js";
package/dist/index.js CHANGED
@@ -1,2 +1 @@
1
- import { AllureAwesomePlugin } from "./plugin.js";
2
- export default AllureAwesomePlugin;
1
+ export { AwesomePlugin as default } from "./plugin.js";
package/dist/model.d.ts CHANGED
@@ -1,15 +1,24 @@
1
- export type AllureAwesomeOptions = {
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" | "ru";
7
+ theme?: "light" | "dark" | "auto";
8
+ reportLanguage?: "en";
7
9
  groupBy?: string[];
8
- ci?: {
9
- type: "github" | "jenkins";
10
- url: string;
11
- name: string;
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 AllureAwesomePluginOptions = AllureAwesomeOptions;
24
+ export type AwesomePluginOptions = AwesomeOptions;
package/dist/plugin.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import type { AllureStore, Plugin, PluginContext } from "@allurereport/plugin-api";
2
- import type { AllureAwesomePluginOptions } from "./model.js";
3
- export declare class AllureAwesomePlugin implements Plugin {
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: AllureAwesomePluginOptions;
6
- constructor(options?: AllureAwesomePluginOptions);
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 _AllureAwesomePlugin_writer, _AllureAwesomePlugin_generate;
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 { generateAttachmentsFiles, generateEnvironmentJson, generateHistoryDataPoints, generatePieChart, generateStaticFiles, generateStatistic, generateTestResults, generateTree, } from "./generators.js";
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 AllureAwesomePlugin {
21
+ export class AwesomePlugin {
17
22
  constructor(options = {}) {
18
23
  this.options = options;
19
- _AllureAwesomePlugin_writer.set(this, void 0);
20
- _AllureAwesomePlugin_generate.set(this, async (context, store) => {
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 statistic = await store.testsStatistic();
28
+ const reportEnvironments = await store.allEnvironments();
24
29
  const attachments = await store.allAttachments();
25
- await generateStatistic(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), statistic);
26
- await generatePieChart(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), statistic);
27
- const convertedTrs = await generateTestResults(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), store);
28
- const treeLabels = preciseTreeLabels(!groupBy.length ? ["parentSuite", "suite", "subSuite"] : groupBy, convertedTrs, ({ labels }) => labels.map(({ name }) => name));
29
- await generateTree(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), "tree", treeLabels, convertedTrs);
30
- await generateHistoryDataPoints(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), store);
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, _AllureAwesomePlugin_writer, "f"), environmentItems);
69
+ await generateEnvironmentJson(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), environmentItems);
33
70
  }
34
71
  if (attachments?.length) {
35
- await generateAttachmentsFiles(__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f"), attachments, (id) => store.attachmentContentById(id));
72
+ await generateAttachmentsFiles(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), attachments, (id) => store.attachmentContentById(id));
36
73
  }
37
- const reportDataFiles = singleFile ? __classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f").reportFiles() : [];
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, _AllureAwesomePlugin_writer, new InMemoryReportDataWriter(), "f");
96
+ __classPrivateFieldSet(this, _AwesomePlugin_writer, new InMemoryReportDataWriter(), "f");
51
97
  return;
52
98
  }
53
- __classPrivateFieldSet(this, _AllureAwesomePlugin_writer, new ReportFileDataWriter(context.reportFiles), "f");
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, _AllureAwesomePlugin_writer, "f")) {
103
+ if (!__classPrivateFieldGet(this, _AwesomePlugin_writer, "f")) {
58
104
  throw new Error("call start first");
59
105
  }
60
- await __classPrivateFieldGet(this, _AllureAwesomePlugin_generate, "f").call(this, context, store);
106
+ await __classPrivateFieldGet(this, _AwesomePlugin_generate, "f").call(this, context, store);
61
107
  };
62
108
  this.done = async (context, store) => {
63
- if (!__classPrivateFieldGet(this, _AllureAwesomePlugin_writer, "f")) {
109
+ if (!__classPrivateFieldGet(this, _AwesomePlugin_writer, "f")) {
64
110
  throw new Error("call start first");
65
111
  }
66
- await __classPrivateFieldGet(this, _AllureAwesomePlugin_generate, "f").call(this, context, store);
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
- _AllureAwesomePlugin_writer = new WeakMap(), _AllureAwesomePlugin_generate = new WeakMap();
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 { AllureAwesomeTestResult } from "@allurereport/web-awesome";
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 AllureAwesomeDataWriter {
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: AllureAwesomeTestResult): Promise<void>;
10
+ writeTestCase(test: AwesomeTestResult): Promise<void>;
11
11
  writeAttachment(source: string, file: ResultFile): Promise<void>;
12
12
  }
13
- export declare class FileSystemReportDataWriter implements AllureAwesomeDataWriter {
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: AllureAwesomeTestResult): Promise<void>;
18
+ writeTestCase(test: AwesomeTestResult): Promise<void>;
19
19
  writeAttachment(source: string, file: ResultFile): Promise<void>;
20
20
  }
21
- export declare class InMemoryReportDataWriter implements AllureAwesomeDataWriter {
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: AllureAwesomeTestResult): Promise<void>;
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 AllureAwesomeDataWriter {
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: AllureAwesomeTestResult): Promise<void>;
35
+ writeTestCase(test: AwesomeTestResult): Promise<void>;
36
36
  }
package/dist/writer.js CHANGED
@@ -5,7 +5,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
5
5
  };
6
6
  var _InMemoryReportDataWriter_data;
7
7
  import { mkdir, writeFile } from "node:fs/promises";
8
- import { join, resolve } from "node:path";
8
+ import { resolve } from "node:path";
9
9
  import { join as joinPosix } from "node:path/posix";
10
10
  export class FileSystemReportDataWriter {
11
11
  constructor(output) {
@@ -56,7 +56,10 @@ export class InMemoryReportDataWriter {
56
56
  }
57
57
  }
58
58
  reportFiles() {
59
- return Object.keys(__classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")).map((key) => ({ name: key, value: __classPrivateFieldGet(this, _InMemoryReportDataWriter_data, "f")[key].toString("base64") }));
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
+ }));
60
63
  }
61
64
  }
62
65
  _InMemoryReportDataWriter_data = new WeakMap();
@@ -75,7 +78,7 @@ export class ReportFileDataWriter {
75
78
  if (!contentBuffer) {
76
79
  return;
77
80
  }
78
- await this.reportFiles.addFile(join("data", "attachments", source), contentBuffer);
81
+ await this.reportFiles.addFile(joinPosix("data", "attachments", source), contentBuffer);
79
82
  }
80
83
  async writeTestCase(test) {
81
84
  await this.reportFiles.addFile(joinPosix("data", "test-results", `${test.id}.json`), Buffer.from(JSON.stringify(test), "utf8"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/plugin-awesome",
3
- "version": "3.0.0-beta.9",
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/core-api": "3.0.0-beta.9",
34
- "@allurereport/plugin-api": "3.0.0-beta.9",
35
- "@allurereport/web-awesome": "3.0.0-beta.9",
36
- "@allurereport/web-commons": "3.0.0-beta.9",
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.8",
48
- "allure-vitest": "^3.0.9",
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.8"
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
- };