@allurereport/plugin-awesome 3.1.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ import type { CategoryDefinition } from "@allurereport/core-api";
2
+ import type { AwesomeTestResult } from "@allurereport/web-awesome";
3
+ import type { AwesomeDataWriter } from "./writer.js";
4
+ export declare const applyCategoriesToTestResults: (tests: AwesomeTestResult[], categories: CategoryDefinition[]) => void;
5
+ export declare const generateCategories: (writer: AwesomeDataWriter, { tests, categories, filename, environmentCount, selectedEnvironmentCount, environments, defaultEnvironment, }: {
6
+ tests: AwesomeTestResult[];
7
+ categories: CategoryDefinition[];
8
+ filename?: string;
9
+ environmentCount?: number;
10
+ selectedEnvironmentCount?: number;
11
+ environments?: string[];
12
+ defaultEnvironment?: string;
13
+ }) => Promise<void>;
@@ -0,0 +1,213 @@
1
+ import { EMPTY_VALUE, buildEnvironmentSortOrder, compareChildNodes, extractErrorMatchingData, findLastByLabelName, incrementStatistic, matchCategory, } from "@allurereport/core-api";
2
+ import { md5 } from "@allurereport/plugin-api";
3
+ const emptyStat = () => ({
4
+ total: 0,
5
+ });
6
+ const msgKey = (m) => (m && m.trim().length ? m : EMPTY_VALUE);
7
+ const envKey = (m) => (m && m.trim().length ? m : EMPTY_VALUE);
8
+ const formatEmptyValue = (key) => {
9
+ if (key === "message") {
10
+ return "No message";
11
+ }
12
+ if (key === "transition") {
13
+ return "No transition";
14
+ }
15
+ if (key === "environment") {
16
+ return "No environment";
17
+ }
18
+ return `No ${key}`;
19
+ };
20
+ const hasEnvironmentSelector = (category) => category.groupBy.some((selector) => selector === "environment");
21
+ const computeGroupEnvironments = (category, environmentCount, isSingleEnvironmentSelected) => {
22
+ if (isSingleEnvironmentSelected) {
23
+ return false;
24
+ }
25
+ if (category.groupEnvironments !== undefined) {
26
+ return category.groupEnvironments;
27
+ }
28
+ if (environmentCount > 1 && !hasEnvironmentSelector(category)) {
29
+ return true;
30
+ }
31
+ return false;
32
+ };
33
+ const displayGroupValue = (key, value) => (value === EMPTY_VALUE ? formatEmptyValue(key) : value);
34
+ const formatGroupName = (key, value) => `${key}: ${displayGroupValue(key, value)}`;
35
+ export const applyCategoriesToTestResults = (tests, categories) => {
36
+ for (const tr of tests) {
37
+ const matchingData = extractErrorMatchingData(tr);
38
+ const matched = matchCategory(categories, matchingData);
39
+ if (!matched) {
40
+ tr.categories = [];
41
+ continue;
42
+ }
43
+ tr.categories = [{ name: matched.name }];
44
+ }
45
+ };
46
+ const extractGroupValue = (selector, testResult) => {
47
+ if (selector === "flaky") {
48
+ const flakyValue = testResult.flaky ? "true" : "false";
49
+ return { key: "flaky", value: flakyValue, name: formatGroupName("flaky", flakyValue) };
50
+ }
51
+ if (selector === "transition") {
52
+ const transitionValue = testResult.transition ?? EMPTY_VALUE;
53
+ return { key: "transition", value: transitionValue, name: formatGroupName("transition", transitionValue) };
54
+ }
55
+ if (selector === "status") {
56
+ const statusValue = testResult.status ?? "unknown";
57
+ return { key: "status", value: statusValue, name: formatGroupName("status", statusValue) };
58
+ }
59
+ if (selector === "environment") {
60
+ const environmentValue = envKey(testResult.environment);
61
+ return { key: "environment", value: environmentValue, name: formatGroupName("environment", environmentValue) };
62
+ }
63
+ if (selector === "owner") {
64
+ const ownerValue = findLastByLabelName(testResult.labels, "owner") ?? EMPTY_VALUE;
65
+ return { key: "owner", value: ownerValue, name: formatGroupName("owner", ownerValue) };
66
+ }
67
+ if (selector === "severity") {
68
+ const fallbackValue = selector === "severity" ? "normal" : EMPTY_VALUE;
69
+ const builtInValue = findLastByLabelName(testResult.labels, selector) ?? fallbackValue;
70
+ return {
71
+ key: selector,
72
+ value: builtInValue,
73
+ name: formatGroupName(selector, builtInValue),
74
+ };
75
+ }
76
+ if (selector === "layer") {
77
+ const layerValue = findLastByLabelName(testResult.labels, "layer") ?? EMPTY_VALUE;
78
+ return { key: "layer", value: layerValue, name: formatGroupName("layer", layerValue) };
79
+ }
80
+ const labelName = selector.label;
81
+ const labelValue = findLastByLabelName(testResult.labels, labelName) ?? EMPTY_VALUE;
82
+ return { key: labelName, value: labelValue, name: formatGroupName(labelName, labelValue) };
83
+ };
84
+ const buildGroupLevels = (category, testResult, matchingData, environmentCount, isSingleEnvironmentSelected) => {
85
+ const levels = [];
86
+ for (const selector of category.groupBy) {
87
+ const groupValue = extractGroupValue(selector, testResult);
88
+ levels.push({ type: "group", key: groupValue.key, value: groupValue.value, name: groupValue.name });
89
+ }
90
+ if (category.groupByMessage) {
91
+ const messageValue = msgKey(matchingData.message);
92
+ levels.push({
93
+ type: "message",
94
+ key: "message",
95
+ value: messageValue,
96
+ name: displayGroupValue("message", messageValue),
97
+ });
98
+ }
99
+ const groupEnvironments = computeGroupEnvironments(category, environmentCount, isSingleEnvironmentSelected);
100
+ if (groupEnvironments) {
101
+ const testKeyValue = testResult.historyId ?? testResult.id;
102
+ const testDisplayName = testResult.name ?? testKeyValue;
103
+ levels.push({
104
+ type: "history",
105
+ key: "historyId",
106
+ value: testKeyValue,
107
+ name: testDisplayName,
108
+ });
109
+ }
110
+ return levels;
111
+ };
112
+ export const generateCategories = async (writer, { tests, categories, filename = "categories.json", environmentCount = 0, selectedEnvironmentCount, environments = [], defaultEnvironment = "default", }) => {
113
+ const visible = tests.filter((t) => !t.hidden);
114
+ const environmentOrderMap = buildEnvironmentSortOrder(environments, defaultEnvironment);
115
+ const nodes = {};
116
+ const roots = [];
117
+ const childrenMap = new Map();
118
+ const categoryOrder = categories.filter((cat) => !cat.hide).map((cat) => cat.name);
119
+ const categoryIds = new Map();
120
+ const categoryTouched = new Set();
121
+ const duplicateChecker = (node) => {
122
+ var _a;
123
+ nodes[_a = node.id] ?? (nodes[_a] = node);
124
+ return nodes[node.id];
125
+ };
126
+ const attachChild = (parentId, childId) => {
127
+ const set = childrenMap.get(parentId) ?? new Set();
128
+ set.add(childId);
129
+ childrenMap.set(parentId, set);
130
+ };
131
+ const bumpStat = (nodeId, status) => {
132
+ const node = nodes[nodeId];
133
+ node.statistic ?? (node.statistic = emptyStat());
134
+ incrementStatistic(node.statistic, status);
135
+ };
136
+ const ensureCategoryNode = (category) => {
137
+ const catId = categoryIds.get(category.name) ?? `cat:${md5(category.name)}`;
138
+ if (!categoryIds.has(category.name)) {
139
+ categoryIds.set(category.name, catId);
140
+ }
141
+ duplicateChecker({
142
+ id: catId,
143
+ type: "category",
144
+ name: category.name,
145
+ statistic: emptyStat(),
146
+ childrenIds: [],
147
+ expand: category.expand,
148
+ });
149
+ return catId;
150
+ };
151
+ for (const tr of visible) {
152
+ const matchingData = extractErrorMatchingData(tr);
153
+ const matchedCategory = matchCategory(categories, matchingData);
154
+ if (!matchedCategory || matchedCategory.hide) {
155
+ continue;
156
+ }
157
+ const catId = ensureCategoryNode(matchedCategory);
158
+ categoryTouched.add(matchedCategory.name);
159
+ bumpStat(catId, tr.status);
160
+ const environmentValue = envKey(tr.environment);
161
+ const isSingleEnvironmentSelected = selectedEnvironmentCount === 1;
162
+ const groupEnvironments = computeGroupEnvironments(matchedCategory, environmentCount, isSingleEnvironmentSelected);
163
+ const levels = buildGroupLevels(matchedCategory, tr, matchingData, environmentCount, isSingleEnvironmentSelected);
164
+ const leafName = groupEnvironments ? formatGroupName("environment", environmentValue) : tr.name;
165
+ let parentId = catId;
166
+ for (const level of levels) {
167
+ const levelId = `${level.type}:${md5(`${parentId}\n${level.key}\n${level.value}`)}`;
168
+ const historyId = level.type === "history" ? level.value : undefined;
169
+ duplicateChecker({
170
+ id: levelId,
171
+ type: level.type,
172
+ name: level.name,
173
+ key: level.key,
174
+ value: level.value,
175
+ historyId,
176
+ statistic: emptyStat(),
177
+ childrenIds: [],
178
+ });
179
+ bumpStat(levelId, tr.status);
180
+ attachChild(parentId, levelId);
181
+ parentId = levelId;
182
+ }
183
+ duplicateChecker({
184
+ id: tr.id,
185
+ type: "tr",
186
+ name: leafName,
187
+ key: groupEnvironments ? "environment" : undefined,
188
+ value: groupEnvironments ? environmentValue : undefined,
189
+ status: tr.status,
190
+ duration: tr.duration,
191
+ flaky: tr.flaky,
192
+ retriesCount: tr.retriesCount,
193
+ transition: tr.transition,
194
+ tooltips: tr.tooltips,
195
+ });
196
+ attachChild(parentId, tr.id);
197
+ }
198
+ for (const [parentNodeId, childNodeIds] of childrenMap.entries()) {
199
+ const sortedChildIds = Array.from(childNodeIds).sort((leftChildId, rightChildId) => compareChildNodes(leftChildId, rightChildId, nodes, environmentOrderMap));
200
+ nodes[parentNodeId].childrenIds = sortedChildIds;
201
+ }
202
+ for (const catName of categoryOrder) {
203
+ if (!categoryTouched.has(catName)) {
204
+ continue;
205
+ }
206
+ const id = categoryIds.get(catName);
207
+ if (id) {
208
+ roots.push(id);
209
+ }
210
+ }
211
+ const store = { roots, nodes };
212
+ await writer.writeWidget(filename, store);
213
+ };
@@ -1,4 +1,4 @@
1
- import type { TestFixtureResult, TestResult, TestStepResult } from "@allurereport/core-api";
1
+ import { type TestFixtureResult, type TestResult, type TestStepResult } from "@allurereport/core-api";
2
2
  import type { AwesomeFixtureResult, AwesomeTestResult, AwesomeTestStepResult } from "@allurereport/web-awesome";
