@allurereport/plugin-awesome 3.21.0 → 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/converters.d.ts +5 -4
- package/dist/converters.js +21 -22
- package/dist/generators.d.ts +5 -4
- package/dist/generators.js +19 -32
- package/dist/model.d.ts +6 -1
- package/dist/plugin.js +12 -5
- package/dist/static/report.tar +0 -0
- package/package.json +16 -13
- package/dist/singleFileAssets.d.ts +0 -1
- package/dist/singleFileAssets.js +0 -81
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/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[];
|
|
@@ -51,6 +51,7 @@ export declare const generateStaticFiles: (payload: AwesomeOptions & {
|
|
|
51
51
|
reportUuid: string;
|
|
52
52
|
reportName: string;
|
|
53
53
|
overviewHref?: string;
|
|
54
|
+
git?: ReportGitInfo;
|
|
54
55
|
executor?: ReportExecutorInfo;
|
|
55
56
|
runSummary?: ReportRunSummary;
|
|
56
57
|
runSummaryByEnv?: Record<string, ReportRunSummary>;
|
package/dist/generators.js
CHANGED
|
@@ -1,12 +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, injectReportDataScript, reportDataScriptPlaceholder, stringifyForInlineScript, createScriptTag, createStylesLinkTag, hasRetriesStatusChange, incrementStatistic, joinPosixPath, nullsLast, ordinal, redactParameters, severityLabelName, } from "@allurereport/core-api";
|
|
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 { createSingleFileScripts } from "./singleFileAssets.js";
|
|
9
|
+
import { convertTestResult } from "./converters.js";
|
|
10
10
|
const reportStaticArchive = new URL("../dist/static/report.tar", import.meta.url);
|
|
11
11
|
const template = `<!DOCTYPE html>
|
|
12
12
|
<html dir="ltr" lang="en">
|
|
@@ -47,10 +47,6 @@ const template = `<!DOCTYPE html>
|
|
|
47
47
|
</html>
|
|
48
48
|
`;
|
|
49
49
|
const compiledTemplate = Handlebars.compile(template);
|
|
50
|
-
export const readTemplateManifest = async (_singleFileMode) => {
|
|
51
|
-
const { manifest } = await readReportStaticAssets(reportStaticArchive);
|
|
52
|
-
return manifest;
|
|
53
|
-
};
|
|
54
50
|
const createBreadcrumbs = (convertedTr) => {
|
|
55
51
|
const labelsByType = convertedTr.labels.reduce((acc, label) => {
|
|
56
52
|
if (!acc[label.name]) {
|
|
@@ -74,18 +70,6 @@ const createBreadcrumbs = (convertedTr) => {
|
|
|
74
70
|
return acc;
|
|
75
71
|
}, []);
|
|
76
72
|
};
|
|
77
|
-
const writeConcurrently = async (items, write, concurrency = 64) => {
|
|
78
|
-
for (let i = 0; i < items.length; i += concurrency) {
|
|
79
|
-
await Promise.all(items.slice(i, i + concurrency).map(write));
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
const mapConcurrently = async (items, map, concurrency = 8) => {
|
|
83
|
-
const results = [];
|
|
84
|
-
for (let i = 0; i < items.length; i += concurrency) {
|
|
85
|
-
results.push(...(await Promise.all(items.slice(i, i + concurrency).map(map))));
|
|
86
|
-
}
|
|
87
|
-
return results;
|
|
88
|
-
};
|
|
89
73
|
export const generateTestResults = async (_writer, store, trs, options) => {
|
|
90
74
|
let convertedTrs = [];
|
|
91
75
|
const related = options.related ?? (await store.relatedByTestResultIds(trs.map(({ id }) => id)));
|
|
@@ -97,6 +81,8 @@ export const generateTestResults = async (_writer, store, trs, options) => {
|
|
|
97
81
|
.map(convertFixtureResult);
|
|
98
82
|
const convertedTr = convertTestResult(tr, {
|
|
99
83
|
hideLabels: options.hideLabels,
|
|
84
|
+
ideaLinks: options.ideaLinks,
|
|
85
|
+
resolutionEvaluatedAt: options.resolutionEvaluatedAt,
|
|
100
86
|
});
|
|
101
87
|
convertedTr.history = (related.historyByTrId.get(tr.id) ?? []).map((item) => ({
|
|
102
88
|
...item,
|
|
@@ -287,7 +273,7 @@ const buildTreeByTitlePath = (tests) => {
|
|
|
287
273
|
};
|
|
288
274
|
};
|
|
289
275
|
const buildTreeByLabelsAndTitlePathCombined = (tests, labels) => collapseTreeGroups(createTreeByLabelsAndTitlePath(tests, labels, leafFactory, undefined, (group, leaf) => incrementStatistic(group.statistic, leaf.status)));
|
|
290
|
-
const leafFactory = ({ id, name, status, duration, flaky, start, retry, retriesCount, retriesStatusChange, 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, }) => {
|
|
291
277
|
const unresolvedFailure = (status === "failed" || status === "broken") && !resolution;
|
|
292
278
|
const parameterValues = redactParameters(parameters).flatMap(({ value }) => (value ? [value] : []));
|
|
293
279
|
const leaf = {
|
|
@@ -302,6 +288,8 @@ const leafFactory = ({ id, name, status, duration, flaky, start, retry, retriesC
|
|
|
302
288
|
retriesCount,
|
|
303
289
|
retriesStatusChange,
|
|
304
290
|
resolution,
|
|
291
|
+
resolutionExpiresAt,
|
|
292
|
+
resolutionState,
|
|
305
293
|
resolutionStatus: resolution ?? (unresolvedFailure ? "none" : undefined),
|
|
306
294
|
transition,
|
|
307
295
|
tooltips,
|
|
@@ -349,14 +337,21 @@ export const generateResolutionCategories = async (writer, tests, filename = "re
|
|
|
349
337
|
.filter((test) => !test.isRetry && test.resolution)
|
|
350
338
|
.forEach((test) => {
|
|
351
339
|
const resolution = test.resolution;
|
|
340
|
+
const mutedExpirationKey = test.resolutionExpiresAt === undefined
|
|
341
|
+
? "forever"
|
|
342
|
+
: (parseResolutionExpiresAt(test.resolutionExpiresAt)?.toString() ?? `invalid:${test.resolutionExpiresAt}`);
|
|
352
343
|
const groupId = resolution === "issue"
|
|
353
344
|
? `${resolution}:${test.resolutionIssue?.id ?? test.id}`
|
|
354
|
-
:
|
|
345
|
+
: [resolution, test.resolutionComment ?? test.id, resolution === "muted" ? mutedExpirationKey : undefined]
|
|
346
|
+
.filter(Boolean)
|
|
347
|
+
.join(":");
|
|
355
348
|
const group = groupsById.get(groupId) ?? {
|
|
356
349
|
id: groupId,
|
|
357
350
|
resolution,
|
|
358
351
|
name: getResolutionGroupName(test),
|
|
359
352
|
comment: test.resolutionComment ?? test.resolutionIssue?.comment,
|
|
353
|
+
...(test.resolutionExpiresAt ? { expiresAt: test.resolutionExpiresAt } : {}),
|
|
354
|
+
...(test.resolutionState ? { resolutionState: test.resolutionState } : {}),
|
|
360
355
|
issue: test.resolutionIssue,
|
|
361
356
|
testResults: [],
|
|
362
357
|
};
|
|
@@ -413,15 +408,6 @@ export const generateAttachmentsFiles = async (writer, attachmentLinks, contentF
|
|
|
413
408
|
});
|
|
414
409
|
return new Map(writtenAttachments.filter((attachment) => attachment !== undefined));
|
|
415
410
|
};
|
|
416
|
-
export const generateHistoryDataPoints = async (writer, store) => {
|
|
417
|
-
const result = new Map();
|
|
418
|
-
const allHistoryPoints = await store.allHistoryDataPoints();
|
|
419
|
-
for (const historyPoint of allHistoryPoints.slice(0, 6)) {
|
|
420
|
-
const src = `history/${historyPoint.uuid}.json`;
|
|
421
|
-
await writer.writeData(src, historyPoint);
|
|
422
|
-
}
|
|
423
|
-
return result;
|
|
424
|
-
};
|
|
425
411
|
export const generateGlobals = async (writer, payload) => {
|
|
426
412
|
const { globalExitCode, globalAttachments = [], globalAttachmentsByEnv = {}, globalErrors = [], globalErrorsByEnv = {}, contentFunction, } = payload;
|
|
427
413
|
const globals = {
|
|
@@ -485,7 +471,7 @@ export const generateQualityGateResults = async (writer, qualityGateResults = {}
|
|
|
485
471
|
await writer.writeWidget("quality-gate.json", resultsWithTrees);
|
|
486
472
|
};
|
|
487
473
|
export const generateStaticFiles = async (payload) => {
|
|
488
|
-
const { id, reportName = "Allure Report", reportLanguage = "en", logo = "", theme = "auto", groupBy, reportFiles, reportDataFiles, reportUuid, allureVersion, layout = "base", defaultSection = "", ci, executor, runSummary, runSummaryByEnv, stepTreeExpansion, defaultSortBy, overviewHref, } = 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;
|
|
489
475
|
const staticAssets = await readReportStaticAssets(reportStaticArchive);
|
|
490
476
|
const { manifest } = staticAssets;
|
|
491
477
|
const headTags = [];
|
|
@@ -527,6 +513,7 @@ export const generateStaticFiles = async (payload) => {
|
|
|
527
513
|
groupBy: groupBy?.length ? groupBy : [],
|
|
528
514
|
cacheKey: now.toString(),
|
|
529
515
|
ci,
|
|
516
|
+
git,
|
|
530
517
|
executor,
|
|
531
518
|
runSummary,
|
|
532
519
|
runSummaryByEnv,
|
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,12 +10,15 @@ 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, hasRetriesStatusChange, 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
23
|
const statisticByTestResults = (testResults, retriesByTrId) => {
|
|
21
24
|
const statistic = { total: 0 };
|
|
@@ -55,7 +58,6 @@ const statisticByTestResults = (testResults, retriesByTrId) => {
|
|
|
55
58
|
}
|
|
56
59
|
return statistic;
|
|
57
60
|
};
|
|
58
|
-
const isActiveStatisticTestResult = (testResult) => testResult.resolution !== "muted" && testResult.resolution !== "accepted";
|
|
59
61
|
export class AwesomePlugin {
|
|
60
62
|
constructor(options = {}) {
|
|
61
63
|
this.options = options;
|
|
@@ -68,6 +70,7 @@ export class AwesomePlugin {
|
|
|
68
70
|
});
|
|
69
71
|
_AwesomePlugin_generate.set(this, async (context, store) => {
|
|
70
72
|
const { singleFile, groupBy = [], filter, appendTitlePath } = this.options ?? {};
|
|
73
|
+
const resolutionEvaluatedAt = Date.now();
|
|
71
74
|
const perf = context.perf;
|
|
72
75
|
const measure = (name, fn) => perf?.measure(name, fn) ?? fn();
|
|
73
76
|
const hideLabels = context.hideLabels;
|
|
@@ -123,7 +126,7 @@ export class AwesomePlugin {
|
|
|
123
126
|
await measure("stats", async () => {
|
|
124
127
|
const envStatistics = new Map();
|
|
125
128
|
const pieEnvStatistics = new Map();
|
|
126
|
-
const pieStatistics = statisticByTestResults(allTrs.filter(
|
|
129
|
+
const pieStatistics = statisticByTestResults(allTrs.filter((testResult) => !isIgnoredResolution(testResult, resolutionEvaluatedAt)), related.retriesByTrId);
|
|
127
130
|
for (const tr of allTrs) {
|
|
128
131
|
const environmentId = envIdByTrId.get(tr.id);
|
|
129
132
|
if (!environmentId) {
|
|
@@ -140,7 +143,7 @@ export class AwesomePlugin {
|
|
|
140
143
|
await Promise.all(environments.map(async ({ id }) => {
|
|
141
144
|
const envTrs = trsByEnvId.get(id) ?? [];
|
|
142
145
|
envStatistics.set(id, statisticByTestResults(envTrs, related.retriesByTrId));
|
|
143
|
-
pieEnvStatistics.set(id, statisticByTestResults(envTrs.filter(
|
|
146
|
+
pieEnvStatistics.set(id, statisticByTestResults(envTrs.filter((testResult) => !isIgnoredResolution(testResult, resolutionEvaluatedAt)), related.retriesByTrId));
|
|
144
147
|
}));
|
|
145
148
|
await generateStatistic(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), {
|
|
146
149
|
stats: statistics,
|
|
@@ -162,8 +165,10 @@ export class AwesomePlugin {
|
|
|
162
165
|
const convertedTrs = await measure("convert", () => generateTestResults(__classPrivateFieldGet(this, _AwesomePlugin_writer, "f"), store, allTrs, {
|
|
163
166
|
pluginId: context.id,
|
|
164
167
|
hideLabels,
|
|
168
|
+
ideaLinks: this.options.ideaLinks,
|
|
165
169
|
related,
|
|
166
170
|
resolveHistoryUrl: context.history?.resolveTestResultUrl,
|
|
171
|
+
resolutionEvaluatedAt,
|
|
167
172
|
}));
|
|
168
173
|
if (perf) {
|
|
169
174
|
perf.count("convertedTestResults.count", convertedTrs.length, {
|
|
@@ -263,6 +268,7 @@ export class AwesomePlugin {
|
|
|
263
268
|
reportName: context.reportName,
|
|
264
269
|
overviewHref: context.overviewHref,
|
|
265
270
|
ci: context.ci,
|
|
271
|
+
git: collectGitHead(),
|
|
266
272
|
executor,
|
|
267
273
|
runSummary,
|
|
268
274
|
runSummaryByEnv,
|
|
@@ -284,6 +290,7 @@ export class AwesomePlugin {
|
|
|
284
290
|
this.done = async (context, store) => {
|
|
285
291
|
await __classPrivateFieldGet(this, _AwesomePlugin_generateAfterStart, "f").call(this, context, store);
|
|
286
292
|
};
|
|
293
|
+
validateChartsOptions(options.charts ?? []);
|
|
287
294
|
}
|
|
288
295
|
async info(context, store) {
|
|
289
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",
|
|
@@ -25,32 +25,35 @@
|
|
|
25
25
|
"scripts": {
|
|
26
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
|
|
28
|
+
"test": "rimraf out && vp test run",
|
|
29
29
|
"test:unit": "yarn test",
|
|
30
|
-
"lint": "
|
|
31
|
-
"lint:fix": "
|
|
30
|
+
"lint": "vp lint --import-plugin src test features stories",
|
|
31
|
+
"lint:fix": "vp lint --import-plugin --fix src test features stories"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@allurereport/charts-api": "3.
|
|
35
|
-
"@allurereport/core-api": "3.
|
|
36
|
-
"@allurereport/
|
|
37
|
-
"@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",
|
|
38
39
|
"d3-shape": "^3.2.0",
|
|
39
40
|
"handlebars": "4.7.10",
|
|
40
|
-
"markdown-it": "^15.0.
|
|
41
|
+
"markdown-it": "^15.0.3"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
|
-
"@allurereport/
|
|
44
|
-
"@allurereport/web-awesome": "3.
|
|
44
|
+
"@allurereport/common-config": "3.22.0",
|
|
45
|
+
"@allurereport/web-awesome": "3.22.0",
|
|
45
46
|
"@types/d3-shape": "^3.1.8",
|
|
46
47
|
"@types/markdown-it": "^14.1.2",
|
|
47
48
|
"@types/node": "^20",
|
|
48
|
-
"@vitest/coverage-istanbul": "
|
|
49
|
+
"@vitest/coverage-istanbul": "5.0.4",
|
|
49
50
|
"@vitest/runner": "^2",
|
|
50
51
|
"allure-js-commons": "^3",
|
|
51
52
|
"allure-vitest": "^3",
|
|
52
53
|
"rimraf": "^6",
|
|
53
54
|
"typescript": "^5",
|
|
54
|
-
"
|
|
55
|
+
"vite": "@voidzero-dev/vite-plus-core@1.2.0",
|
|
56
|
+
"vite-plus": "1.2.0",
|
|
57
|
+
"vitest": "5.0.4"
|
|
55
58
|
}
|
|
56
59
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const createSingleFileScripts: (files: ReadonlyMap<string, Buffer>, mainJs: string) => string;
|
package/dist/singleFileAssets.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { gzipSync } from "node:zlib";
|
|
2
|
-
import { stringifyForInlineScript } from "@allurereport/core-api";
|
|
3
|
-
const embeddedAssetsElementId = "allure-single-file-assets";
|
|
4
|
-
export const createSingleFileScripts = (files, mainJs) => {
|
|
5
|
-
const compressedScripts = Object.fromEntries([...files]
|
|
6
|
-
.filter(([fileName]) => fileName.endsWith(".js"))
|
|
7
|
-
.map(([fileName, content]) => [fileName, gzipSync(content, { level: 9 }).toString("base64")]));
|
|
8
|
-
if (!compressedScripts[mainJs]) {
|
|
9
|
-
throw new Error(`The report static assets do not contain the main script: ${mainJs}`);
|
|
10
|
-
}
|
|
11
|
-
return `
|
|
12
|
-
<script id="${embeddedAssetsElementId}" type="application/json">${stringifyForInlineScript(compressedScripts)}</script>
|
|
13
|
-
<script>
|
|
14
|
-
(function () {
|
|
15
|
-
const assetsElement = document.getElementById(${stringifyForInlineScript(embeddedAssetsElementId)});
|
|
16
|
-
const assets = JSON.parse(assetsElement.textContent || "{}");
|
|
17
|
-
const appendChild = document.head.appendChild;
|
|
18
|
-
|
|
19
|
-
assetsElement.remove();
|
|
20
|
-
|
|
21
|
-
function embeddedAssetName(script) {
|
|
22
|
-
const source = script.getAttribute("src");
|
|
23
|
-
|
|
24
|
-
if (!source) {
|
|
25
|
-
return undefined;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const path = source.split(/[?#]/, 1)[0];
|
|
29
|
-
|
|
30
|
-
return path.slice(path.lastIndexOf("/") + 1);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function decompressAsset(encoded) {
|
|
34
|
-
const binary = atob(encoded);
|
|
35
|
-
const compressed = new Uint8Array(binary.length);
|
|
36
|
-
|
|
37
|
-
for (let index = 0; index < binary.length; index++) {
|
|
38
|
-
compressed[index] = binary.charCodeAt(index);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const stream = new Blob([compressed]).stream().pipeThrough(new DecompressionStream("gzip"));
|
|
42
|
-
|
|
43
|
-
return new Response(stream).text();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
document.head.appendChild = function (node) {
|
|
47
|
-
if (node.tagName !== "SCRIPT") {
|
|
48
|
-
return appendChild.call(this, node);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const fileName = embeddedAssetName(node);
|
|
52
|
-
const encoded = fileName && Object.hasOwn(assets, fileName) ? assets[fileName] : undefined;
|
|
53
|
-
|
|
54
|
-
if (!encoded) {
|
|
55
|
-
return appendChild.call(this, node);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
void decompressAsset(encoded)
|
|
59
|
-
.then(function (source) {
|
|
60
|
-
node.removeAttribute("src");
|
|
61
|
-
node.text = source;
|
|
62
|
-
delete assets[fileName];
|
|
63
|
-
appendChild.call(document.head, node);
|
|
64
|
-
node.dispatchEvent(new Event("load"));
|
|
65
|
-
})
|
|
66
|
-
.catch(function (error) {
|
|
67
|
-
console.error("Failed to load embedded report asset " + fileName, error);
|
|
68
|
-
node.dispatchEvent(new Event("error"));
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
return node;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const mainScript = document.createElement("script");
|
|
75
|
-
|
|
76
|
-
mainScript.src = ${stringifyForInlineScript(mainJs)};
|
|
77
|
-
document.head.appendChild(mainScript);
|
|
78
|
-
})();
|
|
79
|
-
</script>
|
|
80
|
-
`;
|
|
81
|
-
};
|