@allurereport/plugin-awesome 3.20.1 → 3.22.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 +1 -0
- package/dist/categories.js +1 -0
- package/dist/converters.d.ts +5 -4
- package/dist/converters.js +21 -22
- package/dist/generators.d.ts +6 -4
- package/dist/generators.js +29 -35
- package/dist/model.d.ts +6 -1
- package/dist/plugin.js +20 -14
- package/dist/static/report.tar +0 -0
- package/package.json +19 -13
package/README.md
CHANGED
|
@@ -59,6 +59,7 @@ The plugin accepts the following options:
|
|
|
59
59
|
| `appendTitlePath`| Special marker for `groupBy`. Forces a final grouping by `titlePath` after all label-based groups. | `boolean` | `false` |
|
|
60
60
|
| `stepTreeExpansion` | Default expansion policy for step trees in test details. | `"collapsed" \| "expand_failed_only" \| "expanded"` | `"expand_failed_only"` |
|
|
61
61
|
| `defaultSortBy` | Default sort order for the test tree. Accepted values: `order,asc`, `order,desc`, `duration,asc`, `duration,desc`, `name,asc`, `name,desc`, `status,asc`, `status,desc`. User's manual selection is preserved in `localStorage` and takes priority over this value. | `string` | `order,asc` |
|
|
62
|
+
| `ideaLinks` | Adds an "Open in IDEA" link to tests that have a `testClass` label, pointing to the IntelliJ IDEA built-in server (`http://localhost:<port>/api/file?file=<path>`). Pass `true` for defaults or `{ port, fileExtension, sourceRoot }` (defaults: `63342`, `java`, none; `sourceRoot` is e.g. `src/test/java`). The link is added only when `testClass` looks like a class name (dot-separated identifiers). | `boolean \| { port?: number; fileExtension?: string; sourceRoot?: string }` | `false` |
|
|
62
63
|
|
|
63
64
|
### Default sort order
|
|
64
65
|
|
package/dist/categories.js
CHANGED
|
@@ -198,6 +198,7 @@ export const generateCategories = async (writer, { tests, categories, filename =
|
|
|
198
198
|
duration: tr.duration,
|
|
199
199
|
flaky: tr.flaky,
|
|
200
200
|
retriesCount: tr.retriesCount,
|
|
201
|
+
retriesStatusChange: tr.retriesStatusChange,
|
|
201
202
|
transition: tr.transition,
|
|
202
203
|
tooltips: tr.tooltips,
|
|
203
204
|
});
|
package/dist/converters.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
import type {
|
|
1
|
+
import { type TestResult } from "@allurereport/core-api";
|
|
2
|
+
import type { ReportTestResult } from "@allurereport/plugin-api";
|
|
3
|
+
import type { IdeaLinksOptions } from "./model.js";
|
|
3
4
|
export declare const convertTestResult: (tr: TestResult, options?: {
|
|
4
5
|
hideLabels?: readonly (string | RegExp)[];
|
|
6
|
+
ideaLinks?: boolean | IdeaLinksOptions;
|
|
7
|
+
resolutionEvaluatedAt?: number;
|
|
5
8
|
}) => ReportTestResult;
|
|
6
|
-
export declare const convertTestStepResult: (tsr: TestStepResult) => ReportTestStepResult;
|
|
7
|
-
export declare const convertFixtureResult: (fr: TestFixtureResult) => ReportFixtureResult;
|
package/dist/converters.js
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
|
-
import { createDictionary,
|
|
1
|
+
import { createDictionary, getMutedResolutionState, redactParameters, shouldHideLabel, } from "@allurereport/core-api";
|
|
2
|
+
import { convertTestStepResult } from "@allurereport/plugin-api/internal/report";
|
|
2
3
|
import MarkdownIt from "markdown-it";
|
|
3
4
|
const md = new MarkdownIt();
|
|
4
5
|
const markdownToHtml = (value) => (value ? md.render(value) : undefined);
|
|
6
|
+
const javaClassNameRegexp = /^[\p{L}_$][\p{L}\p{N}_$]*(\.[\p{L}_$][\p{L}\p{N}_$]*)*$/u;
|
|
7
|
+
const createIdeaLink = (labels, options) => {
|
|
8
|
+
const { port = 63342, fileExtension = "java", sourceRoot = "" } = options === true ? {} : options || {};
|
|
9
|
+
const testClass = labels.find(({ name, value }) => name === "testClass" && value)?.value;
|
|
10
|
+
const classPath = testClass?.split("$")[0].replaceAll(".", "/");
|
|
11
|
+
if (!testClass || !classPath || !javaClassNameRegexp.test(testClass)) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
const root = sourceRoot.replace(/^\/+|\/+$/g, "");
|
|
15
|
+
const file = `${root ? `${root}/` : ""}${classPath}.${fileExtension.replace(/^\./, "")}`;
|
|
16
|
+
return [
|
|
17
|
+
{ name: "Open in IDEA", type: "idea", url: `http://localhost:${port}/api/file?file=${encodeURIComponent(file)}` },
|
|
18
|
+
];
|
|
19
|
+
};
|
|
5
20
|
const mapLabelsByName = (labels) => {
|
|
6
21
|
return labels.reduce((acc, { name, value }) => {
|
|
7
22
|
acc[name] = acc[name] || [];
|
|
@@ -30,16 +45,20 @@ export const convertTestResult = (tr, options = {}) => {
|
|
|
30
45
|
known: tr.known,
|
|
31
46
|
resolution: tr.resolution,
|
|
32
47
|
resolutionComment: tr.resolutionComment,
|
|
48
|
+
resolutionExpiresAt: tr.resolutionExpiresAt,
|
|
49
|
+
resolutionState: getMutedResolutionState(tr, options.resolutionEvaluatedAt),
|
|
33
50
|
isRetry: tr.isRetry,
|
|
34
51
|
labels,
|
|
35
52
|
groupedLabels: mapLabelsByName(labels),
|
|
36
53
|
parameters: redactParameters(tr.parameters),
|
|
37
|
-
links: tr.links,
|
|
54
|
+
links: options.ideaLinks ? [...tr.links, ...createIdeaLink(tr.labels, options.ideaLinks)] : tr.links,
|
|
38
55
|
steps: (tr.steps ?? []).map(convertTestStepResult),
|
|
39
56
|
error: tr.error,
|
|
40
57
|
errors: tr.errors,
|
|
41
58
|
testCase: tr.testCase,
|
|
42
59
|
descriptionHtml: tr.descriptionHtml ?? markdownToHtml(tr.description),
|
|
60
|
+
preconditionHtml: tr.preconditionHtml ?? markdownToHtml(tr.precondition),
|
|
61
|
+
expectedResultHtml: tr.expectedResultHtml ?? markdownToHtml(tr.expectedResult),
|
|
43
62
|
environment: tr.environment,
|
|
44
63
|
setup: [],
|
|
45
64
|
teardown: [],
|
|
@@ -51,23 +70,3 @@ export const convertTestResult = (tr, options = {}) => {
|
|
|
51
70
|
titlePath: tr.titlePath || [],
|
|
52
71
|
};
|
|
53
72
|
};
|
|
54
|
-
export const convertTestStepResult = (tsr) => {
|
|
55
|
-
if (isStep(tsr)) {
|
|
56
|
-
return {
|
|
57
|
-
...tsr,
|
|
58
|
-
parameters: redactParameters(tsr.parameters),
|
|
59
|
-
steps: (tsr.steps ?? []).map(convertTestStepResult),
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
return tsr;
|
|
63
|
-
};
|
|
64
|
-
export const convertFixtureResult = (fr) => {
|
|
65
|
-
return {
|
|
66
|
-
id: fr.id,
|
|
67
|
-
type: fr.type,
|
|
68
|
-
name: fr.name,
|
|
69
|
-
status: fr.status,
|
|
70
|
-
steps: fr.steps.map(convertTestStepResult),
|
|
71
|
-
duration: fr.duration,
|
|
72
|
-
};
|
|
73
|
-
};
|
package/dist/generators.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { type AttachmentLink, type EnvironmentIdentity, type EnvironmentItem, type HistoryTestResultUrlResolver, type MetricSample, type Statistic, type TestEnvGroup, type TestResult } from "@allurereport/core-api";
|
|
2
|
-
import type { AllureStore, ReportExecutorInfo, ReportRunSummary, ReportTestResult, GlobalAttachmentLink, ExitCode, PluginContext, PluginGlobalError, QualityGateValidationResult, ReportFiles, ResultFile, TestResultRelatedData } from "@allurereport/plugin-api";
|
|
3
|
-
import type { AwesomeOptions,
|
|
2
|
+
import type { AllureStore, ReportExecutorInfo, ReportGitInfo, ReportRunSummary, ReportTestResult, GlobalAttachmentLink, ExitCode, PluginContext, PluginGlobalError, QualityGateValidationResult, ReportFiles, ResultFile, TestResultRelatedData } from "@allurereport/plugin-api";
|
|
3
|
+
import type { AwesomeOptions, IdeaLinksOptions } from "./model.js";
|
|
4
4
|
import type { AwesomeDataWriter, ReportFile } from "./writer.js";
|
|
5
|
-
export declare const readTemplateManifest: (_singleFileMode?: boolean) => Promise<TemplateManifest>;
|
|
6
5
|
export declare const generateTestResults: (_writer: AwesomeDataWriter, store: AllureStore, trs: TestResult[], options: {
|
|
7
6
|
pluginId: string;
|
|
8
7
|
hideLabels?: readonly (string | RegExp)[];
|
|
8
|
+
ideaLinks?: boolean | IdeaLinksOptions;
|
|
9
9
|
related?: TestResultRelatedData;
|
|
10
10
|
resolveHistoryUrl?: HistoryTestResultUrlResolver;
|
|
11
|
+
resolutionEvaluatedAt?: number;
|
|
11
12
|
}) => Promise<ReportTestResult[]>;
|
|
12
13
|
export declare const generateTestCases: (writer: AwesomeDataWriter, trs: ReportTestResult[]) => Promise<void>;
|
|
13
14
|
export declare const generateTestEnvGroups: (writer: AwesomeDataWriter, groups: TestEnvGroup[]) => Promise<void>;
|
|
@@ -29,7 +30,6 @@ export declare const generateStatistic: (writer: AwesomeDataWriter, data: {
|
|
|
29
30
|
envs: EnvironmentIdentity[];
|
|
30
31
|
}) => Promise<void>;
|
|
31
32
|
export declare const generateAttachmentsFiles: (writer: AwesomeDataWriter, attachmentLinks: AttachmentLink[], contentFunction: (id: string) => Promise<ResultFile | undefined>) => Promise<Map<string, string>>;
|
|
32
|
-
export declare const generateHistoryDataPoints: (writer: AwesomeDataWriter, store: AllureStore) => Promise<Map<string, string>>;
|
|
33
33
|
export declare const generateGlobals: (writer: AwesomeDataWriter, payload: {
|
|
34
34
|
globalExitCode?: ExitCode;
|
|
35
35
|
globalAttachments?: GlobalAttachmentLink[];
|
|
@@ -50,6 +50,8 @@ export declare const generateStaticFiles: (payload: AwesomeOptions & {
|
|
|
50
50
|
reportDataFiles: ReportFile[];
|
|
51
51
|
reportUuid: string;
|
|
52
52
|
reportName: string;
|
|
53
|
+
overviewHref?: string;
|
|
54
|
+
git?: ReportGitInfo;
|
|
53
55
|
executor?: ReportExecutorInfo;
|
|
54
56
|
runSummary?: ReportRunSummary;
|
|
55
57
|
runSummaryByEnv?: Record<string, ReportRunSummary>;
|
package/dist/generators.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { defaultChartsConfig } from "@allurereport/charts-api";
|
|
3
|
-
import { appLoaderFaviconDataUri, appLoaderStyles, compareBy, createAppLoaderMarkup, createBaseUrlScript, createFaviconLinkTag, createFontLinkTag,
|
|
3
|
+
import { appLoaderFaviconDataUri, appLoaderStyles, compareBy, createAppLoaderMarkup, createBaseUrlScript, createFaviconLinkTag, createFontLinkTag, injectReportDataScript, reportDataScriptPlaceholder, stringifyForInlineScript, createScriptTag, createStylesLinkTag, hasRetriesStatusChange, incrementStatistic, joinPosixPath, nullsLast, ordinal, parseResolutionExpiresAt, redactParameters, severityLabelName, } from "@allurereport/core-api";
|
|
4
4
|
import { collapseTreeGroups, createTreeByLabels, createTreeByLabelsAndTitlePath, createTreeByTitlePath, preciseTreeLabels, processTree, } from "@allurereport/plugin-api";
|
|
5
|
-
import {
|
|
5
|
+
import { convertFixtureResult, mapConcurrently, writeConcurrently } from "@allurereport/plugin-api/internal/report";
|
|
6
|
+
import { createSingleFileScripts, copyReportStaticAssets, getReportStaticAsset, readReportStaticAssets, } from "@allurereport/plugin-api/static-assets";
|
|
6
7
|
import { generateCharts, getPieChartValues } from "@allurereport/web-commons";
|
|
7
8
|
import Handlebars from "handlebars";
|
|
8
|
-
import {
|
|
9
|
+
import { convertTestResult } from "./converters.js";
|
|
9
10
|
const reportStaticArchive = new URL("../dist/static/report.tar", import.meta.url);
|
|
10
11
|
const template = `<!DOCTYPE html>
|
|
11
12
|
<html dir="ltr" lang="en">
|
|
@@ -46,10 +47,6 @@ const template = `<!DOCTYPE html>
|
|
|
46
47
|
</html>
|
|
47
48
|
`;
|
|
48
49
|
const compiledTemplate = Handlebars.compile(template);
|
|
49
|
-
export const readTemplateManifest = async (_singleFileMode) => {
|
|
50
|
-
const { manifest } = await readReportStaticAssets(reportStaticArchive);
|
|
51
|
-
return manifest;
|
|
52
|
-
};
|
|
53
50
|
const createBreadcrumbs = (convertedTr) => {
|
|
54
51
|
const labelsByType = convertedTr.labels.reduce((acc, label) => {
|
|
55
52
|
if (!acc[label.name]) {
|
|
@@ -73,18 +70,6 @@ const createBreadcrumbs = (convertedTr) => {
|
|
|
73
70
|
return acc;
|
|
74
71
|
}, []);
|
|
75
72
|
};
|
|
76
|
-
const writeConcurrently = async (items, write, concurrency = 64) => {
|
|
77
|
-
for (let i = 0; i < items.length; i += concurrency) {
|
|
78
|
-
await Promise.all(items.slice(i, i + concurrency).map(write));
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
const mapConcurrently = async (items, map, concurrency = 8) => {
|
|
82
|
-
const results = [];
|
|
83
|
-
for (let i = 0; i < items.length; i += concurrency) {
|
|
84
|
-
results.push(...(await Promise.all(items.slice(i, i + concurrency).map(map))));
|
|
85
|
-
}
|
|
86
|
-
return results;
|
|
87
|
-
};
|
|
88
73
|
export const generateTestResults = async (_writer, store, trs, options) => {
|
|
89
74
|
let convertedTrs = [];
|
|
90
75
|
const related = options.related ?? (await store.relatedByTestResultIds(trs.map(({ id }) => id)));
|
|
@@ -96,6 +81,8 @@ export const generateTestResults = async (_writer, store, trs, options) => {
|
|
|
96
81
|
.map(convertFixtureResult);
|
|
97
82
|
const convertedTr = convertTestResult(tr, {
|
|
98
83
|
hideLabels: options.hideLabels,
|
|
84
|
+
ideaLinks: options.ideaLinks,
|
|
85
|
+
resolutionEvaluatedAt: options.resolutionEvaluatedAt,
|
|
99
86
|
});
|
|
100
87
|
convertedTr.history = (related.historyByTrId.get(tr.id) ?? []).map((item) => ({
|
|
101
88
|
...item,
|
|
@@ -104,6 +91,7 @@ export const generateTestResults = async (_writer, store, trs, options) => {
|
|
|
104
91
|
convertedTr.retries = related.retriesByTrId.get(tr.id) ?? [];
|
|
105
92
|
convertedTr.retriesCount = convertedTr.retries.length;
|
|
106
93
|
convertedTr.retry = convertedTr.retriesCount > 0;
|
|
94
|
+
convertedTr.retriesStatusChange = hasRetriesStatusChange(tr, convertedTr.retries);
|
|
107
95
|
convertedTr.isRetry = tr.isRetry;
|
|
108
96
|
convertedTr.setup = convertedTrFixtures.filter((f) => f.type === "before");
|
|
109
97
|
convertedTr.teardown = convertedTrFixtures.filter((f) => f.type === "after");
|
|
@@ -137,7 +125,9 @@ export const generateNav = async (writer, trs, filename = "nav.json") => {
|
|
|
137
125
|
};
|
|
138
126
|
const SEARCHABLE_LABELS = new Set([
|
|
139
127
|
"owner",
|
|
128
|
+
"parentSuite",
|
|
140
129
|
"suite",
|
|
130
|
+
"subSuite",
|
|
141
131
|
"package",
|
|
142
132
|
"testClass",
|
|
143
133
|
"testMethod",
|
|
@@ -175,6 +165,7 @@ const searchDocumentFactory = (test) => {
|
|
|
175
165
|
id: test.id,
|
|
176
166
|
nodeId: test.id,
|
|
177
167
|
name: test.name,
|
|
168
|
+
titlePath: joinSearchValues(test.titlePath ?? []),
|
|
178
169
|
fullName: test.fullName,
|
|
179
170
|
retryHash: test.retryHash,
|
|
180
171
|
labels: joinSearchValues(labels),
|
|
@@ -282,7 +273,7 @@ const buildTreeByTitlePath = (tests) => {
|
|
|
282
273
|
};
|
|
283
274
|
};
|
|
284
275
|
const buildTreeByLabelsAndTitlePathCombined = (tests, labels) => collapseTreeGroups(createTreeByLabelsAndTitlePath(tests, labels, leafFactory, undefined, (group, leaf) => incrementStatistic(group.statistic, leaf.status)));
|
|
285
|
-
const leafFactory = ({ id, name, status, duration, flaky, start, retry, retriesCount, resolution, transition, tooltips, retryHash, groupedLabels, categories, parameters, }) => {
|
|
276
|
+
const leafFactory = ({ id, name, status, duration, flaky, start, retry, retriesCount, retriesStatusChange, resolution, resolutionExpiresAt, resolutionState, transition, tooltips, retryHash, groupedLabels, categories, parameters, }) => {
|
|
286
277
|
const unresolvedFailure = (status === "failed" || status === "broken") && !resolution;
|
|
287
278
|
const parameterValues = redactParameters(parameters).flatMap(({ value }) => (value ? [value] : []));
|
|
288
279
|
const leaf = {
|
|
@@ -295,7 +286,10 @@ const leafFactory = ({ id, name, status, duration, flaky, start, retry, retriesC
|
|
|
295
286
|
start,
|
|
296
287
|
retry,
|
|
297
288
|
retriesCount,
|
|
289
|
+
retriesStatusChange,
|
|
298
290
|
resolution,
|
|
291
|
+
resolutionExpiresAt,
|
|
292
|
+
resolutionState,
|
|
299
293
|
resolutionStatus: resolution ?? (unresolvedFailure ? "none" : undefined),
|
|
300
294
|
transition,
|
|
301
295
|
tooltips,
|
|
@@ -332,6 +326,7 @@ const resolutionTestResultFactory = (test, index) => ({
|
|
|
332
326
|
transition: test.transition,
|
|
333
327
|
retry: test.retry,
|
|
334
328
|
retriesCount: test.retriesCount,
|
|
329
|
+
retriesStatusChange: test.retriesStatusChange,
|
|
335
330
|
resolution: test.resolution,
|
|
336
331
|
groupOrder: index + 1,
|
|
337
332
|
tooltips: test.tooltips,
|
|
@@ -342,14 +337,21 @@ export const generateResolutionCategories = async (writer, tests, filename = "re
|
|
|
342
337
|
.filter((test) => !test.isRetry && test.resolution)
|
|
343
338
|
.forEach((test) => {
|
|
344
339
|
const resolution = test.resolution;
|
|
340
|
+
const mutedExpirationKey = test.resolutionExpiresAt === undefined
|
|
341
|
+
? "forever"
|
|
342
|
+
: (parseResolutionExpiresAt(test.resolutionExpiresAt)?.toString() ?? `invalid:${test.resolutionExpiresAt}`);
|
|
345
343
|
const groupId = resolution === "issue"
|
|
346
344
|
? `${resolution}:${test.resolutionIssue?.id ?? test.id}`
|
|
347
|
-
:
|
|
345
|
+
: [resolution, test.resolutionComment ?? test.id, resolution === "muted" ? mutedExpirationKey : undefined]
|
|
346
|
+
.filter(Boolean)
|
|
347
|
+
.join(":");
|
|
348
348
|
const group = groupsById.get(groupId) ?? {
|
|
349
349
|
id: groupId,
|
|
350
350
|
resolution,
|
|
351
351
|
name: getResolutionGroupName(test),
|
|
352
352
|
comment: test.resolutionComment ?? test.resolutionIssue?.comment,
|
|
353
|
+
...(test.resolutionExpiresAt ? { expiresAt: test.resolutionExpiresAt } : {}),
|
|
354
|
+
...(test.resolutionState ? { resolutionState: test.resolutionState } : {}),
|
|
353
355
|
issue: test.resolutionIssue,
|
|
354
356
|
testResults: [],
|
|
355
357
|
};
|
|
@@ -406,15 +408,6 @@ export const generateAttachmentsFiles = async (writer, attachmentLinks, contentF
|
|
|
406
408
|
});
|
|
407
409
|
return new Map(writtenAttachments.filter((attachment) => attachment !== undefined));
|
|
408
410
|
};
|
|
409
|
-
export const generateHistoryDataPoints = async (writer, store) => {
|
|
410
|
-
const result = new Map();
|
|
411
|
-
const allHistoryPoints = await store.allHistoryDataPoints();
|
|
412
|
-
for (const historyPoint of allHistoryPoints.slice(0, 6)) {
|
|
413
|
-
const src = `history/${historyPoint.uuid}.json`;
|
|
414
|
-
await writer.writeData(src, historyPoint);
|
|
415
|
-
}
|
|
416
|
-
return result;
|
|
417
|
-
};
|
|
418
411
|
export const generateGlobals = async (writer, payload) => {
|
|
419
412
|
const { globalExitCode, globalAttachments = [], globalAttachmentsByEnv = {}, globalErrors = [], globalErrorsByEnv = {}, contentFunction, } = payload;
|
|
420
413
|
const globals = {
|
|
@@ -478,7 +471,7 @@ export const generateQualityGateResults = async (writer, qualityGateResults = {}
|
|
|
478
471
|
await writer.writeWidget("quality-gate.json", resultsWithTrees);
|
|
479
472
|
};
|
|
480
473
|
export const generateStaticFiles = async (payload) => {
|
|
481
|
-
const { id, reportName = "Allure Report", reportLanguage = "en", logo = "", theme = "auto", groupBy, reportFiles, reportDataFiles, reportUuid, allureVersion, layout = "base", defaultSection = "", ci, executor, runSummary, runSummaryByEnv, stepTreeExpansion, defaultSortBy, } = payload;
|
|
474
|
+
const { id, reportName = "Allure Report", reportLanguage = "en", logo = "", theme = "auto", groupBy, reportFiles, reportDataFiles, reportUuid, allureVersion, layout = "base", defaultSection = "", ci, git, executor, runSummary, runSummaryByEnv, stepTreeExpansion, defaultSortBy, overviewHref, } = payload;
|
|
482
475
|
const staticAssets = await readReportStaticAssets(reportStaticArchive);
|
|
483
476
|
const { manifest } = staticAssets;
|
|
484
477
|
const headTags = [];
|
|
@@ -506,8 +499,7 @@ export const generateStaticFiles = async (payload) => {
|
|
|
506
499
|
const mainCssContent = getReportStaticAsset(staticAssets, mainCss);
|
|
507
500
|
headTags.push(createStylesLinkTag(`data:text/css;base64,${mainCssContent.toString("base64")}`));
|
|
508
501
|
}
|
|
509
|
-
|
|
510
|
-
bodyTags.push(createScriptTag(`data:text/javascript;base64,${mainJsContent.toString("base64")}`));
|
|
502
|
+
bodyTags.push(createSingleFileScripts(staticAssets.files, mainJs));
|
|
511
503
|
}
|
|
512
504
|
const now = Date.now();
|
|
513
505
|
const reportOptions = {
|
|
@@ -521,6 +513,7 @@ export const generateStaticFiles = async (payload) => {
|
|
|
521
513
|
groupBy: groupBy?.length ? groupBy : [],
|
|
522
514
|
cacheKey: now.toString(),
|
|
523
515
|
ci,
|
|
516
|
+
git,
|
|
524
517
|
executor,
|
|
525
518
|
runSummary,
|
|
526
519
|
runSummaryByEnv,
|
|
@@ -530,12 +523,13 @@ export const generateStaticFiles = async (payload) => {
|
|
|
530
523
|
defaultSection,
|
|
531
524
|
stepTreeExpansion,
|
|
532
525
|
defaultSortBy,
|
|
526
|
+
overviewHref,
|
|
533
527
|
};
|
|
534
528
|
try {
|
|
535
529
|
const html = compiledTemplate({
|
|
536
530
|
headTags: headTags.join("\n"),
|
|
537
531
|
bodyTags: bodyTags.join("\n"),
|
|
538
|
-
reportFilesScript:
|
|
532
|
+
reportFilesScript: reportDataScriptPlaceholder,
|
|
539
533
|
reportOptions: stringifyForInlineScript(reportOptions),
|
|
540
534
|
analyticsEnable: true,
|
|
541
535
|
allureVersion,
|
|
@@ -543,7 +537,7 @@ export const generateStaticFiles = async (payload) => {
|
|
|
543
537
|
reportName,
|
|
544
538
|
singleFile: payload.singleFile,
|
|
545
539
|
});
|
|
546
|
-
await reportFiles.addFile("index.html",
|
|
540
|
+
await reportFiles.addFile("index.html", injectReportDataScript(html, reportDataFiles));
|
|
547
541
|
}
|
|
548
542
|
catch (err) {
|
|
549
543
|
if (err instanceof RangeError) {
|
package/dist/model.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { ChartOptions } from "@allurereport/charts-api";
|
|
2
2
|
import type { CiDescriptor, EnvironmentsConfig, TestResult } from "@allurereport/core-api";
|
|
3
3
|
import type { StepTreeExpansion } from "@allurereport/plugin-api";
|
|
4
|
+
export type IdeaLinksOptions = {
|
|
5
|
+
port?: number;
|
|
6
|
+
fileExtension?: string;
|
|
7
|
+
sourceRoot?: string;
|
|
8
|
+
};
|
|
4
9
|
export type AwesomeOptions = {
|
|
5
10
|
reportName?: string;
|
|
6
11
|
singleFile?: boolean;
|
|
@@ -22,6 +27,6 @@ export type AwesomeOptions = {
|
|
|
22
27
|
appendTitlePath?: boolean;
|
|
23
28
|
stepTreeExpansion?: StepTreeExpansion;
|
|
24
29
|
defaultSortBy?: string;
|
|
30
|
+
ideaLinks?: boolean | IdeaLinksOptions;
|
|
25
31
|
};
|
|
26
|
-
export type TemplateManifest = Record<string, string>;
|
|
27
32
|
export type AwesomePluginOptions = AwesomeOptions;
|
package/dist/plugin.js
CHANGED
|
@@ -10,14 +10,17 @@ 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_generateAfterStart, _AwesomePlugin_generate;
|
|
13
|
-
import { incrementStatistic, validateEnvironmentId, joinPosixPath, } from "@allurereport/core-api";
|
|
13
|
+
import { incrementStatistic, hasRetriesStatusChange, isIgnoredResolution, validateEnvironmentId, joinPosixPath, } from "@allurereport/core-api";
|
|
14
|
+
import { collectGitHead } from "@allurereport/git";
|
|
14
15
|
import { createPluginSummary, } from "@allurereport/plugin-api";
|
|
15
16
|
import { preciseTreeLabels } from "@allurereport/plugin-api";
|
|
17
|
+
import { generateHistoryDataPoints } from "@allurereport/plugin-api/internal/report";
|
|
18
|
+
import { validateChartsOptions } from "@allurereport/web-commons";
|
|
16
19
|
import { applyCategoriesToTestResults, generateCategories } from "./categories.js";
|
|
17
20
|
import { generateTimeline } from "./generateTimeline.js";
|
|
18
|
-
import { generateAllCharts, generateAttachmentsFiles, generateEnvironmentJson, generateEnvirontmentsList, generateGlobals,
|
|
21
|
+
import { generateAllCharts, generateAttachmentsFiles, generateEnvironmentJson, generateEnvirontmentsList, generateGlobals, generateMetricsWidget, generateNav, generateQualityGateResults, generateResolutionCategories, generateSearchIndex, generateStaticFiles, generateStatistic, generateTestCases, generateTestEnvGroups, generateTestResults, generateTree, generateTreeFilters, generateVariables, getRunSummary, } from "./generators.js";
|
|
19
22
|
import { InMemoryReportDataWriter, ReportFileDataWriter } from "./writer.js";
|
|
20
|
-
const statisticByTestResults = (testResults,
|
|
23
|
+
const statisticByTestResults = (testResults, retriesByTrId) => {
|
|
21
24
|
const statistic = { total: 0 };
|
|
22
25
|
const incrementResolution = (testResult) => {
|
|
23
26
|
if (testResult.resolution === "issue") {
|
|
@@ -38,9 +41,13 @@ const statisticByTestResults = (testResults, trIdsWithRetries) => {
|
|
|
38
41
|
continue;
|
|
39
42
|
}
|
|
40
43
|
incrementStatistic(statistic, testResult.status);
|
|
41
|
-
|
|
44
|
+
const retries = retriesByTrId.get(testResult.id) ?? [];
|
|
45
|
+
if (retries.length > 0) {
|
|
42
46
|
statistic.retries = (statistic.retries ?? 0) + 1;
|
|
43
47
|
}
|
|
48
|
+
if (hasRetriesStatusChange(testResult, retries)) {
|
|
49
|
+
statistic.retriesStatusChange = (statistic.retriesStatusChange ?? 0) + 1;
|
|
50
|
+
}
|
|
44
51
|
if (testResult.flaky) {
|
|
45
52
|
statistic.flaky = (statistic.flaky ?? 0) + 1;
|
|
46
53
|
}
|
|
@@ -51,7 +58,6 @@ const statisticByTestResults = (testResults, trIdsWithRetries) => {
|
|
|
51
58
|
}
|
|
52
59
|
return statistic;
|
|
53
60
|
};
|
|
54
|
-
const isActiveStatisticTestResult = (testResult) => testResult.resolution !== "muted" && testResult.resolution !== "accepted";
|
|
55
61
|
export class AwesomePlugin {
|
|
56
62
|
constructor(options = {}) {
|
|
57
63
|
this.options = options;
|
|
@@ -64,6 +70,7 @@ export class AwesomePlugin {
|
|
|
64
70
|
});
|
|
65
71
|
_AwesomePlugin_generate.set(this, async (context, store) => {
|
|
66
72
|
const { singleFile, groupBy = [], filter, appendTitlePath } = this.options ?? {};
|
|
73
|
+
const resolutionEvaluatedAt = Date.now();
|
|
67
74
|
const perf = context.perf;
|
|
68
75
|
const measure = (name, fn) => perf?.measure(name, fn) ?? fn();
|
|
69
76
|
const hideLabels = context.hideLabels;
|
|
@@ -117,15 +124,9 @@ export class AwesomePlugin {
|
|
|
117
124
|
});
|
|
118
125
|
const trsByEnvId = new Map();
|
|
119
126
|
await measure("stats", async () => {
|
|
120
|
-
const trIdsWithRetries = new Set();
|
|
121
127
|
const envStatistics = new Map();
|
|
122
128
|
const pieEnvStatistics = new Map();
|
|
123
|
-
|
|
124
|
-
if (retries.length > 0) {
|
|
125
|
-
trIdsWithRetries.add(trId);
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
const pieStatistics = statisticByTestResults(allTrs.filter(isActiveStatisticTestResult), trIdsWithRetries);
|
|
129
|
+
const pieStatistics = statisticByTestResults(allTrs.filter((testResult) => !isIgnoredResolution(testResult, resolutionEvaluatedAt)), related.retriesByTrId);
|
|
129
130
|
for (const tr of allTrs) {
|
|
130
131
|
const environmentId = envIdByTrId.get(tr.id);
|
|
131
132
|
if (!environmentId) {
|
|
@@ -141,8 +142,8 @@ export class AwesomePlugin {
|
|
|
141
142
|
}
|
|
142
143
|
await Promise.all(environments.map(async ({ id }) => {
|
|
143
144
|
const envTrs = trsByEnvId.get(id) ?? [];
|
|
144
|
-
envStatistics.set(id, statisticByTestResults(envTrs,
|
|
145
|
-
pieEnvStatistics.set(id, statisticByTestResults(envTrs.filter(
|
|
145
|
+
envStatistics.set(id, statisticByTestResults(envTrs, related.retriesByTrId));
|
|
146
|
+
pieEnvStatistics.set(id, statisticByTestResults(envTrs.filter((testResult) => !isIgnoredResolution(testResult, resolutionEvaluatedAt)), related.retriesByTrId));
|
|
146
147
|
}));
|
|
147
148
|
await generateStatistic(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), {
|
|
148
149
|
stats: statistics,
|
|
@@ -164,8 +165,10 @@ export class AwesomePlugin {
|
|
|
164
165
|
const convertedTrs = await measure("convert", () => generateTestResults(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), store, allTrs, {
|
|
165
166
|
pluginId: context.id,
|
|
166
167
|
hideLabels,
|
|
168
|
+
ideaLinks: this.options.ideaLinks,
|
|
167
169
|
related,
|
|
168
170
|
resolveHistoryUrl: context.history?.resolveTestResultUrl,
|
|
171
|
+
resolutionEvaluatedAt,
|
|
169
172
|
}));
|
|
170
173
|
if (perf) {
|
|
171
174
|
perf.count("convertedTestResults.count", convertedTrs.length, {
|
|
@@ -263,7 +266,9 @@ export class AwesomePlugin {
|
|
|
263
266
|
reportFiles: context.reportFiles,
|
|
264
267
|
reportUuid: context.reportUuid,
|
|
265
268
|
reportName: context.reportName,
|
|
269
|
+
overviewHref: context.overviewHref,
|
|
266
270
|
ci: context.ci,
|
|
271
|
+
git: collectGitHead(),
|
|
267
272
|
executor,
|
|
268
273
|
runSummary,
|
|
269
274
|
runSummaryByEnv,
|
|
@@ -285,6 +290,7 @@ export class AwesomePlugin {
|
|
|
285
290
|
this.done = async (context, store) => {
|
|
286
291
|
await __classPrivateFieldGet(this, _AwesomePlugin_generateAfterStart, "f").call(this, context, store);
|
|
287
292
|
};
|
|
293
|
+
validateChartsOptions(options.charts ?? []);
|
|
288
294
|
}
|
|
289
295
|
async info(context, store) {
|
|
290
296
|
const perf = context.perf;
|
package/dist/static/report.tar
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/plugin-awesome",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.22.0",
|
|
4
4
|
"description": "Allure Awesome Plugin – brand new HTML report with modern design and new features",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure",
|
|
@@ -23,31 +23,37 @@
|
|
|
23
23
|
".": "./dist/index.js"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
|
-
"build": "run clean && tsc --project ./tsconfig.json && node ../../scripts/pack-report-static.mjs ../web-awesome/dist/multi ./dist/static/report.tar",
|
|
26
|
+
"build": "run clean && tsc --project ./tsconfig.json && node ../../scripts/pack-report-static.mjs ../web-awesome/dist/multi ./dist/static/report.tar --allow-chunks",
|
|
27
27
|
"clean": "rimraf ./dist",
|
|
28
|
-
"test": "rimraf
|
|
29
|
-
"
|
|
30
|
-
"lint
|
|
28
|
+
"test": "rimraf out && vp test run",
|
|
29
|
+
"test:unit": "yarn test",
|
|
30
|
+
"lint": "vp lint --import-plugin src test features stories",
|
|
31
|
+
"lint:fix": "vp lint --import-plugin --fix src test features stories"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
|
-
"@allurereport/charts-api": "3.
|
|
34
|
-
"@allurereport/core-api": "3.
|
|
35
|
-
"@allurereport/
|
|
36
|
-
"@allurereport/
|
|
34
|
+
"@allurereport/charts-api": "3.22.0",
|
|
35
|
+
"@allurereport/core-api": "3.22.0",
|
|
36
|
+
"@allurereport/git": "3.22.0",
|
|
37
|
+
"@allurereport/plugin-api": "3.22.0",
|
|
38
|
+
"@allurereport/web-commons": "3.22.0",
|
|
37
39
|
"d3-shape": "^3.2.0",
|
|
38
|
-
"handlebars": "
|
|
39
|
-
"markdown-it": "^
|
|
40
|
+
"handlebars": "4.7.10",
|
|
41
|
+
"markdown-it": "^15.0.3"
|
|
40
42
|
},
|
|
41
43
|
"devDependencies": {
|
|
42
|
-
"@allurereport/
|
|
44
|
+
"@allurereport/common-config": "3.22.0",
|
|
45
|
+
"@allurereport/web-awesome": "3.22.0",
|
|
43
46
|
"@types/d3-shape": "^3.1.8",
|
|
44
47
|
"@types/markdown-it": "^14.1.2",
|
|
45
48
|
"@types/node": "^20",
|
|
49
|
+
"@vitest/coverage-istanbul": "5.0.4",
|
|
46
50
|
"@vitest/runner": "^2",
|
|
47
51
|
"allure-js-commons": "^3",
|
|
48
52
|
"allure-vitest": "^3",
|
|
49
53
|
"rimraf": "^6",
|
|
50
54
|
"typescript": "^5",
|
|
51
|
-
"
|
|
55
|
+
"vite": "@voidzero-dev/vite-plus-core@1.2.0",
|
|
56
|
+
"vite-plus": "1.2.0",
|
|
57
|
+
"vitest": "5.0.4"
|
|
52
58
|
}
|
|
53
59
|
}
|