@allurereport/core 3.16.0 → 3.17.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.
@@ -1,7 +1,9 @@
1
+ import { randomUUID } from "node:crypto";
1
2
  import { mkdir, writeFile } from "node:fs/promises";
2
3
  import { join } from "node:path";
3
4
  import { performance } from "node:perf_hooks";
4
- export const PERF_METRICS_FILE = "allure-perf-metrics.json";
5
+ export const PERF_METRICS_FILE = "performance.json";
6
+ export const perfMetricsFileName = (reportUuid) => `${reportUuid}-perf.json`;
5
7
  const MARK_PREFIX = "allure:perf:";
6
8
  const ENABLED_VALUES = new Set(["1", "true", "yes", "on"]);
7
9
  const SPANS = [];
@@ -10,6 +12,7 @@ const MEASURES = new Set();
10
12
  let sequence = 0;
11
13
  const round = (value) => Number(value.toFixed(3));
12
14
  export const PERF_METRIC_NAMES = {
15
+ allureTotal: "allure.total",
13
16
  restoreStateTotal: "restoreState.total",
14
17
  restoreStateDump: "restoreState.dump",
15
18
  restoreStateAttachments: "restoreState.attachments",
@@ -24,6 +27,22 @@ export const PERF_METRIC_PREFIXES = {
24
27
  generatePluginDone: "generate.plugin.done.",
25
28
  publishUploadPlugin: "publish.upload.plugin.",
26
29
  };
30
+ const getCoveredDurationSummary = () => {
31
+ if (SPANS.length === 0) {
32
+ return undefined;
33
+ }
34
+ const startTimeMs = Math.min(...SPANS.map(({ startTimeMs }) => startTimeMs));
35
+ const endTimeMs = Math.max(...SPANS.map(({ startTimeMs, durationMs }) => startTimeMs + durationMs));
36
+ const durationMs = round(endTimeMs - startTimeMs);
37
+ return {
38
+ name: PERF_METRIC_NAMES.allureTotal,
39
+ count: 1,
40
+ totalMs: durationMs,
41
+ minMs: durationMs,
42
+ maxMs: durationMs,
43
+ avgMs: durationMs,
44
+ };
45
+ };
27
46
  export const isPerfMetricsEnabled = () => ENABLED_VALUES.has((process.env.ALLURE_PERF_METRICS ?? "").toLowerCase());
28
47
  export const startPerfSpan = (name) => {
29
48
  if (!isPerfMetricsEnabled()) {
@@ -72,39 +91,33 @@ export const measurePerf = async (name, fn) => {
72
91
  end();
73
92
  }
74
93
  };
75
- export const getPerfMetricsPayload = () => {
76
- const byName = new Map();
77
- for (const span of SPANS) {
78
- const current = byName.get(span.name) ?? [];
79
- current.push(span);
80
- byName.set(span.name, current);
94
+ export const getPerfMetricsResults = () => {
95
+ const totalSummary = getCoveredDurationSummary();
96
+ const results = SPANS.map((span) => ({
97
+ id: randomUUID(),
98
+ key: span.name,
99
+ value: span.durationMs,
100
+ start: round(performance.timeOrigin + span.startTimeMs),
101
+ stop: round(performance.timeOrigin + span.startTimeMs + span.durationMs),
102
+ }));
103
+ if (totalSummary) {
104
+ results.unshift({
105
+ id: randomUUID(),
106
+ key: PERF_METRIC_NAMES.allureTotal,
107
+ value: totalSummary.avgMs,
108
+ start: round(performance.timeOrigin + Math.min(...SPANS.map(({ startTimeMs }) => startTimeMs))),
109
+ stop: round(performance.timeOrigin + Math.max(...SPANS.map(({ startTimeMs, durationMs }) => startTimeMs + durationMs))),
110
+ });
81
111
  }
82
- return {
83
- version: 1,
84
- generatedAt: new Date().toISOString(),
85
- timeOriginMs: round(performance.timeOrigin),
86
- spans: [...SPANS],
87
- summary: [...byName.entries()].map(([name, group]) => {
88
- const durations = group.map(({ durationMs }) => durationMs);
89
- const totalMs = durations.reduce((acc, duration) => acc + duration, 0);
90
- return {
91
- name,
92
- count: group.length,
93
- totalMs: round(totalMs),
94
- minMs: round(Math.min(...durations)),
95
- maxMs: round(Math.max(...durations)),
96
- avgMs: round(totalMs / group.length),
97
- };
98
- }),
99
- };
112
+ return results;
100
113
  };
101
- export const writePerfMetrics = async (output) => {
114
+ export const writePerfMetrics = async (output, fileName = PERF_METRICS_FILE) => {
102
115
  if (!isPerfMetricsEnabled()) {
103
116
  return false;
104
117
  }
105
- const payload = getPerfMetricsPayload();
118
+ const results = getPerfMetricsResults();
106
119
  await mkdir(output, { recursive: true });
107
- await writeFile(join(output, PERF_METRICS_FILE), `${JSON.stringify(payload, null, 2)}\n`, "utf8");
120
+ await writeFile(join(output, fileName), `${JSON.stringify(results, null, 2)}\n`, "utf8");
108
121
  resetPerfMetrics();
109
122
  return true;
110
123
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/core",
3
- "version": "3.16.0",
3
+ "version": "3.17.0",
4
4
  "description": "Collection of generic Allure utilities used across the entire project",
5
5
  "keywords": [
6
6
  "allure"
@@ -25,26 +25,26 @@
25
25
  "lint:fix": "oxlint --import-plugin --fix src test features stories"
26
26
  },
27
27
  "dependencies": {
28
- "@allurereport/ci": "3.16.0",
29
- "@allurereport/cli-commons": "3.16.0",
30
- "@allurereport/core-api": "3.16.0",
31
- "@allurereport/plugin-agent": "3.16.0",
32
- "@allurereport/plugin-allure2": "3.16.0",
33
- "@allurereport/plugin-api": "3.16.0",
34
- "@allurereport/plugin-awesome": "3.16.0",
35
- "@allurereport/plugin-classic": "3.16.0",
36
- "@allurereport/plugin-csv": "3.16.0",
37
- "@allurereport/plugin-dashboard": "3.16.0",
38
- "@allurereport/plugin-jira": "3.16.0",
39
- "@allurereport/plugin-log": "3.16.0",
40
- "@allurereport/plugin-progress": "3.16.0",
41
- "@allurereport/plugin-slack": "3.16.0",
42
- "@allurereport/plugin-testops": "3.16.0",
43
- "@allurereport/plugin-testplan": "3.16.0",
44
- "@allurereport/reader": "3.16.0",
45
- "@allurereport/reader-api": "3.16.0",
46
- "@allurereport/service": "3.16.0",
47
- "@allurereport/summary": "3.16.0",
28
+ "@allurereport/ci": "3.17.0",
29
+ "@allurereport/cli-commons": "3.17.0",
30
+ "@allurereport/core-api": "3.17.0",
31
+ "@allurereport/plugin-agent": "3.17.0",
32
+ "@allurereport/plugin-allure2": "3.17.0",
33
+ "@allurereport/plugin-api": "3.17.0",
34
+ "@allurereport/plugin-awesome": "3.17.0",
35
+ "@allurereport/plugin-classic": "3.17.0",
36
+ "@allurereport/plugin-csv": "3.17.0",
37
+ "@allurereport/plugin-dashboard": "3.17.0",
38
+ "@allurereport/plugin-jira": "3.17.0",
39
+ "@allurereport/plugin-log": "3.17.0",
40
+ "@allurereport/plugin-progress": "3.17.0",
41
+ "@allurereport/plugin-slack": "3.17.0",
42
+ "@allurereport/plugin-testops": "3.17.0",
43
+ "@allurereport/plugin-testplan": "3.17.0",
44
+ "@allurereport/reader": "3.17.0",
45
+ "@allurereport/reader-api": "3.17.0",
46
+ "@allurereport/service": "3.17.0",
47
+ "@allurereport/summary": "3.17.0",
48
48
  "glob": "^13.0.6",
49
49
  "handlebars": "^4.7.9",
50
50
  "jiti": "^2.5.1",
package/dist/known.d.ts DELETED
@@ -1,8 +0,0 @@
1
- import type { KnownIssuesConfig, KnownTestFailure, TestResult } from "@allurereport/core-api";
2
- import type { AllureStore } from "@allurereport/plugin-api";
3
- export declare const DEFAULT_KNOWN_ISSUES_PATH = "known-issues.json";
4
- export declare const hasKnownIssueRules: (knownIssues?: KnownIssuesConfig) => boolean;
5
- export declare const getKnownIssueByRules: (testResult: TestResult, knownIssues: KnownIssuesConfig | undefined, environmentId?: string) => KnownTestFailure | undefined;
6
- export declare const resolveExactIssuesFilePath: (pathOrDir: string | undefined, label: string) => Promise<string | undefined>;
7
- export declare const readKnownIssues: (knownIssuePath: string) => Promise<KnownTestFailure[]>;
8
- export declare const writeKnownIssues: (store: AllureStore, knownIssuesPath?: string) => Promise<void>;
package/dist/known.js DELETED
@@ -1,86 +0,0 @@
1
- import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
2
- import { dirname, extname, resolve } from "node:path";
3
- import { isFileNotFoundError } from "./utils/misc.js";
4
- export const DEFAULT_KNOWN_ISSUES_PATH = "known-issues.json";
5
- export const hasKnownIssueRules = (knownIssues) => (knownIssues?.rules?.length ?? 0) > 0;
6
- const messageMatches = (rule, testResult) => {
7
- if (!rule.messageRegexp) {
8
- return true;
9
- }
10
- const message = testResult.error?.message;
11
- return typeof message === "string" && new RegExp(rule.messageRegexp).test(message);
12
- };
13
- const testCaseIdMatches = (rule, testResult) => {
14
- const { id, allureId, externalId } = testResult.testCase ?? {};
15
- return !rule.testCaseId || [id, allureId, externalId].includes(rule.testCaseId);
16
- };
17
- const retryHashMatches = (rule, testResult) => {
18
- return !rule.retryHash || rule.retryHash === testResult.retryHash;
19
- };
20
- const environmentMatches = (rule, testResult) => {
21
- return !rule.environmentId || rule.environmentId === testResult.environment;
22
- };
23
- export const getKnownIssueByRules = (testResult, knownIssues, environmentId) => {
24
- if (!testResult.historyId || !hasKnownIssueRules(knownIssues)) {
25
- return undefined;
26
- }
27
- const matchedRule = knownIssues.rules.find((rule) => [messageMatches, testCaseIdMatches, environmentMatches, retryHashMatches].every((matcher) => matcher(rule, testResult)));
28
- if (!matchedRule) {
29
- return undefined;
30
- }
31
- return {
32
- historyId: testResult.historyId,
33
- reason: matchedRule.decision.reason,
34
- links: matchedRule.decision.links,
35
- error: testResult.error,
36
- };
37
- };
38
- export const resolveExactIssuesFilePath = async (pathOrDir, label) => {
39
- if (!pathOrDir) {
40
- return undefined;
41
- }
42
- const path = resolve(pathOrDir);
43
- if (extname(path).toLowerCase() !== ".json") {
44
- throw new Error(`Invalid ${label} path ${JSON.stringify(pathOrDir)}: expected exact .json file path`);
45
- }
46
- try {
47
- const pathStats = await stat(path);
48
- if (pathStats.isDirectory()) {
49
- throw new Error(`Invalid ${label} path ${JSON.stringify(pathOrDir)}: expected file, got directory`);
50
- }
51
- }
52
- catch (e) {
53
- if (!isFileNotFoundError(e)) {
54
- throw e;
55
- }
56
- }
57
- return path;
58
- };
59
- export const readKnownIssues = async (knownIssuePath) => {
60
- const path = await resolveExactIssuesFilePath(knownIssuePath, "known issues");
61
- if (!path) {
62
- return [];
63
- }
64
- try {
65
- const content = await readFile(path, { encoding: "utf-8" });
66
- return JSON.parse(content);
67
- }
68
- catch (e) {
69
- if (isFileNotFoundError(e)) {
70
- return [];
71
- }
72
- throw e;
73
- }
74
- };
75
- const writeKnownIssueRecords = async (knownIssues, knownIssuesPath) => {
76
- const path = await resolveExactIssuesFilePath(knownIssuesPath, "known issues");
77
- if (!path) {
78
- return;
79
- }
80
- await mkdir(dirname(path), { recursive: true });
81
- await writeFile(path, `${JSON.stringify(knownIssues)}\n`, "utf-8");
82
- };
83
- export const writeKnownIssues = async (store, knownIssuesPath) => {
84
- const knownIssues = await store.allKnownIssues();
85
- await writeKnownIssueRecords(knownIssues, knownIssuesPath);
86
- };