@allurereport/plugin-allure2 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.
@@ -38,7 +38,7 @@ const match = (regex, value) => {
38
38
  const b = new RegExp(regex, "s").test(value);
39
39
  return b;
40
40
  }
41
- catch (ignored) {
41
+ catch {
42
42
  return false;
43
43
  }
44
44
  };
@@ -1,4 +1,4 @@
1
- import { isStep, redactParameters } from "@allurereport/core-api";
1
+ import { hasRetriesStatusChange, isStep, redactParameters } from "@allurereport/core-api";
2
2
  import { matchCategories } from "./categories.js";
3
3
  import { severityValues } from "./model.js";
4
4
  import { createStatistic, updateStatistic } from "./utils.js";
@@ -170,8 +170,7 @@ export const convertTestResult = (context, test) => {
170
170
  duration: retry.duration,
171
171
  },
172
172
  }));
173
- const retriesStatusChange = isImportantStatus(status) &&
174
- retries.find((retry) => isImportantStatus(retry.status) && retry.status !== status) !== undefined;
173
+ const retriesStatusChange = hasRetriesStatusChange(test, context.retries);
175
174
  const historyItems = context.legacyHistory
176
175
  ? context.legacyHistory.items.map((item) => ({
177
176
  uid: item.uid,
@@ -1,10 +1,7 @@
1
1
  import type { AttachmentLink, GlobalAttachmentLink, HistoryDataPoint, TestError } from "@allurereport/core-api";
2
- import type { ReportFiles, ResultFile } from "@allurereport/plugin-api";
3
- import type { ReportStaticManifest } from "@allurereport/plugin-api/static-assets";
2
+ import type { ExitCode, ReportFiles, ResultFile } from "@allurereport/plugin-api";
4
3
  import type { Allure2CategoriesTrendItem, Allure2DurationTrendItem, Allure2ExecutorInfo, Allure2LegacyHistoryTrendItem, Allure2RetryTrendItem, Allure2TestResult } from "./model.js";
5
4
  import type { Allure2DataWriter, ReportFile } from "./writer.js";
6
- export type TemplateManifest = ReportStaticManifest;
7
- export declare const readTemplateManifest: () => Promise<TemplateManifest>;
8
5
  export declare const generateStaticFiles: (payload: {
9
6
  allureVersion: string;
10
7
  reportName: string;
@@ -13,6 +10,7 @@ export declare const generateStaticFiles: (payload: {
13
10
  reportFiles: ReportFiles;
14
11
  reportDataFiles: ReportFile[];
15
12
  reportUuid: string;
13
+ overviewHref?: string;
16
14
  }) => Promise<void>;
17
15
  export declare const generateTree: (writer: Allure2DataWriter, name: string, labelNames: string[], tests: Allure2TestResult[]) => Promise<void>;
18
16
  export declare const generatePackagesData: (writer: Allure2DataWriter, tests: Allure2TestResult[]) => Promise<void>;
@@ -31,4 +29,4 @@ export declare const generateDurationTrendData: (writer: Allure2DataWriter, test
31
29
  export declare const generateRetryTrendData: (writer: Allure2DataWriter, tests: Allure2TestResult[], history?: Allure2RetryTrendItem[], executor?: Partial<Allure2ExecutorInfo>) => Promise<void>;
32
30
  export declare const generateCategoriesTrendData: (writer: Allure2DataWriter, tests: Allure2TestResult[], history?: Allure2CategoriesTrendItem[], executor?: Partial<Allure2ExecutorInfo>) => Promise<void>;
33
31
  export declare const generateAttachmentsData: (writer: Allure2DataWriter, attachmentLinks: AttachmentLink[], contentFunction: (id: string) => Promise<ResultFile | undefined>) => Promise<Map<string, string>>;
34
- export declare const generateGlobalsData: (writer: Allure2DataWriter, globalErrors: TestError[], globalAttachments: GlobalAttachmentLink[], attachmentMap: Map<string, string>, attachmentTimestamps?: Record<string, number>, errorTimestamps?: Array<number | undefined>) => Promise<void>;
32
+ export declare const generateGlobalsData: (writer: Allure2DataWriter, globalErrors: TestError[], globalAttachments: GlobalAttachmentLink[], attachmentMap: Map<string, string>, attachmentTimestamps?: Record<string, number>, errorTimestamps?: Array<number | undefined>, exitCode?: ExitCode) => Promise<void>;
@@ -1,14 +1,10 @@
1
- import { createBaseUrlScript, createScriptTag, createStylesLinkTag } from "@allurereport/core-api";
1
+ import { createBaseUrlScript, createScriptTag, createStylesLinkTag, stringifyForInlineScript, } from "@allurereport/core-api";
2
+ import { writeConcurrently } from "@allurereport/plugin-api/internal/report";
2
3
  import { copyReportStaticAssets, getReportStaticAsset, readReportStaticAssets, } from "@allurereport/plugin-api/static-assets";
3
4
  import Handlebars from "handlebars";
4
5
  import { byLabels, collapseTree, createTree, createWidget } from "./tree.js";
5
6
  import { createStatistic, updateStatistic, updateTime } from "./utils.js";
6
7
  const reportStaticArchive = new URL("../dist/static/report.tar", import.meta.url);
7
- const writeConcurrently = async (items, write, concurrency = 64) => {
8
- for (let i = 0; i < items.length; i += concurrency) {
9
- await Promise.all(items.slice(i, i + concurrency).map(write));
10
- }
11
- };
12
8
  const template = `<!DOCTYPE html>
13
9
  <html dir="ltr" lang="{{reportLanguage}}">
14
10
  <head>
@@ -38,6 +34,11 @@ const template = `<!DOCTYPE html>
38
34
  }
39
35
  </script>
40
36
  ${createBaseUrlScript()}
37
+ {{#if reportOptions}}
38
+ <script>
39
+ window.allureReportOptions = {{{ reportOptions }}}
40
+ </script>
41
+ {{/if}}
41
42
  {{#if analyticsEnable}}
42
43
  <script async src="https://www.googletagmanager.com/gtag/js?id=G-FVWC4GKEYS"></script>
43
44
  <script>
@@ -56,11 +57,15 @@ const template = `<!DOCTYPE html>
56
57
  </html>
57
58
  `;
58
59
  const compiledTemplate = Handlebars.compile(template);
59
- const createEmbeddedReportDataScript = (reportFiles) => {
60
- const reportFilesDeclaration = reportFiles
61
- .map(({ name, value }) => `d(${JSON.stringify(name)},${JSON.stringify(value)})`)
62
- .join(",");
63
- return `
60
+ const reportDataScriptPlaceholder = "<!-- allure2-report-data -->";
61
+ const injectEmbeddedReportDataScript = (html, reportFiles) => {
62
+ const placeholderIndex = html.indexOf(reportDataScriptPlaceholder);
63
+ if (placeholderIndex === -1) {
64
+ throw new Error("Report data script placeholder is missing from the Allure 2 HTML template");
65
+ }
66
+ const chunks = [
67
+ Buffer.from(html.slice(0, placeholderIndex), "utf8"),
68
+ Buffer.from(`
64
69
  <script>
65
70
  window.reportDataReady = false;
66
71
  window.reportData = window.reportData || {};
@@ -73,18 +78,20 @@ const createEmbeddedReportDataScript = (reportFiles) => {
73
78
  }
74
79
  </script>
75
80
  <script>
76
- Promise.allSettled([${reportFilesDeclaration}]).then(function () {
81
+ Promise.allSettled([`),
82
+ ];
83
+ reportFiles.forEach(({ name, value }, index) => {
84
+ chunks.push(Buffer.from(`${index === 0 ? "" : ","}d(${stringifyForInlineScript(name)},${stringifyForInlineScript(value)})`));
85
+ });
86
+ chunks.push(Buffer.from(`]).then(function () {
77
87
  window.reportDataReady = true;
78
88
  });
79
89
  </script>
80
- `;
81
- };
82
- export const readTemplateManifest = async () => {
83
- const { manifest } = await readReportStaticAssets(reportStaticArchive);
84
- return manifest;
90
+ `), Buffer.from(html.slice(placeholderIndex + reportDataScriptPlaceholder.length), "utf8"));
91
+ return Buffer.concat(chunks);
85
92
  };
86
93
  export const generateStaticFiles = async (payload) => {
87
- const { reportName, reportLanguage, singleFile, reportFiles, reportDataFiles, reportUuid, allureVersion } = payload;
94
+ const { reportName, reportLanguage, singleFile, reportFiles, reportDataFiles, reportUuid, allureVersion, overviewHref, } = payload;
88
95
  const staticAssets = await readReportStaticAssets(reportStaticArchive);
89
96
  const { manifest } = staticAssets;
90
97
  const mainJs = manifest["main.js"];
@@ -110,15 +117,16 @@ export const generateStaticFiles = async (payload) => {
110
117
  const html = compiledTemplate({
111
118
  headTags: headTags.join("\n"),
112
119
  bodyTags: bodyTags.join("\n"),
113
- reportFilesScript: singleFile ? createEmbeddedReportDataScript(reportDataFiles) : "",
120
+ reportFilesScript: singleFile ? reportDataScriptPlaceholder : "",
114
121
  analyticsEnable: process.env.ALLURE_NO_ANALYTICS?.toLowerCase() !== "true",
115
122
  allureVersion,
116
123
  reportLanguage,
117
124
  reportUuid,
118
125
  reportName,
119
126
  singleFile,
127
+ reportOptions: overviewHref ? stringifyForInlineScript({ overviewHref }) : undefined,
120
128
  });
121
- await reportFiles.addFile("index.html", Buffer.from(html, "utf8"));
129
+ await reportFiles.addFile("index.html", singleFile ? injectEmbeddedReportDataScript(html, reportDataFiles) : Buffer.from(html, "utf8"));
122
130
  }
123
131
  catch (err) {
124
132
  if (err instanceof RangeError) {
@@ -308,7 +316,7 @@ export const generateAttachmentsData = async (writer, attachmentLinks, contentFu
308
316
  }
309
317
  return result;
310
318
  };
311
- export const generateGlobalsData = async (writer, globalErrors, globalAttachments, attachmentMap, attachmentTimestamps = {}, errorTimestamps = []) => {
319
+ export const generateGlobalsData = async (writer, globalErrors, globalAttachments, attachmentMap, attachmentTimestamps = {}, errorTimestamps = [], exitCode) => {
312
320
  const data = {
313
321
  errors: globalErrors.map(({ message, trace, actual, expected }, index) => ({
314
322
  message,
@@ -334,5 +342,8 @@ export const generateGlobalsData = async (writer, globalErrors, globalAttachment
334
342
  ];
335
343
  }),
336
344
  };
345
+ if (exitCode) {
346
+ data.exitCode = exitCode;
347
+ }
337
348
  await writer.writeWidget("globals.json", data);
338
349
  };
package/dist/model.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Statistic } from "@allurereport/core-api";
2
+ import type { ExitCode } from "@allurereport/plugin-api";
2
3
  export type Allure2Status = "failed" | "broken" | "passed" | "skipped" | "unknown";
3
4
  export interface Allure2Time {
4
5
  start?: number;
@@ -38,6 +39,7 @@ export interface Allure2GlobalAttachment extends Allure2Attachment {
38
39
  timestamp?: number;
39
40
  }
40
41
  export interface Allure2GlobalsData {
42
+ exitCode?: ExitCode;
41
43
  errors: Allure2GlobalError[];
42
44
  attachments: Allure2GlobalAttachment[];
43
45
  }
package/dist/plugin.js CHANGED
@@ -16,13 +16,14 @@ export class Allure2Plugin {
16
16
  const writer = singleFile ? new InMemoryReportDataWriter() : new ReportFileDataWriter(context.reportFiles);
17
17
  const attachmentLinks = await store.allAttachments();
18
18
  const attachmentMap = await generateAttachmentsData(writer, attachmentLinks, (id) => store.attachmentContentById(id));
19
- const [globalErrors, globalAttachments] = await Promise.all([
19
+ const [globalErrors, globalAttachments, globalExitCode] = await Promise.all([
20
20
  store.allGlobalErrors(),
21
21
  store.allGlobalAttachments(),
22
+ store.globalExitCode(),
22
23
  ]);
23
24
  const globalAttachmentTimestamps = (await store.metadataByKey("allure2_global_attachment_timestamps")) ?? {};
24
25
  const globalErrorTimestamps = (await store.metadataByKey("allure2_global_error_timestamps")) ?? [];
25
- await generateGlobalsData(writer, globalErrors, globalAttachments, attachmentMap, globalAttachmentTimestamps, globalErrorTimestamps);
26
+ await generateGlobalsData(writer, globalErrors, globalAttachments, attachmentMap, globalAttachmentTimestamps, globalErrorTimestamps, globalExitCode);
26
27
  const categories = (await store.metadataByKey("allure2_categories")) ?? [];
27
28
  const legacyHistory = (await store.metadataByKey("allure2_history")) ?? {};
28
29
  const environmentItems = (await store.metadataByKey("allure_environment")) ?? [];
@@ -80,6 +81,7 @@ export class Allure2Plugin {
80
81
  reportFiles: context.reportFiles,
81
82
  reportDataFiles,
82
83
  reportUuid: context.reportUuid,
84
+ overviewHref: context.overviewHref,
83
85
  });
84
86
  });
85
87
  this.update = async (context, store) => {
Binary file
package/dist/tree.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createHash } from "node:crypto";
2
- import { byStatistic, compareBy } from "@allurereport/core-api";
1
+ import { byStatistic, compareBy, nullsFirst, ordinal } from "@allurereport/core-api";
2
+ import { md5 } from "@allurereport/plugin-api";
3
3
  import { calculateStatisticByLeafs } from "./utils.js";
4
4
  const rootNodeUid = "__ROOT__";
5
5
  const createLeaf = (endNode, test) => {
@@ -28,7 +28,9 @@ export const createTree = (tests, classifier, leafFactory = createLeaf) => {
28
28
  const groups = new Map();
29
29
  const root = { uid: rootNodeUid, name: rootNodeUid, children: [] };
30
30
  groups.set(root.uid, root);
31
- for (const test of tests) {
31
+ const compareStart = nullsFirst(ordinal());
32
+ const orderedTests = [...tests].sort((a, b) => compareStart(a.time.start, b.time.start) || (a.uid < b.uid ? -1 : a.uid > b.uid ? 1 : 0));
33
+ for (const test of orderedTests) {
32
34
  const treeLayers = classifier(test);
33
35
  if (!treeLayers) {
34
36
  continue;
@@ -72,7 +74,6 @@ const groupByLabels = (test, labelNames) => {
72
74
  const groupUid = (parentUid, groupName) => {
73
75
  return md5(parentUid ? `${parentUid}.${groupName}` : groupName);
74
76
  };
75
- const md5 = (data) => createHash("md5").update(data).digest("hex");
76
77
  export const collapseTree = (treeGroup, separator = ".") => {
77
78
  const newChildren = treeGroup.children.map((c) => {
78
79
  if (!("children" in c)) {
package/dist/writer.d.ts CHANGED
@@ -10,15 +10,6 @@ export interface Allure2DataWriter {
10
10
  writeTestCase(test: Allure2TestResult): Promise<void>;
11
11
  writeAttachment(source: string, file: ResultFile): Promise<void>;
12
12
  }
13
- export declare class FileSystemReportDataWriter implements Allure2DataWriter {
14
- #private;
15
- private readonly output;
16
- constructor(output: string);
17
- writeData(fileName: string, data: any): Promise<void>;
18
- writeWidget(fileName: string, data: any): Promise<void>;
19
- writeTestCase(test: Allure2TestResult): Promise<void>;
20
- writeAttachment(source: string, file: ResultFile): Promise<void>;
21
- }
22
13
  export declare class InMemoryReportDataWriter implements Allure2DataWriter {
23
14
  #private;
24
15
  writeData(fileName: string, data: any): Promise<void>;
package/dist/writer.js CHANGED
@@ -1,56 +1,10 @@
1
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
- if (kind === "m") throw new TypeError("Private method is not writable");
3
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
- 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");
5
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
- };
7
1
  var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
2
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
3
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
4
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
5
  };
12
- var _FileSystemReportDataWriter_dataDir, _FileSystemReportDataWriter_widgetsDir, _FileSystemReportDataWriter_testCasesDir, _FileSystemReportDataWriter_attachmentsDir, _FileSystemReportDataWriter_dataDirReady, _FileSystemReportDataWriter_widgetsDirReady, _FileSystemReportDataWriter_testCasesDirReady, _FileSystemReportDataWriter_attachmentsDirReady, _InMemoryReportDataWriter_data;
13
- import { mkdir, writeFile } from "node:fs/promises";
14
- import { resolve } from "node:path";
6
+ var _InMemoryReportDataWriter_data;
15
7
  import { joinPosixPath } from "@allurereport/core-api";
16
- export class FileSystemReportDataWriter {
17
- constructor(output) {
18
- this.output = output;
19
- _FileSystemReportDataWriter_dataDir.set(this, void 0);
20
- _FileSystemReportDataWriter_widgetsDir.set(this, void 0);
21
- _FileSystemReportDataWriter_testCasesDir.set(this, void 0);
22
- _FileSystemReportDataWriter_attachmentsDir.set(this, void 0);
23
- _FileSystemReportDataWriter_dataDirReady.set(this, void 0);
24
- _FileSystemReportDataWriter_widgetsDirReady.set(this, void 0);
25
- _FileSystemReportDataWriter_testCasesDirReady.set(this, void 0);
26
- _FileSystemReportDataWriter_attachmentsDirReady.set(this, void 0);
27
- __classPrivateFieldSet(this, _FileSystemReportDataWriter_dataDir, resolve(this.output, "data"), "f");
28
- __classPrivateFieldSet(this, _FileSystemReportDataWriter_widgetsDir, resolve(this.output, "widgets"), "f");
29
- __classPrivateFieldSet(this, _FileSystemReportDataWriter_testCasesDir, resolve(this.output, "data", "test-cases"), "f");
30
- __classPrivateFieldSet(this, _FileSystemReportDataWriter_attachmentsDir, resolve(this.output, "data", "attachments"), "f");
31
- __classPrivateFieldSet(this, _FileSystemReportDataWriter_dataDirReady, mkdir(__classPrivateFieldGet(this, _FileSystemReportDataWriter_dataDir, "f"), { recursive: true }), "f");
32
- __classPrivateFieldSet(this, _FileSystemReportDataWriter_widgetsDirReady, mkdir(__classPrivateFieldGet(this, _FileSystemReportDataWriter_widgetsDir, "f"), { recursive: true }), "f");
33
- __classPrivateFieldSet(this, _FileSystemReportDataWriter_testCasesDirReady, mkdir(__classPrivateFieldGet(this, _FileSystemReportDataWriter_testCasesDir, "f"), { recursive: true }), "f");
34
- __classPrivateFieldSet(this, _FileSystemReportDataWriter_attachmentsDirReady, mkdir(__classPrivateFieldGet(this, _FileSystemReportDataWriter_attachmentsDir, "f"), { recursive: true }), "f");
35
- }
36
- async writeData(fileName, data) {
37
- await __classPrivateFieldGet(this, _FileSystemReportDataWriter_dataDirReady, "f");
38
- await writeFile(resolve(__classPrivateFieldGet(this, _FileSystemReportDataWriter_dataDir, "f"), fileName), JSON.stringify(data), { encoding: "utf-8" });
39
- }
40
- async writeWidget(fileName, data) {
41
- await __classPrivateFieldGet(this, _FileSystemReportDataWriter_widgetsDirReady, "f");
42
- await writeFile(resolve(__classPrivateFieldGet(this, _FileSystemReportDataWriter_widgetsDir, "f"), fileName), JSON.stringify(data), { encoding: "utf-8" });
43
- }
44
- async writeTestCase(test) {
45
- await __classPrivateFieldGet(this, _FileSystemReportDataWriter_testCasesDirReady, "f");
46
- await writeFile(resolve(__classPrivateFieldGet(this, _FileSystemReportDataWriter_testCasesDir, "f"), `${test.uid}.json`), JSON.stringify(test), { encoding: "utf-8" });
47
- }
48
- async writeAttachment(source, file) {
49
- await __classPrivateFieldGet(this, _FileSystemReportDataWriter_attachmentsDirReady, "f");
50
- await file.writeTo(resolve(__classPrivateFieldGet(this, _FileSystemReportDataWriter_attachmentsDir, "f"), source));
51
- }
52
- }
53
- _FileSystemReportDataWriter_dataDir = new WeakMap(), _FileSystemReportDataWriter_widgetsDir = new WeakMap(), _FileSystemReportDataWriter_testCasesDir = new WeakMap(), _FileSystemReportDataWriter_attachmentsDir = new WeakMap(), _FileSystemReportDataWriter_dataDirReady = new WeakMap(), _FileSystemReportDataWriter_widgetsDirReady = new WeakMap(), _FileSystemReportDataWriter_testCasesDirReady = new WeakMap(), _FileSystemReportDataWriter_attachmentsDirReady = new WeakMap();
54
8
  export class InMemoryReportDataWriter {
55
9
  constructor() {
56
10
  _InMemoryReportDataWriter_data.set(this, {});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/plugin-allure2",
3
- "version": "3.20.1",
3
+ "version": "3.22.0",
4
4
  "description": "The Allure 2-compatible HTML report",
5
5
  "keywords": [
6
6
  "allure",
@@ -25,23 +25,28 @@
25
25
  "scripts": {
26
26
  "build": "run clean && tsc --project ./tsconfig.json && node ../../scripts/pack-report-static.mjs ../web-allure2/dist/multi ./dist/static/report.tar",
27
27
  "clean": "rimraf ./dist",
28
- "test": "rimraf ./out && vitest run",
29
- "lint": "oxlint --import-plugin src test features stories",
30
- "lint:fix": "oxlint --import-plugin --fix src test features stories"
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/core-api": "3.20.1",
34
- "@allurereport/plugin-api": "3.20.1",
35
- "handlebars": "^4.7.9"
34
+ "@allurereport/core-api": "3.22.0",
35
+ "@allurereport/plugin-api": "3.22.0",
36
+ "handlebars": "4.7.10"
36
37
  },
37
38
  "devDependencies": {
38
- "@allurereport/web-allure2": "3.20.1",
39
+ "@allurereport/common-config": "3.22.0",
40
+ "@allurereport/web-allure2": "3.22.0",
39
41
  "@types/node": "^20",
42
+ "@vitest/coverage-istanbul": "5.0.4",
40
43
  "@vitest/runner": "^2",
41
44
  "allure-js-commons": "^3",
42
45
  "allure-vitest": "^3",
43
46
  "rimraf": "^6",
44
47
  "typescript": "^5",
45
- "vitest": "^4.1.0"
48
+ "vite": "@voidzero-dev/vite-plus-core@1.2.0",
49
+ "vite-plus": "1.2.0",
50
+ "vitest": "5.0.4"
46
51
  }
47
52
  }