@allurereport/core 3.0.0-beta.12 → 3.0.0-beta.14

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/dist/plugin.js CHANGED
@@ -11,7 +11,8 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
11
11
  };
12
12
  var _DefaultPluginState_state, _PluginFiles_parent, _PluginFiles_pluginId, _InMemoryReportFiles_state, _FileSystemReportFiles_output;
13
13
  import { mkdir, writeFile } from "node:fs/promises";
14
- import { dirname, join, resolve } from "node:path";
14
+ import { dirname, resolve } from "node:path";
15
+ import { join as joinPosix } from "node:path/posix";
15
16
  export class DefaultPluginState {
16
17
  constructor(state) {
17
18
  _DefaultPluginState_state.set(this, void 0);
@@ -33,7 +34,7 @@ export class PluginFiles {
33
34
  _PluginFiles_parent.set(this, void 0);
34
35
  _PluginFiles_pluginId.set(this, void 0);
35
36
  this.addFile = async (key, data) => {
36
- await __classPrivateFieldGet(this, _PluginFiles_parent, "f").addFile(join(__classPrivateFieldGet(this, _PluginFiles_pluginId, "f"), key), data);
37
+ await __classPrivateFieldGet(this, _PluginFiles_parent, "f").addFile(joinPosix(__classPrivateFieldGet(this, _PluginFiles_pluginId, "f"), key), data);
37
38
  };
38
39
  __classPrivateFieldSet(this, _PluginFiles_parent, parent, "f");
39
40
  __classPrivateFieldSet(this, _PluginFiles_pluginId, pluginId, "f");
package/dist/report.js CHANGED
@@ -17,7 +17,7 @@ import console from "node:console";
17
17
  import { randomUUID } from "node:crypto";
18
18
  import { EventEmitter } from "node:events";
19
19
  import { readFileSync } from "node:fs";
20
- import { opendir, readdir, realpath, rename, rm } from "node:fs/promises";
20
+ import { lstat, opendir, readdir, realpath, rename, rm } from "node:fs/promises";
21
21
  import { dirname, join, resolve } from "node:path";
22
22
  import { createHistory, writeHistory } from "./history.js";
23
23
  import { DefaultPluginState, PluginFiles } from "./plugin.js";
@@ -126,7 +126,7 @@ export class AllureReport {
126
126
  }
127
127
  summaries.push({
128
128
  ...summary,
129
- href: join("/", id),
129
+ href: `${id}/`,
130
130
  });
131
131
  });
132
132
  if (__classPrivateFieldGet(this, _AllureReport_appendHistory, "f")) {
@@ -136,8 +136,13 @@ export class AllureReport {
136
136
  await writeHistory(__classPrivateFieldGet(this, _AllureReport_historyPath, "f"), historyDataPoint);
137
137
  }
138
138
  const outputDirFiles = await readdir(__classPrivateFieldGet(this, _AllureReport_output, "f"));
139
- if (outputDirFiles.length === 1) {
140
- const reportPath = join(__classPrivateFieldGet(this, _AllureReport_output, "f"), outputDirFiles[0]);
139
+ if (outputDirFiles.length === 0) {
140
+ return;
141
+ }
142
+ const reportPath = join(__classPrivateFieldGet(this, _AllureReport_output, "f"), outputDirFiles[0]);
143
+ const outputEntriesStats = await Promise.all(outputDirFiles.map((file) => lstat(join(__classPrivateFieldGet(this, _AllureReport_output, "f"), file))));
144
+ const outputDirectoryEntries = outputEntriesStats.filter((entry) => entry.isDirectory());
145
+ if (outputDirectoryEntries.length === 1) {
141
146
  const reportContent = await readdir(reportPath);
142
147
  for (const entry of reportContent) {
143
148
  const currentFilePath = join(reportPath, entry);
@@ -147,10 +152,9 @@ export class AllureReport {
147
152
  await rm(reportPath, { recursive: true });
148
153
  return;
149
154
  }
150
- if (summaries.length === 0) {
151
- return;
155
+ if (summaries.length > 1) {
156
+ await generateSummary(__classPrivateFieldGet(this, _AllureReport_output, "f"), summaries);
152
157
  }
153
- await generateSummary(__classPrivateFieldGet(this, _AllureReport_output, "f"), summaries);
154
158
  };
155
159
  _AllureReport_eachPlugin.set(this, async (initState, consumer) => {
156
160
  if (initState) {
@@ -181,7 +181,7 @@ const convertStep = (stateData, step) => {
181
181
  stepId: md5(`${step.name}${step.start}`),
182
182
  name: step.name ?? __unknown,
183
183
  status: step.status ?? defaultStatus,
184
- steps: convertSteps(stateData, step.steps),
184
+ steps: subSteps,
185
185
  parameters: convertParameters(step.parameters),
186
186
  ...processTimings(step),
187
187
  type: "step",
@@ -43,8 +43,9 @@ export declare class DefaultAllureStore implements AllureStore, ResultsVisitor {
43
43
  metadataByKey<T>(key: string): Promise<T | undefined>;
44
44
  testResultsByTcId(tcId: string): Promise<TestResult[]>;
45
45
  attachmentsByTrId(trId: string): Promise<AttachmentLink[]>;
46
- retriesByTr(tr: TestResult): TestResult[];
46
+ retriesByTr(tr: TestResult): Promise<TestResult[]>;
47
47
  retriesByTrId(trId: string): Promise<TestResult[]>;
48
+ historyByTr(tr: TestResult): Promise<HistoryTestResult[]>;
48
49
  historyByTrId(trId: string): Promise<HistoryTestResult[]>;
49
50
  fixturesByTrId(trId: string): Promise<TestFixtureResult[]>;
50
51
  failedTestResults(): Promise<TestResult[]>;
@@ -12,6 +12,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
12
12
  var _DefaultAllureStore_testResults, _DefaultAllureStore_attachments, _DefaultAllureStore_attachmentContents, _DefaultAllureStore_testCases, _DefaultAllureStore_metadata, _DefaultAllureStore_history, _DefaultAllureStore_known, _DefaultAllureStore_fixtures, _DefaultAllureStore_defaultLabels, _DefaultAllureStore_environmentsConfig, _DefaultAllureStore_reportVariables, _DefaultAllureStore_eventEmitter;
13
13
  import { compareBy, getWorstStatus, matchEnvironment, nullsLast, ordinal, reverse, } from "@allurereport/core-api";
14
14
  import { md5 } from "@allurereport/plugin-api";
15
+ import { isFlaky } from "../utils/flaky.js";
15
16
  import { getTestResultsStats } from "../utils/stats.js";
16
17
  import { testFixtureResultRawToState, testResultRawToState } from "./convert.js";
17
18
  const index = (indexMap, key, ...items) => {
@@ -86,6 +87,8 @@ export class DefaultAllureStore {
86
87
  });
87
88
  }
88
89
  testResult.environment = matchEnvironment(__classPrivateFieldGet(this, _DefaultAllureStore_environmentsConfig, "f"), testResult);
90
+ const trHistory = await this.historyByTr(testResult);
91
+ testResult.flaky = isFlaky(testResult, trHistory);
89
92
  __classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").set(testResult.id, testResult);
90
93
  if (testResult.historyId) {
91
94
  const maybeOther = this.indexLatestEnvTestResultByHistoryId
@@ -200,7 +203,7 @@ export class DefaultAllureStore {
200
203
  async attachmentsByTrId(trId) {
201
204
  return this.indexAttachmentByTestResult.get(trId) ?? [];
202
205
  }
203
- retriesByTr(tr) {
206
+ async retriesByTr(tr) {
204
207
  if (!tr || tr.hidden || !tr.historyId) {
205
208
  return [];
206
209
  }
@@ -210,13 +213,9 @@ export class DefaultAllureStore {
210
213
  }
211
214
  async retriesByTrId(trId) {
212
215
  const tr = await this.testResultById(trId);
213
- if (!tr) {
214
- return [];
215
- }
216
- return this.retriesByTr(tr);
216
+ return tr ? this.retriesByTr(tr) : [];
217
217
  }
218
- async historyByTrId(trId) {
219
- const tr = await this.testResultById(trId);
218
+ async historyByTr(tr) {
220
219
  if (!tr?.historyId) {
221
220
  return [];
222
221
  }
@@ -224,6 +223,10 @@ export class DefaultAllureStore {
224
223
  .filter((dp) => !!dp.testResults[tr.historyId])
225
224
  .map((dp) => ({ ...dp.testResults[tr.historyId] }));
226
225
  }
226
+ async historyByTrId(trId) {
227
+ const tr = await this.testResultById(trId);
228
+ return tr ? this.historyByTr(tr) : [];
229
+ }
227
230
  async fixturesByTrId(trId) {
228
231
  return this.indexFixturesByTestResult.get(trId) ?? [];
229
232
  }
@@ -261,11 +264,16 @@ export class DefaultAllureStore {
261
264
  }
262
265
  async testsStatistic(filter) {
263
266
  const all = await this.allTestResults();
264
- const allWithRetries = all.map((tr) => ({
265
- ...tr,
266
- retries: this.retriesByTr(tr),
267
+ const allWithStats = await Promise.all(all.map(async (tr) => {
268
+ const trHistory = await this.historyByTr(tr);
269
+ const retries = await this.retriesByTr(tr);
270
+ return {
271
+ ...tr,
272
+ flaky: isFlaky(tr, trHistory),
273
+ retries,
274
+ };
267
275
  }));
268
- return getTestResultsStats(allWithRetries, filter);
276
+ return getTestResultsStats(allWithStats, filter);
269
277
  }
270
278
  async allEnvironments() {
271
279
  return Array.from(new Set(["default", ...Object.keys(__classPrivateFieldGet(this, _DefaultAllureStore_environmentsConfig, "f"))]));
@@ -0,0 +1,2 @@
1
+ import type { HistoryTestResult, TestResult } from "@allurereport/core-api";
2
+ export declare const isFlaky: (tr: TestResult, history: HistoryTestResult[]) => boolean;
@@ -0,0 +1,12 @@
1
+ const MAX_LAST_HISTORY_SIZE = 5;
2
+ const badStatuses = ["failed", "broken"];
3
+ const isAllureClassicFlaky = (tr, history) => {
4
+ if (history.length === 0 || !badStatuses.includes(tr.status)) {
5
+ return false;
6
+ }
7
+ const limitedLastHistory = history.slice(-MAX_LAST_HISTORY_SIZE);
8
+ const limitedLastHistoryStatuses = limitedLastHistory.map((h) => h.status);
9
+ return (limitedLastHistoryStatuses.includes("passed") &&
10
+ limitedLastHistoryStatuses.indexOf("passed") < limitedLastHistoryStatuses.lastIndexOf("failed"));
11
+ };
12
+ export const isFlaky = (tr, history) => tr.flaky || isAllureClassicFlaky(tr, history);
@@ -7,6 +7,9 @@ export const getTestResultsStats = (trs, filter = () => true) => {
7
7
  if (tr.retries && tr.retries?.length > 0) {
8
8
  acc.retries = (acc.retries ?? 0) + 1;
9
9
  }
10
+ if (tr.flaky) {
11
+ acc.flaky = (acc.flaky ?? 0) + 1;
12
+ }
10
13
  if (!acc[tr.status]) {
11
14
  acc[tr.status] = 0;
12
15
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/core",
3
- "version": "3.0.0-beta.12",
3
+ "version": "3.0.0-beta.14",
4
4
  "description": "Collection of generic Allure utilities used across the entire project",
5
5
  "keywords": [
6
6
  "allure"
@@ -25,20 +25,20 @@
25
25
  "test": "vitest run"
26
26
  },
27
27
  "dependencies": {
28
- "@allurereport/core-api": "3.0.0-beta.12",
29
- "@allurereport/plugin-allure2": "3.0.0-beta.12",
30
- "@allurereport/plugin-api": "3.0.0-beta.12",
31
- "@allurereport/plugin-awesome": "3.0.0-beta.12",
32
- "@allurereport/plugin-classic": "3.0.0-beta.12",
33
- "@allurereport/plugin-csv": "3.0.0-beta.12",
34
- "@allurereport/plugin-dashboard": "3.0.0-beta.12",
35
- "@allurereport/plugin-log": "3.0.0-beta.12",
36
- "@allurereport/plugin-progress": "3.0.0-beta.12",
37
- "@allurereport/plugin-slack": "3.0.0-beta.12",
38
- "@allurereport/plugin-testplan": "3.0.0-beta.12",
39
- "@allurereport/reader": "3.0.0-beta.12",
40
- "@allurereport/reader-api": "3.0.0-beta.12",
41
- "@allurereport/summary": "3.0.0-beta.12",
28
+ "@allurereport/core-api": "3.0.0-beta.14",
29
+ "@allurereport/plugin-allure2": "3.0.0-beta.14",
30
+ "@allurereport/plugin-api": "3.0.0-beta.14",
31
+ "@allurereport/plugin-awesome": "3.0.0-beta.14",
32
+ "@allurereport/plugin-classic": "3.0.0-beta.14",
33
+ "@allurereport/plugin-csv": "3.0.0-beta.14",
34
+ "@allurereport/plugin-dashboard": "3.0.0-beta.14",
35
+ "@allurereport/plugin-log": "3.0.0-beta.14",
36
+ "@allurereport/plugin-progress": "3.0.0-beta.14",
37
+ "@allurereport/plugin-slack": "3.0.0-beta.14",
38
+ "@allurereport/plugin-testplan": "3.0.0-beta.14",
39
+ "@allurereport/reader": "3.0.0-beta.14",
40
+ "@allurereport/reader-api": "3.0.0-beta.14",
41
+ "@allurereport/summary": "3.0.0-beta.14",
42
42
  "handlebars": "^4.7.8",
43
43
  "markdown-it": "^14.1.0"
44
44
  },