@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 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
 
@@ -1,7 +1,8 @@
1
- import { type TestFixtureResult, type TestResult, type TestStepResult } from "@allurereport/core-api";
2
- import type { ReportFixtureResult, ReportTestResult, ReportTestStepResult } from "@allurereport/plugin-api";
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;
@@ -1,7 +1,22 @@
1
- import { createDictionary, isStep, redactParameters, shouldHideLabel, } from "@allurereport/core-api";
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
- };
@@ -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, TemplateManifest } from "./model.js";
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>;
@@ -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 { copyReportStaticAssets, getReportStaticAsset, readReportStaticAssets, } from "@allurereport/plugin-api/static-assets";
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 { convertFixtureResult, convertTestResult } from "./converters.js";
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
- : `${resolution}:${test.resolutionComment ?? test.id}`;
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, generateHistoryDataPoints, generateMetricsWidget, generateNav, generateQualityGateResults, generateResolutionCategories, generateSearchIndex, generateStaticFiles, generateStatistic, generateTestCases, generateTestEnvGroups, generateTestResults, generateTree, generateTreeFilters, generateVariables, getRunSummary, } from "./generators.js";
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(isActiveStatisticTestResult), related.retriesByTrId);
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(isActiveStatisticTestResult), related.retriesByTrId));
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;
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/plugin-awesome",
3
- "version": "3.21.0",
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 ./out && vitest run",
28
+ "test": "rimraf out && vp test run",
29
29
  "test:unit": "yarn test",
30
- "lint": "oxlint --import-plugin src test features stories",
31
- "lint:fix": "oxlint --import-plugin --fix src test features stories"
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.21.0",
35
- "@allurereport/core-api": "3.21.0",
36
- "@allurereport/plugin-api": "3.21.0",
37
- "@allurereport/web-commons": "3.21.0",
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.2"
41
+ "markdown-it": "^15.0.3"
41
42
  },
42
43
  "devDependencies": {
43
- "@allurereport/test-config": "3.21.0",
44
- "@allurereport/web-awesome": "3.21.0",
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": "^4.1.0",
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
- "vitest": "^4.1.0"
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;
@@ -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
- };