@allurereport/core 3.18.0 → 3.19.1

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/config.js CHANGED
@@ -91,6 +91,7 @@ export const validateConfig = (config) => {
91
91
  "historyPath",
92
92
  "historyBaseUrl",
93
93
  "historyLimit",
94
+ "flakyDetection",
94
95
  "resolutions",
95
96
  "plugins",
96
97
  "defaultLabels",
@@ -184,12 +185,25 @@ const resolveConfigEnvironments = (config) => {
184
185
  allowedEnvironments,
185
186
  };
186
187
  };
188
+ const validateFlakyDetectionConfig = (config) => {
189
+ if (config === undefined) {
190
+ return;
191
+ }
192
+ const { historyDepth, includePassedTests } = config;
193
+ if (historyDepth !== undefined && (!Number.isInteger(historyDepth) || historyDepth < -1)) {
194
+ throw new Error("flakyDetection.historyDepth must be an integer greater than or equal to -1");
195
+ }
196
+ if (includePassedTests !== undefined && typeof includePassedTests !== "boolean") {
197
+ throw new TypeError("flakyDetection.includePassedTests must be a boolean");
198
+ }
199
+ };
187
200
  export const resolveConfig = async (config, override = {}) => {
188
201
  const validationResult = validateConfig(config);
189
202
  if (!validationResult.valid) {
190
203
  throw new Error(`The provided Allure config contains unsupported fields: ${validationResult.fields.join(", ")}`);
191
204
  }
192
205
  validateResolutionsConfig(config.resolutions);
206
+ validateFlakyDetectionConfig(config.flakyDetection);
193
207
  const { environments, environment, allowedEnvironments } = resolveConfigEnvironments(config);
194
208
  const name = override.name ?? config.name ?? "Allure Report";
195
209
  const open = override.open ?? config.open ?? false;
@@ -246,6 +260,7 @@ export const resolveConfig = async (config, override = {}) => {
246
260
  environments,
247
261
  appendHistory,
248
262
  historyLimit,
263
+ flakyDetection: config.flakyDetection,
249
264
  historyPath: historyPath ? resolve(historyPath) : undefined,
250
265
  historyBaseUrl,
251
266
  dump,
package/dist/history.js CHANGED
@@ -19,8 +19,8 @@ import { normalizeHistoryDataPointUrls, } from "@allurereport/core-api";
19
19
  import { isFileNotFoundError } from "./utils/misc.js";
20
20
  const createHistoryItems = (testResults, remoteUrl) => {
21
21
  return testResults
22
- .filter((tr) => tr.historyId)
23
- .map(({ id, name, fullName, environment, historyId, status, error: { message, trace } = {}, start, stop, duration, labels, }) => {
22
+ .filter((tr) => tr.retryHash)
23
+ .map(({ id, name, fullName, environment, retryHash, status, error: { message, trace } = {}, start, stop, duration, labels, }) => {
24
24
  return {
25
25
  id,
26
26
  name,
@@ -34,12 +34,12 @@ const createHistoryItems = (testResults, remoteUrl) => {
34
34
  duration,
35
35
  labels,
36
36
  url: remoteUrl,
37
- historyId: historyId,
37
+ retryHash: retryHash,
38
38
  reportLinks: [],
39
39
  };
40
40
  })
41
41
  .reduce((acc, item) => {
42
- acc[item.historyId] = item;
42
+ acc[item.retryHash] = item;
43
43
  return acc;
44
44
  }, {});
45
45
  };
@@ -228,7 +228,9 @@ export class AllureLocalHistory {
228
228
  }
229
229
  finally {
230
230
  const closing = historyFile.close();
231
- dst?.destroy();
231
+ if (historyFile.fd !== -1) {
232
+ dst?.destroy();
233
+ }
232
234
  await closing;
233
235
  if (limit !== 0) {
234
236
  __classPrivateFieldGet(this, _AllureLocalHistory_cachedHistory, "f").push(normalizedData);
package/dist/index.d.ts CHANGED
@@ -11,4 +11,4 @@ export * from "./resolutions.js";
11
11
  export { resolveConfig, readConfig, readRawConfig, getPluginInstance } from "./config.js";
12
12
  export * from "./report.js";
13
13
  export * from "./plugin.js";
14
- export { QualityGateState, qualityGateDefaultRules, maxFailuresRule, minTestsCountRule, successRateRule, maxDurationRule, allTestsContainEnvRule, environmentsTestedRule, metricMaxRule, metricMinRule, metricMaxDeltaRule, metricMaxDeltaPercentRule, convertQualityGateResultsToTestErrors, filterFailedQualityGateResults, stringifyQualityGateResults, } from "./qualityGate/index.js";
14
+ export { QualityGateState, qualityGateDefaultRules, maxFailuresRule, minTestsCountRule, newTestsRule, successRateRule, maxDurationRule, allTestsContainEnvRule, environmentsTestedRule, metricMaxRule, metricMinRule, metricMaxDeltaRule, metricMaxDeltaPercentRule, convertQualityGateResultsToTestErrors, filterFailedQualityGateResults, stringifyQualityGateResults, } from "./qualityGate/index.js";
package/dist/index.js CHANGED
@@ -10,4 +10,4 @@ export * from "./resolutions.js";
10
10
  export { resolveConfig, readConfig, readRawConfig, getPluginInstance } from "./config.js";
11
11
  export * from "./report.js";
12
12
  export * from "./plugin.js";
13
- export { QualityGateState, qualityGateDefaultRules, maxFailuresRule, minTestsCountRule, successRateRule, maxDurationRule, allTestsContainEnvRule, environmentsTestedRule, metricMaxRule, metricMinRule, metricMaxDeltaRule, metricMaxDeltaPercentRule, convertQualityGateResultsToTestErrors, filterFailedQualityGateResults, stringifyQualityGateResults, } from "./qualityGate/index.js";
13
+ export { QualityGateState, qualityGateDefaultRules, maxFailuresRule, minTestsCountRule, newTestsRule, successRateRule, maxDurationRule, allTestsContainEnvRule, environmentsTestedRule, metricMaxRule, metricMinRule, metricMaxDeltaRule, metricMaxDeltaPercentRule, convertQualityGateResultsToTestErrors, filterFailedQualityGateResults, stringifyQualityGateResults, } from "./qualityGate/index.js";
@@ -71,7 +71,7 @@ export class QualityGate {
71
71
  }
72
72
  trsToValidateById.set(tr.id, tr);
73
73
  }
74
- const trsToValidate = trsToValidateById.values().toArray();
74
+ const trsToValidate = [...trsToValidateById.values()];
75
75
  const { rules, use = [...qualityGateDefaultRules] } = this.config;
76
76
  const results = [];
77
77
  let fastFailed = false;
@@ -7,6 +7,7 @@ type MetricRuleConfig = {
7
7
  };
8
8
  export declare const maxFailuresRule: QualityGateRule<number>;
9
9
  export declare const minTestsCountRule: QualityGateRule<number>;
10
+ export declare const newTestsRule: QualityGateRule<boolean, number>;
10
11
  export declare const successRateRule: QualityGateRule<number>;
11
12
  export declare const maxDurationRule: QualityGateRule<number>;
12
13
  export declare const allTestsContainEnvRule: QualityGateRule<string, number>;
@@ -15,5 +16,5 @@ export declare const metricMaxRule: QualityGateRule<MetricRuleConfig>;
15
16
  export declare const metricMinRule: QualityGateRule<MetricRuleConfig>;
16
17
  export declare const metricMaxDeltaRule: QualityGateRule<MetricRuleConfig>;
17
18
  export declare const metricMaxDeltaPercentRule: QualityGateRule<MetricRuleConfig>;
18
- export declare const qualityGateDefaultRules: (QualityGateRule<number> | QualityGateRule<string, number> | QualityGateRule<string[]> | QualityGateRule<MetricRuleConfig>)[];
19
+ export declare const qualityGateDefaultRules: (QualityGateRule<number> | QualityGateRule<boolean, number> | QualityGateRule<string, number> | QualityGateRule<string[]> | QualityGateRule<MetricRuleConfig>)[];
19
20
  export {};
@@ -41,12 +41,17 @@ const metricActual = (metrics, key, value) => {
41
41
  ...(sample?.unit ? { unit: sample.unit } : {}),
42
42
  };
43
43
  };
44
+ const formatQualityGateNumber = (value) => {
45
+ if (!Number.isFinite(value)) {
46
+ return String(value);
47
+ }
48
+ return Number.isInteger(value) ? String(value) : String(Number(value.toFixed(3)));
49
+ };
44
50
  const formatMetricValue = (value, unit) => {
45
51
  if (!Number.isFinite(value)) {
46
52
  return "n/a";
47
53
  }
48
- const finiteValue = value;
49
- const formatted = Number.isInteger(finiteValue) ? String(finiteValue) : String(Number(finiteValue.toFixed(3)));
54
+ const formatted = formatQualityGateNumber(value);
50
55
  return unit ? `${formatted} ${unit}` : formatted;
51
56
  };
52
57
  const metricRuleTitle = (actual) => actual.title ?? actual.key;
@@ -101,10 +106,29 @@ export const minTestsCountRule = {
101
106
  };
102
107
  },
103
108
  };
109
+ export const newTestsRule = {
110
+ rule: "newTests",
111
+ message: ({ actual, expected }) => expected
112
+ ? `No new tests were found; expected at least one new test`
113
+ : `The number of new tests ${bold(String(actual))} does not match the expected policy`,
114
+ successMessage: ({ actual }) => `New tests were found: ${bold(String(actual))}`,
115
+ validate: async ({ trs, expected, state }) => {
116
+ const previous = numberStateValue(state.getResult());
117
+ const newTrs = trs.filter((tr) => tr.transition === "new");
118
+ const testResults = newTrs.map((tr) => tr.id);
119
+ const actual = previous + newTrs.length;
120
+ state.setResult(actual, testResults);
121
+ return {
122
+ success: !expected || actual > 0,
123
+ actual,
124
+ testResults,
125
+ };
126
+ },
127
+ };
104
128
  export const successRateRule = {
105
129
  rule: "successRate",
106
- message: ({ actual, expected }) => `Success rate ${bold(String(actual))} is less, than expected ${bold(String(expected))}`,
107
- successMessage: ({ actual, expected }) => `Success rate ${bold(String(actual))} is not less, than expected ${bold(String(expected))}`,
130
+ message: ({ actual, expected }) => `Success rate ${bold(formatQualityGateNumber(actual))} is less, than expected ${bold(formatQualityGateNumber(expected))}`,
131
+ successMessage: ({ actual, expected }) => `Success rate ${bold(formatQualityGateNumber(actual))} is not less, than expected ${bold(formatQualityGateNumber(expected))}`,
108
132
  validate: async ({ trs, expected, state }) => {
109
133
  const previous = successRateStateValue(state.getResult());
110
134
  const eligibleTrs = trs.filter(filterIncludedInSuccessRate);
@@ -232,6 +256,7 @@ export const metricMaxDeltaPercentRule = {
232
256
  export const qualityGateDefaultRules = [
233
257
  maxFailuresRule,
234
258
  minTestsCountRule,
259
+ newTestsRule,
235
260
  successRateRule,
236
261
  maxDurationRule,
237
262
  allTestsContainEnvRule,
package/dist/report.js CHANGED
@@ -22,7 +22,7 @@ import { detect } from "@allurereport/ci";
22
22
  import { createProgressLogger } from "@allurereport/cli-commons";
23
23
  import { normalizeCategoriesConfig, parseIntegerConfigValue } from "@allurereport/core-api";
24
24
  import { AllureStoreDumpFiles, createTestResultRegistry, } from "@allurereport/plugin-api";
25
- import { allure1, allure2, attachments, cucumberjson, junitXml, readXcResultBundle } from "@allurereport/reader";
25
+ import { allure1, allure2, attachments, cucumberjson, cucumberMessages, junitXml, readXcResultBundle, } from "@allurereport/reader";
26
26
  import { PathResultFile } from "@allurereport/reader-api";
27
27
  import { AllureRemoteHistory, AllureServiceClient, AllureTestOpsClient, KnownError, UnknownError, } from "@allurereport/service";
28
28
  import { generateSummary } from "@allurereport/summary";
@@ -37,7 +37,7 @@ import { writeKnownIssues } from "./resolutions.js";
37
37
  import { DefaultAllureStore } from "./store/store.js";
38
38
  import { ARTIFACTS_MANIFEST_FILENAME, createReportArtifact, deduplicateDumpInputs, } from "./utils/artifacts.js";
39
39
  import { environmentIdentityById, environmentIdentityByName } from "./utils/environment.js";
40
- import { getPerfMetricsResults, isPerfMetricsEnabled, measurePerf, PERF_METRIC_NAMES, PERF_METRIC_PREFIXES, perfMetricsFileName, startPerfSpan, writePerfMetrics, } from "./utils/perf.js";
40
+ import { getPerfMetricsResults, incrementPerfCounter, isPerfMetricsEnabled, measurePerfAggregate, measurePerf, PERF_METRIC_NAMES, PERF_METRIC_PREFIXES, perfMetricsFileName, startPerfSpan, writePerfMetrics, } from "./utils/perf.js";
41
41
  import { RealtimeChannel } from "./utils/realtimeChannel.js";
42
42
  import { RealtimeUpdateScheduler } from "./utils/realtimeUpdateScheduler.js";
43
43
  import { resolveDumpAttachmentPath, UnsafeDumpPathError } from "./utils/safeDumpPath.js";
@@ -53,6 +53,11 @@ const ROOT_INTEGRATION_FILENAMES = new Set([
53
53
  QUALITY_GATE_RESULTS_FILENAME,
54
54
  ARTIFACTS_MANIFEST_FILENAME,
55
55
  ]);
56
+ const WORKLOAD_PERF_METRIC = {
57
+ group: "workload",
58
+ groupTitle: "Workload",
59
+ better: "neutral",
60
+ };
56
61
  const readConcurrency = () => {
57
62
  const parsed = Number.parseInt(process.env.ALLURE_READ_CONCURRENCY ?? "", 10);
58
63
  if (!Number.isFinite(parsed)) {
@@ -298,17 +303,23 @@ export class AllureReport {
298
303
  throw new Error(INIT_REQUIRED_ERROR_MESSAGE);
299
304
  }
300
305
  const resultsDirPath = resolve(resultsDir);
301
- if (await readXcResultBundle(__classPrivateFieldGet(this, _AllureReport_store, "f"), resultsDirPath)) {
306
+ if (await measurePerf(PERF_METRIC_NAMES.generateReadResultsXcresultCheck, () => readXcResultBundle(__classPrivateFieldGet(this, _AllureReport_store, "f"), resultsDirPath))) {
307
+ __classPrivateFieldGet(this, _AllureReport_store, "f").updateHistoryFlags();
302
308
  return;
303
309
  }
304
310
  try {
305
- const entries = (await readdir(resultsDirPath, { withFileTypes: true }))
311
+ const entries = await measurePerf(PERF_METRIC_NAMES.generateReadResultsReaddir, async () => (await readdir(resultsDirPath, { withFileTypes: true }))
306
312
  .filter((dirent) => dirent.isFile() && !dirent.name.endsWith(".tmp"))
307
- .sort((a, b) => a.name.localeCompare(b.name));
313
+ .sort((a, b) => a.name.localeCompare(b.name)));
308
314
  const limit = pLimit(readConcurrency());
315
+ incrementPerfCounter(PERF_METRIC_NAMES.generateReadResultsFiles, entries.length, {
316
+ ...WORKLOAD_PERF_METRIC,
317
+ title: "Input files",
318
+ unit: "files",
319
+ });
309
320
  await Promise.all(entries.map((dirent) => limit(async () => {
310
321
  try {
311
- const path = await realpath(join(resultsDirPath, dirent.name));
322
+ const path = await measurePerfAggregate(PERF_METRIC_NAMES.generateReadResultsRealpath, () => realpath(join(resultsDirPath, dirent.name)));
312
323
  await this.readResult(new PathResultFile(path, dirent.name));
313
324
  }
314
325
  catch (e) {
@@ -319,12 +330,14 @@ export class AllureReport {
319
330
  catch (e) {
320
331
  console.error("can't read directory", e);
321
332
  }
333
+ __classPrivateFieldGet(this, _AllureReport_store, "f").updateHistoryFlags();
322
334
  });
323
335
  this.readFile = async (resultsFile) => measurePerf(PERF_METRIC_NAMES.generateReadResults, async () => {
324
336
  if (__classPrivateFieldGet(this, _AllureReport_executionStage, "f") !== "running") {
325
337
  throw new Error(INIT_REQUIRED_ERROR_MESSAGE);
326
338
  }
327
339
  await this.readResult(new PathResultFile(resultsFile));
340
+ __classPrivateFieldGet(this, _AllureReport_store, "f").updateHistoryFlags();
328
341
  });
329
342
  this.readResult = async (data) => {
330
343
  if (__classPrivateFieldGet(this, _AllureReport_executionStage, "f") !== "running") {
@@ -335,7 +348,7 @@ export class AllureReport {
335
348
  if (reader.matches && !(await reader.matches(data))) {
336
349
  continue;
337
350
  }
338
- const processed = await reader.read(__classPrivateFieldGet(this, _AllureReport_store, "f"), data);
351
+ const processed = await measurePerfAggregate(PERF_METRIC_NAMES.generateReadResultsReaderRead, () => reader.read(__classPrivateFieldGet(this, _AllureReport_store, "f"), data));
339
352
  if (processed) {
340
353
  return;
341
354
  }
@@ -345,6 +358,9 @@ export class AllureReport {
345
358
  };
346
359
  this.validate = async (params) => {
347
360
  const { trs, state, environment } = params;
361
+ if (__classPrivateFieldGet(this, _AllureReport_executionStage, "f") !== "done") {
362
+ __classPrivateFieldGet(this, _AllureReport_store, "f").updateHistoryFlags(trs.filter(Boolean));
363
+ }
348
364
  const qualityGateEnvironment = environment === undefined
349
365
  ? undefined
350
366
  : (environmentIdentityById(__classPrivateFieldGet(this, _AllureReport_environments, "f"), environment)?.name ??
@@ -370,6 +386,7 @@ export class AllureReport {
370
386
  if (__classPrivateFieldGet(this, _AllureReport_executionStage, "f") === "done") {
371
387
  throw new Error("the report is already stopped, the restart isn't supported at the moment");
372
388
  }
389
+ __classPrivateFieldGet(this, _AllureReport_store, "f").updateHistoryFlags();
373
390
  __classPrivateFieldSet(this, _AllureReport_executionStage, "running", "f");
374
391
  __classPrivateFieldSet(this, _AllureReport_endGeneratePerfSpan, startPerfSpan(PERF_METRIC_NAMES.generateTotal), "f");
375
392
  if (__classPrivateFieldGet(this, _AllureReport_globalAttachments, "f")?.length) {
@@ -399,6 +416,7 @@ export class AllureReport {
399
416
  if (__classPrivateFieldGet(this, _AllureReport_executionStage, "f") !== "running") {
400
417
  return;
401
418
  }
419
+ __classPrivateFieldGet(this, _AllureReport_store, "f").updateHistoryFlags();
402
420
  await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, false, async (plugin, context) => {
403
421
  await plugin.update?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"));
404
422
  });
@@ -449,7 +467,7 @@ export class AllureReport {
449
467
  const addJsonDumpEntry = async (entryName, value) => {
450
468
  await addRequiredDumpEntry(Buffer.from(JSON.stringify(value)), entryName);
451
469
  };
452
- const dumpJsonEntries = ({ testResults, testCases, fixtures, attachments, environments, reportVariables, checkResults = {}, globalAttachmentIds = [], globalErrors = [], indexAttachmentByTestResult = {}, indexTestResultByHistoryId = {}, indexTestResultByTestCase = {}, indexTestResultByResolutionIssue = {}, indexAttachmentByFixture = {}, indexFixturesByTestResult = {}, resolutionIssues = {}, qualityGateResults = [], testResultIdsIngestOrder = [], metrics = [], }) => [
470
+ const dumpJsonEntries = ({ testResults, testCases, fixtures, attachments, environments, reportVariables, metadata = {}, checkResults = {}, globalAttachmentIds = [], globalErrors = [], indexAttachmentByTestResult = {}, indexTestResultByRetryHash = {}, indexTestResultByTestCase = {}, indexTestResultByResolutionIssue = {}, indexAttachmentByFixture = {}, indexFixturesByTestResult = {}, resolutionIssues = {}, qualityGateResults = [], testResultIdsIngestOrder = [], metrics = [], }) => [
453
471
  [AllureStoreDumpFiles.TestResults, testResults],
454
472
  [AllureStoreDumpFiles.TestCases, testCases],
455
473
  [AllureStoreDumpFiles.Fixtures, fixtures],
@@ -457,11 +475,12 @@ export class AllureReport {
457
475
  [AllureStoreDumpFiles.CheckResults, checkResults],
458
476
  [AllureStoreDumpFiles.Environments, environments],
459
477
  [AllureStoreDumpFiles.ReportVariables, reportVariables],
478
+ [AllureStoreDumpFiles.Metadata, metadata],
460
479
  [AllureStoreDumpFiles.ResolutionIssues, resolutionIssues],
461
480
  [AllureStoreDumpFiles.GlobalAttachments, globalAttachmentIds],
462
481
  [AllureStoreDumpFiles.GlobalErrors, globalErrors],
463
482
  [AllureStoreDumpFiles.IndexAttachmentsByTestResults, indexAttachmentByTestResult],
464
- [AllureStoreDumpFiles.IndexTestResultsByHistoryId, indexTestResultByHistoryId],
483
+ [AllureStoreDumpFiles.IndexTestResultsByRetryHash, indexTestResultByRetryHash],
465
484
  [AllureStoreDumpFiles.IndexTestResultsByTestCase, indexTestResultByTestCase],
466
485
  [AllureStoreDumpFiles.IndexTestResultsByResolutionIssue, indexTestResultByResolutionIssue],
467
486
  [AllureStoreDumpFiles.IndexAttachmentsByFixture, indexAttachmentByFixture],
@@ -537,6 +556,7 @@ export class AllureReport {
537
556
  this.restoreState = async (dumps) => {
538
557
  __classPrivateFieldGet(this, _AllureReport_store, "f").resetIngestOrder();
539
558
  await __classPrivateFieldGet(this, _AllureReport_restoreStateDumps, "f").call(this, dumps.map((path) => ({ artifactPath: path, path })));
559
+ __classPrivateFieldGet(this, _AllureReport_store, "f").updateHistoryFlags();
540
560
  };
541
561
  _AllureReport_recordArtifact.set(this, (filePath, name = basename(filePath)) => {
542
562
  const artifact = createReportArtifact(filePath, __classPrivateFieldGet(this, _AllureReport_getCwd, "f").call(this), name);
@@ -604,11 +624,10 @@ export class AllureReport {
604
624
  const checkResultsEntry = await optionalEntryData(AllureStoreDumpFiles.CheckResults);
605
625
  const environmentsEntry = await requiredEntryData(AllureStoreDumpFiles.Environments);
606
626
  const reportVariablesEntry = await requiredEntryData(AllureStoreDumpFiles.ReportVariables);
627
+ const metadataEntry = await optionalEntryData(AllureStoreDumpFiles.Metadata);
607
628
  const globalAttachmentsEntry = await requiredEntryData(AllureStoreDumpFiles.GlobalAttachments);
608
629
  const globalErrorsEntry = await requiredEntryData(AllureStoreDumpFiles.GlobalErrors);
609
630
  const indexAttachmentsEntry = await requiredEntryData(AllureStoreDumpFiles.IndexAttachmentsByTestResults);
610
- const indexTestResultsByHistoryId = await requiredEntryData(AllureStoreDumpFiles.IndexTestResultsByHistoryId);
611
- const indexTestResultsByTestCaseEntry = await requiredEntryData(AllureStoreDumpFiles.IndexTestResultsByTestCase);
612
631
  const indexTestResultsByResolutionIssueEntry = await optionalEntryData(AllureStoreDumpFiles.IndexTestResultsByResolutionIssue);
613
632
  const indexAttachmentsByFixtureEntry = await requiredEntryData(AllureStoreDumpFiles.IndexAttachmentsByFixture);
614
633
  const indexFixturesByTestResultEntry = await requiredEntryData(AllureStoreDumpFiles.IndexFixturesByTestResult);
@@ -626,11 +645,12 @@ export class AllureReport {
626
645
  case AllureStoreDumpFiles.Fixtures:
627
646
  case AllureStoreDumpFiles.Environments:
628
647
  case AllureStoreDumpFiles.ReportVariables:
648
+ case AllureStoreDumpFiles.Metadata:
629
649
  case AllureStoreDumpFiles.ResolutionIssues:
630
650
  case AllureStoreDumpFiles.GlobalAttachments:
631
651
  case AllureStoreDumpFiles.GlobalErrors:
632
652
  case AllureStoreDumpFiles.IndexAttachmentsByTestResults:
633
- case AllureStoreDumpFiles.IndexTestResultsByHistoryId:
653
+ case AllureStoreDumpFiles.IndexTestResultsByRetryHash:
634
654
  case AllureStoreDumpFiles.IndexTestResultsByTestCase:
635
655
  case AllureStoreDumpFiles.IndexTestResultsByResolutionIssue:
636
656
  case AllureStoreDumpFiles.IndexAttachmentsByFixture:
@@ -656,11 +676,12 @@ export class AllureReport {
656
676
  checkResults: checkResultsEntry ? JSON.parse(checkResultsEntry.toString("utf8")) : [],
657
677
  environments: JSON.parse(environmentsEntry.toString("utf8")),
658
678
  reportVariables: JSON.parse(reportVariablesEntry.toString("utf8")),
679
+ metadata: metadataEntry ? JSON.parse(metadataEntry.toString("utf8")) : {},
659
680
  globalAttachmentIds: JSON.parse(globalAttachmentsEntry.toString("utf8")),
660
681
  globalErrors: JSON.parse(globalErrorsEntry.toString("utf8")),
661
682
  indexAttachmentByTestResult: JSON.parse(indexAttachmentsEntry.toString("utf8")),
662
- indexTestResultByHistoryId: JSON.parse(indexTestResultsByHistoryId.toString("utf8")),
663
- indexTestResultByTestCase: JSON.parse(indexTestResultsByTestCaseEntry.toString("utf8")),
683
+ indexTestResultByRetryHash: {},
684
+ indexTestResultByTestCase: {},
664
685
  indexTestResultByResolutionIssue: indexTestResultsByResolutionIssueEntry
665
686
  ? JSON.parse(indexTestResultsByResolutionIssueEntry.toString("utf8"))
666
687
  : {},
@@ -840,6 +861,7 @@ export class AllureReport {
840
861
  console.error("realtime update failed during shutdown", e);
841
862
  }
842
863
  __classPrivateFieldSet(this, _AllureReport_executionStage, "done", "f");
864
+ __classPrivateFieldGet(this, _AllureReport_store, "f").updateHistoryFlags();
843
865
  if (__classPrivateFieldGet(this, _AllureReport_dump, "f")) {
844
866
  await this.dumpState();
845
867
  return;
@@ -970,6 +992,11 @@ export class AllureReport {
970
992
  await pluginState.set("files", {});
971
993
  }
972
994
  const pluginFiles = new PluginFiles(__classPrivateFieldGet(this, _AllureReport_reportFiles, "f"), id, async (key, filepath) => {
995
+ incrementPerfCounter(`${PERF_METRIC_PREFIXES.generatePlugin}${id}.generatedFiles`, 1, {
996
+ ...WORKLOAD_PERF_METRIC,
997
+ title: `Generated ${id} files`,
998
+ unit: "files",
999
+ });
973
1000
  const currentPluginState = __classPrivateFieldGet(this, _AllureReport_instances, "m", _AllureReport_getPluginState).call(this, false, id);
974
1001
  const files = await currentPluginState?.get("files");
975
1002
  if (!files) {
@@ -986,6 +1013,14 @@ export class AllureReport {
986
1013
  hideLabels: __classPrivateFieldGet(this, _AllureReport_hideLabels, "f"),
987
1014
  state: pluginState,
988
1015
  reportFiles: pluginFiles,
1016
+ ...(isPerfMetricsEnabled()
1017
+ ? {
1018
+ perf: {
1019
+ measure: (name, fn) => measurePerf(`${PERF_METRIC_PREFIXES.generatePlugin}${id}.${name}`, fn),
1020
+ count: (name, value, metadata) => incrementPerfCounter(`${PERF_METRIC_PREFIXES.generatePlugin}${id}.${name}`, value, metadata),
1021
+ },
1022
+ }
1023
+ : {}),
989
1024
  reportUrl: this.reportUrl,
990
1025
  realTime: !!__classPrivateFieldGet(this, _AllureReport_realTime, "f"),
991
1026
  output: __classPrivateFieldGet(this, _AllureReport_output, "f"),
@@ -1005,7 +1040,7 @@ export class AllureReport {
1005
1040
  }
1006
1041
  }
1007
1042
  });
1008
- const { name, readers = [allure1, allure2, cucumberjson, junitXml, attachments], plugins = [], resolutions, reportFiles, realTime, historyPath, historyBaseUrl, historyLimit, appendHistory, defaultLabels = {}, variables = {}, environment, allowedEnvironments, environments, output, hideLabels, qualityGate, performance, dump, categories, allureService, globalAttachments, cwd, } = opts;
1043
+ const { name, readers = [allure1, allure2, cucumberjson, cucumberMessages, junitXml, attachments], plugins = [], resolutions, reportFiles, realTime, historyPath, historyBaseUrl, historyLimit, flakyDetection, appendHistory, defaultLabels = {}, variables = {}, environment, allowedEnvironments, environments, output, hideLabels, qualityGate, performance, dump, categories, allureService, globalAttachments, cwd, } = opts;
1009
1044
  const allureServiceAccessToken = allureService?.accessToken;
1010
1045
  if (allureServiceAccessToken) {
1011
1046
  const allureServiceClientConfig = {
@@ -1024,7 +1059,11 @@ export class AllureReport {
1024
1059
  __classPrivateFieldSet(this, _AllureReport_ci, detect(), "f");
1025
1060
  const reportTitleSuffix = __classPrivateFieldGet(this, _AllureReport_ci, "f")?.pullRequestName ?? __classPrivateFieldGet(this, _AllureReport_ci, "f")?.jobRunName;
1026
1061
  this.reportName = [name, reportTitleSuffix].filter(Boolean).join(" – ");
1027
- __classPrivateFieldSet(this, _AllureReport_realtimeChannel, new RealtimeChannel(), "f");
1062
+ __classPrivateFieldSet(this, _AllureReport_realtimeChannel, new RealtimeChannel(() => {
1063
+ if (__classPrivateFieldGet(this, _AllureReport_executionStage, "f") === "running") {
1064
+ __classPrivateFieldGet(this, _AllureReport_store, "f").updateHistoryFlags();
1065
+ }
1066
+ }), "f");
1028
1067
  __classPrivateFieldSet(this, _AllureReport_realtimeUpdateScheduler, new RealtimeUpdateScheduler(__classPrivateFieldGet(this, _AllureReport_runRealtimeUpdate, "f")), "f");
1029
1068
  __classPrivateFieldSet(this, _AllureReport_realTime, realTime, "f");
1030
1069
  __classPrivateFieldSet(this, _AllureReport_dump, dump, "f");
@@ -1057,6 +1096,7 @@ export class AllureReport {
1057
1096
  reportVariables: variables,
1058
1097
  environmentsConfig: environments,
1059
1098
  history: __classPrivateFieldGet(this, _AllureReport_history, "f"),
1099
+ flakyDetection,
1060
1100
  resolutionsConfig: resolutions,
1061
1101
  defaultLabels,
1062
1102
  environment,
@@ -1,6 +1,5 @@
1
1
  import type { AttachmentLink, TestCase, TestFixtureResult, TestResult } from "@allurereport/core-api";
2
2
  import type { RawFixtureResult, RawTestResult, ReaderContext } from "@allurereport/reader-api";
3
- export declare const __unknown = "#___unknown_value___#";
4
3
  export type StateData = {
5
4
  testCases: Map<string, TestCase>;
6
5
  attachments: Map<string, AttachmentLink>;