3
3
  export declare const convertTestResult: (tr: TestResult) => AwesomeTestResult;
4
4
  export declare const convertTestStepResult: (tsr: TestStepResult) => AwesomeTestStepResult;
@@ -1,3 +1,7 @@
1
+ import { createDictionary, } from "@allurereport/core-api";
2
+ import MarkdownIt from "markdown-it";
3
+ const md = new MarkdownIt();
4
+ const markdownToHtml = (value) => (value ? md.render(value) : undefined);
1
5
  const mapLabelsByName = (labels) => {
2
6
  return labels.reduce((acc, { name, value }) => {
3
7
  acc[name] = acc[name] || [];
@@ -5,7 +9,7 @@ const mapLabelsByName = (labels) => {
5
9
  acc[name].push(value);
6
10
  }
7
11
  return acc;
8
- }, {});
12
+ }, createDictionary());
9
13
  };
10
14
  export const convertTestResult = (tr) => {
11
15
  return {
@@ -28,6 +32,7 @@ export const convertTestResult = (tr) => {
28
32
  steps: tr.steps,
29
33
  error: tr.error,
30
34
  testCase: tr.testCase,
35
+ descriptionHtml: tr.descriptionHtml ?? markdownToHtml(tr.description),
31
36
  environment: tr.environment,
32
37
  setup: [],
33
38
  teardown: [],
@@ -1,7 +1,7 @@
1
- import type { AllureStore } from "@allurereport/plugin-api";
1
+ import type { AwesomeTestResult } from "@allurereport/web-awesome";
2
2
  import type { AwesomeOptions } from "./model.js";
3
3
  type Writer = {
4
4
  writeWidget(fileName: string, data: any): Promise<void>;
5
5
  };
6
- export declare const generateTimeline: (writer: Writer, store: AllureStore, options: AwesomeOptions) => Promise<void>;
6
+ export declare const generateTimeline: (writer: Writer, trs: AwesomeTestResult[], options: AwesomeOptions) => Promise<void>;
7
7
  export {};
@@ -1,16 +1,12 @@
1
- import { hasLabels } from "@allurereport/web-commons";
2
1
  const DEFAULT_MIN_DURATION = 1;
3
- const HOST_LABEL = "host";
4
- const THREAD_LABEL = "thread";
5
2
  const DEFAULT_TIMELINE_OPTIONS = {
6
3
  minDuration: DEFAULT_MIN_DURATION,
7
4
  };
8
- export const generateTimeline = async (writer, store, options) => {
5
+ export const generateTimeline = async (writer, trs, options) => {
9
6
  const { timeline = DEFAULT_TIMELINE_OPTIONS } = options;
10
7
  const { minDuration = DEFAULT_MIN_DURATION } = timeline;
11
- const testResults = await store.allTestResults({ includeHidden: true });
12
8
  const result = [];
13
- for (const test of testResults) {
9
+ for (const test of trs) {
14
10
  const hasStart = Number.isInteger(test.start);
15
11
  const hasStop = Number.isInteger(test.stop);
16
12
  if (!hasStart || !hasStop) {
@@ -20,7 +16,8 @@ export const generateTimeline = async (writer, store, options) => {
20
16
  if (duration < minDuration) {
21
17
  continue;
22
18
  }
23
- if (!hasLabels(test, [HOST_LABEL, THREAD_LABEL])) {
19
+ const { host, thread } = test.groupedLabels;
20
+ if (!host?.length || !thread?.length) {
24
21
  continue;
25
22
  }
26
23
  result.push({
@@ -29,10 +26,10 @@ export const generateTimeline = async (writer, store, options) => {
29
26
  name: test.name,
30
27
  status: test.status,
31
28
  hidden: test.hidden,
32
- labels: test.labels,
29
+ host: host[0],
30
+ thread: thread[0],
33
31
  environment: test.environment,
34
32
  start: test.start,
35
- stop: test.stop,
36
33
  duration,
37
34
  });
38
35
  }
@@ -1,10 +1,10 @@
1
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";
2
+ import type { AllureStore, ExitCode, PluginContext, QualityGateValidationResult, ReportFiles, ResultFile } from "@allurereport/plugin-api";
3
3
  import type { AwesomeTestResult } from "@allurereport/web-awesome";
4
4
  import type { AwesomeOptions, TemplateManifest } from "./model.js";
5
5
  import type { AwesomeDataWriter, ReportFile } from "./writer.js";
6
6
  export declare const readTemplateManifest: (singleFileMode?: boolean) => Promise<TemplateManifest>;
7
- export declare const generateTestResults: (writer: AwesomeDataWriter, store: AllureStore, trs: TestResult[], filter?: TestResultFilter) => Promise<AwesomeTestResult[]>;
7
+ export declare const generateTestResults: (writer: AwesomeDataWriter, store: AllureStore, trs: TestResult[]) => Promise<AwesomeTestResult[]>;
8
8
  export declare const generateTestCases: (writer: AwesomeDataWriter, trs: AwesomeTestResult[]) => Promise<void>;
9
9
  export declare const generateTestEnvGroups: (writer: AwesomeDataWriter, groups: TestEnvGroup[]) => Promise<void>;
10
10
  export declare const generateNav: (writer: AwesomeDataWriter, trs: AwesomeTestResult[], filename?: string) => Promise<void>;
@@ -27,7 +27,7 @@ export declare const generateGlobals: (writer: AwesomeDataWriter, payload: {
27
27
  globalErrors?: TestError[];
28
28
  contentFunction: (id: string) => Promise<ResultFile | undefined>;
29
29
  }) => Promise<void>;
30
- export declare const generateQualityGateResults: (writer: AwesomeDataWriter, qualityGateResults?: QualityGateValidationResult[]) => Promise<void>;
30
+ export declare const generateQualityGateResults: (writer: AwesomeDataWriter, qualityGateResults?: Record<string, QualityGateValidationResult[]>) => Promise<void>;
31
31
  export declare const generateStaticFiles: (payload: AwesomeOptions & {
32
32
  id: string;
33
33
  allureVersion: string;
@@ -37,4 +37,4 @@ export declare const generateStaticFiles: (payload: AwesomeOptions & {
37
37
  reportName: string;
38
38
  }) => Promise<void>;
39
39
  export declare const generateAllCharts: (writer: AwesomeDataWriter, store: AllureStore, options: AwesomeOptions, context: PluginContext) => Promise<void>;
40
- export declare const generateTreeFilters: (writer: AwesomeDataWriter, store: AllureStore) => Promise<void>;
40
+ export declare const generateTreeFilters: (writer: AwesomeDataWriter, testResults: AwesomeTestResult[]) => Promise<void>;
@@ -58,9 +58,9 @@ const createBreadcrumbs = (convertedTr) => {
58
58
  acc[label.name].push(label.value || "");
59
59
  return acc;
60
60
  }, {});
61
- const parentSuites = labelsByType.parentSuite || [""];
62
- const suites = labelsByType.suite || [""];
63
- const subSuites = labelsByType.subSuite || [""];
61
+ const parentSuites = labelsByType.parentSuite ?? [""];
62
+ const suites = labelsByType.suite ?? [""];
63
+ const subSuites = labelsByType.subSuite ?? [""];
64
64
  return parentSuites.reduce((acc, parentSuite) => {
65
65
  suites.forEach((suite) => {
66
66
  subSuites.forEach((subSuite) => {
@@ -73,10 +73,9 @@ const createBreadcrumbs = (convertedTr) => {
73
73
  return acc;
74
74
  }, []);
75
75
  };
76
- export const generateTestResults = async (writer, store, trs, filter) => {
77
- const allTr = trs.filter((tr) => (filter ? filter(tr) : true));
76
+ export const generateTestResults = async (writer, store, trs) => {
78
77
  let convertedTrs = [];
79
- for (const tr of allTr) {
78
+ for (const tr of trs) {
80
79
  const trFixtures = await store.fixturesByTrId(tr.id);
81
80
  const convertedTrFixtures = trFixtures.map(convertFixtureResult);
82
81
  const convertedTr = convertTestResult(tr);
@@ -190,7 +189,7 @@ const buildTreeByTitlePath = (tests) => {
190
189
  };
191
190
  };
192
191
  const buildTreeByLabelsAndTitlePathCombined = (tests, labels) => createTreeByLabelsAndTitlePath(tests, labels, leafFactory, undefined, (group, leaf) => incrementStatistic(group.statistic, leaf.status));
193
- const leafFactory = ({ id, name, status, duration, flaky, start, retry, retriesCount, transition, tooltips, historyId, groupedLabels, }) => {
192
+ const leafFactory = ({ id, name, status, duration, flaky, start, retry, retriesCount, transition, tooltips, historyId, groupedLabels, categories, }) => {
194
193
  const leaf = {
195
194
  nodeId: id,
196
195
  id: historyId ?? id,
@@ -207,6 +206,9 @@ const leafFactory = ({ id, name, status, duration, flaky, start, retry, retriesC
207
206
  if (groupedLabels.tag && groupedLabels.tag.length > 0) {
208
207
  leaf.tags = groupedLabels.tag;
209
208
  }
209
+ if (categories?.length) {
210
+ leaf.categories = categories.map((category) => category.name).filter(Boolean);
211
+ }
210
212
  return leaf;
211
213
  };
212
214
  export const generateEnvironmentJson = async (writer, env) => {
@@ -283,7 +285,7 @@ export const generateGlobals = async (writer, payload) => {
283
285
  }
284
286
  await writer.writeWidget("globals.json", globals);
285
287
  };
286
- export const generateQualityGateResults = async (writer, qualityGateResults = []) => {
288
+ export const generateQualityGateResults = async (writer, qualityGateResults = {}) => {
287
289
  await writer.writeWidget("quality-gate.json", qualityGateResults);
288
290
  };
289
291
  export const generateStaticFiles = async (payload) => {
@@ -359,28 +361,29 @@ export const generateStaticFiles = async (payload) => {
359
361
  }
360
362
  };
361
363
  export const generateAllCharts = async (writer, store, options, context) => {
362
- const { charts = defaultChartsConfig } = options;
363
- const generatedChartsData = await generateCharts(charts, store, context.reportName, randomUUID);
364
+ const { charts = defaultChartsConfig, filter } = options;
365
+ const generatedChartsData = await generateCharts(charts, store, context.reportName, randomUUID, filter);
364
366
  if (Object.keys(generatedChartsData.general).length > 0) {
365
367
  await writer.writeWidget("charts.json", generatedChartsData);
366
368
  }
367
369
  };
368
- export const generateTreeFilters = async (writer, store) => {
370
+ export const generateTreeFilters = async (writer, testResults) => {
369
371
  const trTags = new Set();
370
- const trs = await store.allTestResults({ includeHidden: false });
371
- for (const tr of trs) {
372
- if (tr.labels.length === 0) {
373
- continue;
372
+ const trCategories = new Set();
373
+ for (const tr of testResults) {
374
+ for (const tag of tr.groupedLabels.tag ?? []) {
375
+ trTags.add(tag);
374
376
  }
375
- tr.labels.forEach((label) => {
376
- if (label.name === "tag" && !!label.value) {
377
- trTags.add(label.value);
377
+ tr.categories?.forEach((category) => {
378
+ if (category.name) {
379
+ trCategories.add(category.name);
378
380
  }
379
381
  });
380
382
  }
381
- if (trTags.size === 0) {
383
+ if (trTags.size === 0 && trCategories.size === 0) {
382
384
  return Promise.resolve();
383
385
  }
384
386
  const tags = Array.from(trTags).sort((a, b) => a.localeCompare(b));
385
- await writer.writeWidget("tree-filters.json", { tags });
387
+ const categories = Array.from(trCategories).sort((a, b) => a.localeCompare(b));
388
+ await writer.writeWidget("tree-filters.json", { tags, categories });
386
389
  };
package/dist/model.d.ts CHANGED
@@ -5,7 +5,7 @@ export type AwesomeOptions = {
5
5
  singleFile?: boolean;
6
6
  logo?: string;
7
7
  theme?: "light" | "dark" | "auto";
8
- reportLanguage?: "en";
8
+ reportLanguage?: string;
9
9
  groupBy?: string[];
10
10
  layout?: "base" | "split";
11
11
  environments?: Record<string, EnvironmentsConfig>;
package/dist/plugin.js CHANGED
@@ -10,10 +10,10 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
10
10
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
11
  };
12
12
  var _AwesomePlugin_writer, _AwesomePlugin_generate;
13
- import { getWorstStatus } from "@allurereport/core-api";
14
- import { convertToSummaryTestResult, } from "@allurereport/plugin-api";
13
+ import { createPluginSummary, } from "@allurereport/plugin-api";
15
14
  import { preciseTreeLabels } from "@allurereport/plugin-api";
16
15
  import { join } from "node:path";
16
+ import { applyCategoriesToTestResults, generateCategories } from "./categories.js";
17
17
  import { filterEnv } from "./environments.js";
18
18
  import { generateTimeline } from "./generateTimeline.js";
19
19
  import { generateAllCharts, generateAttachmentsFiles, generateEnvironmentJson, generateEnvirontmentsList, generateGlobals, generateHistoryDataPoints, generateNav, generateQualityGateResults, generateStaticFiles, generateStatistic, generateTestCases, generateTestEnvGroups, generateTestResults, generateTree, generateTreeFilters, generateVariables, } from "./generators.js";
@@ -24,10 +24,11 @@ export class AwesomePlugin {
24
24
  _AwesomePlugin_writer.set(this, void 0);
25
25
  _AwesomePlugin_generate.set(this, async (context, store) => {
26
26
  const { singleFile, groupBy = [], filter, appendTitlePath } = this.options ?? {};
27
+ const categories = context.categories ?? [];
27
28
  const environmentItems = await store.metadataByKey("allure_environment");
28
29
  const reportEnvironments = await store.allEnvironments();
29
30
  const attachments = await store.allAttachments();
30
- const allTrs = await store.allTestResults({ includeHidden: true });
31
+ const allTrs = await store.allTestResults({ includeHidden: true, filter });
31
32
  const statistics = await store.testsStatistic(filter);
32
33
  const environments = await store.allEnvironments();
33
34
  const envStatistics = new Map();
@@ -35,7 +36,7 @@ export class AwesomePlugin {
35
36
  const globalAttachments = await store.allGlobalAttachments();
36
37
  const globalExitCode = await store.globalExitCode();
37
38
  const globalErrors = await store.allGlobalErrors();
38
- const qualityGateResults = await store.qualityGateResults();
39
+ const qualityGateResults = await store.qualityGateResultsByEnv();
39
40
  for (const env of environments) {
40
41
  envStatistics.set(env, await store.testsStatistic(filterEnv(env, filter)));
41
42
  }
@@ -45,9 +46,18 @@ export class AwesomePlugin {
45
46
  envs: environments,
46
47
  });
47
48
  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);
49
+ const convertedTrs = await generateTestResults(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), store, allTrs);
50
+ applyCategoriesToTestResults(convertedTrs, categories);
51
+ await generateCategories(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), {
52
+ tests: convertedTrs,
53
+ categories,
54
+ environmentCount: environments.length,
55
+ environments,
56
+ defaultEnvironment: "default",
57
+ selectedEnvironmentCount: environments.length,
58
+ });
50
59
  const hasGroupBy = groupBy.length > 0;
60
+ await generateTimeline(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), convertedTrs, this.options);
51
61
  const treeLabels = hasGroupBy
52
62
  ? preciseTreeLabels(groupBy, convertedTrs, ({ labels }) => labels.map(({ name }) => name))
53
63
  : [];
@@ -62,8 +72,16 @@ export class AwesomePlugin {
62
72
  appendTitlePath,
63
73
  });
64
74
  await generateNav(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), envConvertedTrs, join(reportEnvironment, "nav.json"));
75
+ await generateCategories(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), {
76
+ tests: envConvertedTrs,
77
+ categories,
78
+ environmentCount: 1,
79
+ defaultEnvironment: "default",
80
+ selectedEnvironmentCount: 1,
81
+ filename: join(reportEnvironment, "categories.json"),
82
+ });
65
83
  }
66
- await generateTreeFilters(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), store);
84
+ await generateTreeFilters(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), convertedTrs);
67
85
  await generateEnvirontmentsList(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), store);
68
86
  await generateVariables(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), store);
69
87
  if (environmentItems?.length) {
@@ -114,29 +132,19 @@ export class AwesomePlugin {
114
132
  };
115
133
  }
116
134
  async info(context, store) {
117
- const allTrs = (await store.allTestResults()).filter((tr) => this.options.filter ? this.options.filter(tr) : true);
118
- const newTrs = await store.allNewTestResults();
119
- const retryTrs = allTrs.filter((tr) => !!tr?.retries?.length);
120
- const flakyTrs = allTrs.filter((tr) => !!tr?.flaky);
121
- const duration = allTrs.reduce((acc, { duration: trDuration = 0 }) => acc + trDuration, 0);
122
- const worstStatus = getWorstStatus(allTrs.map(({ status }) => status));
123
- const createdAt = allTrs.reduce((acc, { stop }) => Math.max(acc, stop || 0), 0);
124
- return {
135
+ return createPluginSummary({
125
136
  name: this.options.reportName || context.reportName,
126
- stats: await store.testsStatistic(this.options.filter),
127
- status: worstStatus ?? "passed",
128
- duration,
129
- createdAt,
130
137
  plugin: "Awesome",
131
- newTests: newTrs.map(convertToSummaryTestResult),
132
- flakyTests: flakyTrs.map(convertToSummaryTestResult),
133
- retryTests: retryTrs.map(convertToSummaryTestResult),
134
138
  meta: {
135
139
  reportId: context.reportUuid,
136
140
  singleFile: this.options.singleFile ?? false,
137
141
  withTestResultsLinks: true,
138
142
  },
139
- };
143
+ filter: this.options.filter,
144
+ ci: context.ci,
145
+ history: context.history,
146
+ store,
147
+ });
140
148
  }
141
149
  }
142
150
  _AwesomePlugin_writer = new WeakMap(), _AwesomePlugin_generate = new WeakMap();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/plugin-awesome",
3
- "version": "3.1.0",
3
+ "version": "3.3.1",
4
4
  "description": "Allure Awesome Plugin – brand new HTML report with modern design and new features",
5
5
  "keywords": [
6
6
  "allure",
@@ -30,18 +30,20 @@
30
30
  "test": "rimraf ./out && vitest run"
31
31
  },
32
32
  "dependencies": {
33
- "@allurereport/charts-api": "3.1.0",
34
- "@allurereport/core-api": "3.1.0",
35
- "@allurereport/plugin-api": "3.1.0",
36
- "@allurereport/web-awesome": "3.1.0",
37
- "@allurereport/web-commons": "3.1.0",
33
+ "@allurereport/charts-api": "3.3.1",
34
+ "@allurereport/core-api": "3.3.1",
35
+ "@allurereport/plugin-api": "3.3.1",
36
+ "@allurereport/web-awesome": "3.3.1",
37
+ "@allurereport/web-commons": "3.3.1",
38
38
  "d3-shape": "^3.2.0",
39
- "handlebars": "^4.7.8"
39
+ "handlebars": "^4.7.8",
40
+ "markdown-it": "^14.1.0"
40
41
  },
41
42
  "devDependencies": {
42
43
  "@stylistic/eslint-plugin": "^2.6.1",
43
44
  "@types/d3-shape": "^3.1.6",
44
45
  "@types/eslint": "^8.56.11",
46
+ "@types/markdown-it": "^14.1.2",
45
47
  "@types/node": "^20.17.9",
46
48
  "@typescript-eslint/eslint-plugin": "^8.0.0",
47
49
  "@typescript-eslint/parser": "^8.0.0",