allure 3.8.2 → 3.9.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.
@@ -2,7 +2,7 @@ import { Command } from "clipanion";
2
2
  export declare class Allure2Command extends Command {
3
3
  static paths: string[][];
4
4
  static usage: import("clipanion").Usage;
5
- resultsDir: string;
5
+ resultsDir: string[];
6
6
  config: string | undefined;
7
7
  cwd: string | undefined;
8
8
  output: string | undefined;
@@ -1,15 +1,17 @@
1
1
  import * as console from "node:console";
2
- import { existsSync } from "node:fs";
3
2
  import { realpath } from "node:fs/promises";
4
3
  import process, { exit } from "node:process";
5
4
  import { AllureReport, readConfig } from "@allurereport/core";
6
5
  import Allure2Plugin from "@allurereport/plugin-allure2";
7
6
  import { Command, Option } from "clipanion";
8
7
  import { red } from "yoctocolors";
8
+ import { findAllureResultDirectories } from "../utils/fileSystem.js";
9
9
  export class Allure2Command extends Command {
10
10
  constructor() {
11
11
  super(...arguments);
12
- this.resultsDir = Option.String({ required: true, name: "The directory with Allure results" });
12
+ this.resultsDir = Option.Rest({
13
+ name: "Patterns to match test results directories in the current working directory (default: ./**/allure-results)",
14
+ });
13
15
  this.config = Option.String("--config,-c", {
14
16
  description: "The path Allure config file",
15
17
  });
@@ -36,12 +38,13 @@ export class Allure2Command extends Command {
36
38
  });
37
39
  }
38
40
  async execute() {
39
- if (!existsSync(this.resultsDir)) {
40
- console.error(red(`The given test results directory doesn't exist: ${this.resultsDir}`));
41
+ const cwd = await realpath(this.cwd ?? process.cwd());
42
+ const { resultDirectories, patterns } = await findAllureResultDirectories(cwd, this.resultsDir);
43
+ if (!resultDirectories.length) {
44
+ console.error(red(`No test results directories found matching pattern: ${patterns}`));
41
45
  exit(1);
42
46
  return;
43
47
  }
44
- const cwd = await realpath(this.cwd ?? process.cwd());
45
48
  const before = new Date().getTime();
46
49
  const defaultAllure2Options = {
47
50
  singleFile: this.singleFile ?? false,
@@ -63,7 +66,9 @@ export class Allure2Command extends Command {
63
66
  ];
64
67
  const allureReport = new AllureReport(config);
65
68
  await allureReport.start();
66
- await allureReport.readDirectory(this.resultsDir);
69
+ for (const directory of resultDirectories) {
70
+ await allureReport.readDirectory(directory);
71
+ }
67
72
  await allureReport.done();
68
73
  const after = new Date().getTime();
69
74
  console.log(`the report successfully generated (${after - before}ms)`);
@@ -80,5 +85,13 @@ Allure2Command.usage = Command.Usage({
80
85
  "allure2 ./allure-results --output custom-report",
81
86
  "Generate a report from the ./allure-results directory to the custom-report directory",
82
87
  ],
88
+ [
89
+ "allure2 ./packages/*/allure-results",
90
+ "Generate a report from all Allure result directories matching the pattern",
91
+ ],
92
+ [
93
+ "allure2 ./packages/foo/allure-results ./packages/bar/allure-results",
94
+ "Generate a report from two Allure result directories",
95
+ ],
83
96
  ],
84
97
  });
@@ -2,7 +2,7 @@ import { Command } from "clipanion";
2
2
  export declare class AwesomeCommand extends Command {
3
3
  static paths: string[][];
4
4
  static usage: import("clipanion").Usage;
5
- resultsDir: string;
5
+ resultsDir: string[];
6
6
  config: string | undefined;
7
7
  cwd: string | undefined;
8
8
  output: string | undefined;
@@ -1,15 +1,17 @@
1
1
  import * as console from "node:console";
2
- import { existsSync } from "node:fs";
3
2
  import { realpath } from "node:fs/promises";
4
3
  import process, { exit } from "node:process";
5
4
  import { AllureReport, readConfig } from "@allurereport/core";
6
5
  import { default as AwesomePlugin } from "@allurereport/plugin-awesome";
7
6
  import { Command, Option } from "clipanion";
8
7
  import { red } from "yoctocolors";
8
+ import { findAllureResultDirectories } from "../utils/fileSystem.js";
9
9
  export class AwesomeCommand extends Command {
10
10
  constructor() {
11
11
  super(...arguments);
12
- this.resultsDir = Option.String({ required: true, name: "The directory with Allure results" });
12
+ this.resultsDir = Option.Rest({
13
+ name: "Patterns to match test results directories in the current working directory (default: ./**/allure-results)",
14
+ });
13
15
  this.config = Option.String("--config,-c", {
14
16
  description: "The path Allure config file",
15
17
  });
@@ -48,12 +50,13 @@ export class AwesomeCommand extends Command {
48
50
  });
49
51
  }
50
52
  async execute() {
51
- if (!existsSync(this.resultsDir)) {
52
- console.error(red(`The given test results directory doesn't exist: ${this.resultsDir}`));
53
+ const cwd = await realpath(this.cwd ?? process.cwd());
54
+ const { resultDirectories, patterns } = await findAllureResultDirectories(cwd, this.resultsDir);
55
+ if (!resultDirectories.length) {
56
+ console.error(red(`No test results directories found matching pattern: ${patterns}`));
53
57
  exit(1);
54
58
  return;
55
59
  }
56
- const cwd = await realpath(this.cwd ?? process.cwd());
57
60
  const before = new Date().getTime();
58
61
  const hideLabels = this.hideLabels?.length ? this.hideLabels : undefined;
59
62
  const config = await readConfig(cwd, this.config, {
@@ -80,7 +83,9 @@ export class AwesomeCommand extends Command {
80
83
  ];
81
84
  const allureReport = new AllureReport(config);
82
85
  await allureReport.start();
83
- await allureReport.readDirectory(this.resultsDir);
86
+ for (const directory of resultDirectories) {
87
+ await allureReport.readDirectory(directory);
88
+ }
84
89
  await allureReport.done();
85
90
  const after = new Date().getTime();
86
91
  console.log(`the report successfully generated (${after - before}ms)`);
@@ -97,5 +102,13 @@ AwesomeCommand.usage = Command.Usage({
97
102
  "awesome ./allure-results --output custom-report",
98
103
  "Generate a report from the ./allure-results directory to the custom-report directory",
99
104
  ],
105
+ [
106
+ "awesome ./packages/*/allure-results",
107
+ "Generate a report from all Allure result directories matching the pattern",
108
+ ],
109
+ [
110
+ "awesome ./packages/foo/allure-results ./packages/bar/allure-results",
111
+ "Generate a report from two Allure result directories",
112
+ ],
100
113
  ],
101
114
  });
@@ -2,7 +2,7 @@ import { Command } from "clipanion";
2
2
  export declare class ClassicCommand extends Command {
3
3
  static paths: string[][];
4
4
  static usage: import("clipanion").Usage;
5
- resultsDir: string;
5
+ resultsDir: string[];
6
6
  config: string | undefined;
7
7
  cwd: string | undefined;
8
8
  output: string | undefined;
@@ -1,15 +1,17 @@
1
1
  import * as console from "node:console";
2
- import { existsSync } from "node:fs";
3
2
  import { realpath } from "node:fs/promises";
4
3
  import process, { exit } from "node:process";
5
4
  import { AllureReport, readConfig } from "@allurereport/core";
6
5
  import ClassicPlugin from "@allurereport/plugin-classic";
7
6
  import { Command, Option } from "clipanion";
8
7
  import { red } from "yoctocolors";
8
+ import { findAllureResultDirectories } from "../utils/fileSystem.js";
9
9
  export class ClassicCommand extends Command {
10
10
  constructor() {
11
11
  super(...arguments);
12
- this.resultsDir = Option.String({ required: true, name: "The directory with Allure results" });
12
+ this.resultsDir = Option.Rest({
13
+ name: "Patterns to match test results directories in the current working directory (default: ./**/allure-results)",
14
+ });
13
15
  this.config = Option.String("--config,-c", {
14
16
  description: "The path Allure config file",
15
17
  });
@@ -36,12 +38,13 @@ export class ClassicCommand extends Command {
36
38
  });
37
39
  }
38
40
  async execute() {
39
- if (!existsSync(this.resultsDir)) {
40
- console.error(red(`The given test results directory doesn't exist: ${this.resultsDir}`));
41
+ const cwd = await realpath(this.cwd ?? process.cwd());
42
+ const { resultDirectories, patterns } = await findAllureResultDirectories(cwd, this.resultsDir);
43
+ if (!resultDirectories.length) {
44
+ console.error(red(`No test results directories found matching pattern: ${patterns}`));
41
45
  exit(1);
42
46
  return;
43
47
  }
44
- const cwd = await realpath(this.cwd ?? process.cwd());
45
48
  const before = new Date().getTime();
46
49
  const defaultClassicOptions = {
47
50
  singleFile: this.singleFile ?? false,
@@ -63,7 +66,9 @@ export class ClassicCommand extends Command {
63
66
  ];
64
67
  const allureReport = new AllureReport(config);
65
68
  await allureReport.start();
66
- await allureReport.readDirectory(this.resultsDir);
69
+ for (const directory of resultDirectories) {
70
+ await allureReport.readDirectory(directory);
71
+ }
67
72
  await allureReport.done();
68
73
  const after = new Date().getTime();
69
74
  console.log(`the report successfully generated (${after - before}ms)`);
@@ -80,5 +85,13 @@ ClassicCommand.usage = Command.Usage({
80
85
  "classic ./allure-results --output custom-report",
81
86
  "Generate a report from the ./allure-results directory to the custom-report directory",
82
87
  ],
88
+ [
89
+ "classic ./packages/*/allure-results",
90
+ "Generate a report from all Allure result directories matching the pattern",
91
+ ],
92
+ [
93
+ "classic ./packages/foo/allure-results ./packages/bar/allure-results",
94
+ "Generate a report from two Allure result directories",
95
+ ],
83
96
  ],
84
97
  });
@@ -2,6 +2,6 @@ import type { FullConfig } from "@allurereport/core";
2
2
  export declare const generate: (params: {
3
3
  cwd: string;
4
4
  config: FullConfig;
5
- resultsDir: string;
5
+ resultsDir: string[];
6
6
  dump?: string[];
7
7
  }) => Promise<void>;
@@ -1,37 +1,16 @@
1
1
  import { exit } from "node:process";
2
2
  import { AllureReport } from "@allurereport/core";
3
3
  import { KnownError } from "@allurereport/service";
4
- import { glob } from "glob";
5
4
  import { red } from "yoctocolors";
5
+ import { findAllureResultDirectories, findFilesByGlobs } from "../../utils/fileSystem.js";
6
6
  import { logError } from "../../utils/logs.js";
7
7
  export const generate = async (params) => {
8
- const dumpFiles = [];
9
- const resultsDirectories = [];
10
- if (params?.dump?.length) {
11
- for (const dump of params.dump) {
12
- const matchedFiles = await glob(dump, {
13
- nodir: true,
14
- dot: true,
15
- absolute: true,
16
- windowsPathsNoEscape: true,
17
- cwd: params.cwd,
18
- });
19
- dumpFiles.push(...matchedFiles);
20
- }
21
- }
22
- if (!!params?.resultsDir || dumpFiles.length === 0) {
23
- const matchedDirs = (await glob(params.resultsDir, {
24
- mark: true,
25
- nodir: false,
26
- absolute: true,
27
- dot: true,
28
- windowsPathsNoEscape: true,
29
- cwd: params.cwd,
30
- })).filter((p) => /(\/|\\)$/.test(p));
31
- resultsDirectories.push(...matchedDirs);
32
- }
33
- if (resultsDirectories.length === 0 && dumpFiles.length === 0) {
34
- console.error(red(`No test results directories found matching pattern: ${params.resultsDir}`));
8
+ const dumpFiles = params?.dump?.length ? await findFilesByGlobs(params.cwd, params.dump) : [];
9
+ const { resultDirectories = [], patterns = params.resultsDir } = !!params?.resultsDir || dumpFiles.length === 0
10
+ ? await findAllureResultDirectories(params.cwd, params.resultsDir)
11
+ : {};
12
+ if (resultDirectories.length === 0 && dumpFiles.length === 0) {
13
+ console.error(red(`No test results directories found matching pattern: ${patterns}`));
35
14
  exit(1);
36
15
  return;
37
16
  }
@@ -39,7 +18,7 @@ export const generate = async (params) => {
39
18
  const allureReport = new AllureReport(params.config);
40
19
  await allureReport.restoreState(Array.from(dumpFiles));
41
20
  await allureReport.start();
42
- for (const dir of resultsDirectories) {
21
+ for (const dir of resultDirectories) {
43
22
  await allureReport.readDirectory(dir);
44
23
  }
45
24
  await allureReport.done();
@@ -194,7 +194,7 @@ export const executeAllureRun = async (params) => {
194
194
  await rm(tmpDir, { recursive: true });
195
195
  logTests(await allureReport.store.allTestResults());
196
196
  }
197
- const trs = await allureReport.store.allTestResults({ includeHidden: false });
197
+ const trs = await allureReport.store.allTestResults({ includeRetries: false });
198
198
  qualityGateResults = testProcessResult?.qualityGateResults ?? [];
199
199
  if (withQualityGate && !qualityGateResults.length) {
200
200
  const { results } = await allureReport.validate({
@@ -2,7 +2,7 @@ import { Command } from "clipanion";
2
2
  export declare class CsvCommand extends Command {
3
3
  static paths: string[][];
4
4
  static usage: import("clipanion").Usage;
5
- resultsDir: string;
5
+ resultsDir: string[];
6
6
  config: string | undefined;
7
7
  cwd: string | undefined;
8
8
  output: string | undefined;
@@ -1,5 +1,4 @@
1
1
  import * as console from "node:console";
2
- import { existsSync } from "node:fs";
3
2
  import { realpath } from "node:fs/promises";
4
3
  import { isAbsolute, join } from "node:path";
5
4
  import process, { exit } from "node:process";
@@ -7,10 +6,13 @@ import { AllureReport, readConfig } from "@allurereport/core";
7
6
  import CsvPlugin from "@allurereport/plugin-csv";
8
7
  import { Command, Option } from "clipanion";
9
8
  import { red } from "yoctocolors";
9
+ import { findAllureResultDirectories } from "../utils/fileSystem.js";
10
10
  export class CsvCommand extends Command {
11
11
  constructor() {
12
12
  super(...arguments);
13
- this.resultsDir = Option.String({ required: true, name: "The directory with Allure results" });
13
+ this.resultsDir = Option.Rest({
14
+ name: "Patterns to match test results directories in the current working directory (default: ./**/allure-results)",
15
+ });
14
16
  this.config = Option.String("--config,-c", {
15
17
  description: "The path Allure config file",
16
18
  });
@@ -31,12 +33,13 @@ export class CsvCommand extends Command {
31
33
  });
32
34
  }
33
35
  async execute() {
34
- if (!existsSync(this.resultsDir)) {
35
- console.error(red(`The given test results directory doesn't exist: ${this.resultsDir}`));
36
+ const cwd = await realpath(this.cwd ?? process.cwd());
37
+ const { resultDirectories, patterns } = await findAllureResultDirectories(cwd, this.resultsDir);
38
+ if (!resultDirectories.length) {
39
+ console.error(red(`No test results directories found matching pattern: ${patterns}`));
36
40
  exit(1);
37
41
  return;
38
42
  }
39
- const cwd = await realpath(this.cwd ?? process.cwd());
40
43
  const before = new Date().getTime();
41
44
  const defaultCsvOptions = {
42
45
  separator: this.separator ?? ",",
@@ -56,7 +59,9 @@ export class CsvCommand extends Command {
56
59
  ];
57
60
  const allureReport = new AllureReport(config);
58
61
  await allureReport.start();
59
- await allureReport.readDirectory(this.resultsDir);
62
+ for (const directory of resultDirectories) {
63
+ await allureReport.readDirectory(directory);
64
+ }
60
65
  await allureReport.done();
61
66
  const after = new Date().getTime();
62
67
  console.log(`the report successfully generated (${after - before}ms)`);
@@ -73,5 +78,10 @@ CsvCommand.usage = Command.Usage({
73
78
  "csv ./allure-results --output custom-report.csv",
74
79
  "Generate a report from the ./allure-results directory to the custom-report.csv file",
75
80
  ],
81
+ ["csv ./packages/*/allure-results", "Generate a report from all Allure result directories matching the pattern"],
82
+ [
83
+ "csv ./packages/foo/allure-results ./packages/bar/allure-results",
84
+ "Generate a report from two Allure result directories",
85
+ ],
76
86
  ],
77
87
  });
@@ -2,7 +2,7 @@ import { Command } from "clipanion";
2
2
  export declare class DashboardCommand extends Command {
3
3
  static paths: string[][];
4
4
  static usage: import("clipanion").Usage;
5
- resultsDir: string;
5
+ resultsDir: string[];
6
6
  config: string | undefined;
7
7
  cwd: string | undefined;
8
8
  output: string | undefined;
@@ -1,15 +1,17 @@
1
1
  import * as console from "node:console";
2
- import { existsSync } from "node:fs";
3
2
  import { realpath } from "node:fs/promises";
4
3
  import process, { exit } from "node:process";
5
4
  import { AllureReport, readConfig } from "@allurereport/core";
6
5
  import DashboardPlugin from "@allurereport/plugin-dashboard";
7
6
  import { Command, Option } from "clipanion";
8
7
  import { red } from "yoctocolors";
8
+ import { findAllureResultDirectories } from "../utils/fileSystem.js";
9
9
  export class DashboardCommand extends Command {
10
10
  constructor() {
11
11
  super(...arguments);
12
- this.resultsDir = Option.String({ required: true, name: "The directory with Allure results" });
12
+ this.resultsDir = Option.Rest({
13
+ name: "Patterns to match test results directories in the current working directory (default: ./**/allure-results)",
14
+ });
13
15
  this.config = Option.String("--config,-c", {
14
16
  description: "The path Allure config file",
15
17
  });
@@ -36,12 +38,13 @@ export class DashboardCommand extends Command {
36
38
  });
37
39
  }
38
40
  async execute() {
39
- if (!existsSync(this.resultsDir)) {
40
- console.error(red(`The given test results directory doesn't exist: ${this.resultsDir}`));
41
+ const cwd = await realpath(this.cwd ?? process.cwd());
42
+ const { resultDirectories, patterns } = await findAllureResultDirectories(cwd, this.resultsDir);
43
+ if (!resultDirectories.length) {
44
+ console.error(red(`No test results directories found matching pattern: ${patterns}`));
41
45
  exit(1);
42
46
  return;
43
47
  }
44
- const cwd = await realpath(this.cwd ?? process.cwd());
45
48
  const before = new Date().getTime();
46
49
  const defaultDashboardOptions = {
47
50
  singleFile: this.singleFile ?? false,
@@ -63,7 +66,9 @@ export class DashboardCommand extends Command {
63
66
  ];
64
67
  const allureReport = new AllureReport(config);
65
68
  await allureReport.start();
66
- await allureReport.readDirectory(this.resultsDir);
69
+ for (const directory of resultDirectories) {
70
+ await allureReport.readDirectory(directory);
71
+ }
67
72
  await allureReport.done();
68
73
  const after = new Date().getTime();
69
74
  console.log(`the report successfully generated (${after - before}ms)`);
@@ -80,5 +85,13 @@ DashboardCommand.usage = Command.Usage({
80
85
  "dashboard ./allure-results --output custom-report",
81
86
  "Generate a report from the ./allure-results directory to the custom-report directory",
82
87
  ],
88
+ [
89
+ "dashboard ./packages/*/allure-results",
90
+ "Generate a report from all Allure result directories matching the pattern",
91
+ ],
92
+ [
93
+ "dashboard ./packages/foo/allure-results ./packages/bar/allure-results",
94
+ "Generate a report from two Allure result directories",
95
+ ],
83
96
  ],
84
97
  });
@@ -2,7 +2,7 @@ import { Command } from "clipanion";
2
2
  export declare class GenerateCommand extends Command {
3
3
  static paths: string[][];
4
4
  static usage: import("clipanion").Usage;
5
- resultsDir: string | undefined;
5
+ resultsDir: string[];
6
6
  config: string | undefined;
7
7
  output: string | undefined;
8
8
  cwd: string | undefined;
@@ -6,9 +6,8 @@ import { generate } from "./commons/generate.js";
6
6
  export class GenerateCommand extends Command {
7
7
  constructor() {
8
8
  super(...arguments);
9
- this.resultsDir = Option.String({
10
- required: false,
11
- name: "Pattern to match test results directories in the current working directory (default: ./**/allure-results)",
9
+ this.resultsDir = Option.Rest({
10
+ name: "Patterns to match test results directories in the current working directory (default: ./**/allure-results)",
12
11
  });
13
12
  this.config = Option.String("--config,-c", {
14
13
  description: "The path Allure config file",
@@ -23,7 +22,9 @@ export class GenerateCommand extends Command {
23
22
  description: "The report name (default: Allure Report)",
24
23
  });
25
24
  this.dump = Option.Array("--dump", {
26
- description: "Dump archives to restore state from (default: empty string)",
25
+ description: "Path or pattern that matches one or more archives created by `allure run --dump ...`. " +
26
+ "Allure loads the matched archives before generating the report. " +
27
+ "This option can be specified multiple times.",
27
28
  });
28
29
  this.open = Option.Boolean("--open", {
29
30
  description: "Open the report in the default browser after generation (default: false)",
@@ -51,7 +52,7 @@ export class GenerateCommand extends Command {
51
52
  });
52
53
  await generate({
53
54
  dump: this.dump,
54
- resultsDir: this.resultsDir ?? "./**/allure-results",
55
+ resultsDir: this.resultsDir,
55
56
  cwd,
56
57
  config,
57
58
  });
@@ -66,8 +67,8 @@ export class GenerateCommand extends Command {
66
67
  }
67
68
  GenerateCommand.paths = [["generate"]];
68
69
  GenerateCommand.usage = Command.Usage({
69
- description: "Generates the report to specified directory",
70
- details: "This command generates a report from the provided Allure Results directory.",
70
+ description: "Generates the report in the specified directory.",
71
+ details: "This command generates a report from the provided Allure Results directories.",
71
72
  examples: [
72
73
  ["generate ./allure-results", "Generate a report from the ./allure-results directory"],
73
74
  [
@@ -82,5 +83,9 @@ GenerateCommand.usage = Command.Usage({
82
83
  "generate --dump=allure-*.zip",
83
84
  "Generate a report using data from any dump archive that matches the given pattern and results directory if it exists",
84
85
  ],
86
+ [
87
+ "generate ./packages/foo/out/allure-results ./packages/bar/out/allure-results",
88
+ "Generate a report from two Allure results directories",
89
+ ],
85
90
  ],
86
91
  });
@@ -2,7 +2,7 @@ import { Command } from "clipanion";
2
2
  export declare class HistoryCommand extends Command {
3
3
  static paths: string[][];
4
4
  static usage: import("clipanion").Usage;
5
- resultsDir: string;
5
+ resultsDir: string[];
6
6
  historyPath: string | undefined;
7
7
  historyLimit: string | undefined;
8
8
  reportName: string | undefined;
@@ -1,13 +1,15 @@
1
1
  import * as console from "node:console";
2
- import { existsSync } from "node:fs";
3
- import { exit } from "node:process";
2
+ import process, { exit } from "node:process";
4
3
  import { AllureReport, resolveConfig } from "@allurereport/core";
5
4
  import { Command, Option } from "clipanion";
6
5
  import { red } from "yoctocolors";
6
+ import { findAllureResultDirectories } from "../utils/fileSystem.js";
7
7
  export class HistoryCommand extends Command {
8
8
  constructor() {
9
9
  super(...arguments);
10
- this.resultsDir = Option.String({ required: true, name: "The directory with Allure results" });
10
+ this.resultsDir = Option.Rest({
11
+ name: "Patterns to match test results directories in the current working directory (default: ./**/allure-results)",
12
+ });
11
13
  this.historyPath = Option.String("--history-path,-h", {
12
14
  description: "The path to history file",
13
15
  });
@@ -19,9 +21,11 @@ export class HistoryCommand extends Command {
19
21
  });
20
22
  }
21
23
  async execute() {
22
- if (!existsSync(this.resultsDir)) {
23
- console.error(red(`The given test results directory doesn't exist: ${this.resultsDir}`));
24
+ const { resultDirectories, patterns } = await findAllureResultDirectories(process.cwd(), this.resultsDir);
25
+ if (!resultDirectories.length) {
26
+ console.error(red(`No test results directories found matching pattern: ${patterns}`));
24
27
  exit(1);
28
+ return;
25
29
  }
26
30
  const config = await resolveConfig({
27
31
  historyPath: this.historyPath ?? "history.jsonl",
@@ -31,7 +35,9 @@ export class HistoryCommand extends Command {
31
35
  });
32
36
  const allureReport = new AllureReport(config);
33
37
  await allureReport.start();
34
- await allureReport.readDirectory(this.resultsDir);
38
+ for (const directory of resultDirectories) {
39
+ await allureReport.readDirectory(directory);
40
+ }
35
41
  await allureReport.done();
36
42
  }
37
43
  }
@@ -45,5 +51,13 @@ HistoryCommand.usage = Command.Usage({
45
51
  "history ./allure-results --history-path custom-history.jsonl",
46
52
  "Generate history from the ./allure-results directory to the custom-history.jsonl file",
47
53
  ],
54
+ [
55
+ "history ./packages/*/allure-results",
56
+ "Generate history from all Allure result directories matching the pattern",
57
+ ],
58
+ [
59
+ "history ./packages/foo/allure-results ./packages/bar/allure-results",
60
+ "Generate history from two Allure result directories",
61
+ ],
48
62
  ],
49
63
  });
@@ -2,7 +2,7 @@ import { Command } from "clipanion";
2
2
  export declare class KnownIssueCommand extends Command {
3
3
  static paths: string[][];
4
4
  static usage: import("clipanion").Usage;
5
- resultsDir: string;
5
+ resultsDir: string[];
6
6
  output: string | undefined;
7
7
  execute(): Promise<void>;
8
8
  }
@@ -1,21 +1,24 @@
1
1
  import * as console from "node:console";
2
- import { existsSync } from "node:fs";
3
2
  import { resolve } from "node:path";
4
- import { exit } from "node:process";
3
+ import process, { exit } from "node:process";
5
4
  import { AllureReport, resolveConfig, writeKnownIssues } from "@allurereport/core";
6
5
  import { Command, Option } from "clipanion";
7
6
  import { red } from "yoctocolors";
7
+ import { findAllureResultDirectories } from "../utils/fileSystem.js";
8
8
  export class KnownIssueCommand extends Command {
9
9
  constructor() {
10
10
  super(...arguments);
11
- this.resultsDir = Option.String({ required: true, name: "The directory with Allure results" });
11
+ this.resultsDir = Option.Rest({
12
+ name: "Patterns to match test results directories in the current working directory (default: ./**/allure-results)",
13
+ });
12
14
  this.output = Option.String("--output,-o", {
13
15
  description: "The output file name. Absolute paths are accepted as well",
14
16
  });
15
17
  }
16
18
  async execute() {
17
- if (!existsSync(this.resultsDir)) {
18
- console.error(red(`The given test results directory doesn't exist: ${this.resultsDir}`));
19
+ const { resultDirectories, patterns } = await findAllureResultDirectories(process.cwd(), this.resultsDir);
20
+ if (!resultDirectories.length) {
21
+ console.error(red(`No test results directories found matching pattern: ${patterns}`));
19
22
  exit(1);
20
23
  return;
21
24
  }
@@ -25,7 +28,9 @@ export class KnownIssueCommand extends Command {
25
28
  });
26
29
  const allureReport = new AllureReport(config);
27
30
  await allureReport.start();
28
- await allureReport.readDirectory(this.resultsDir);
31
+ for (const directory of resultDirectories) {
32
+ await allureReport.readDirectory(directory);
33
+ }
29
34
  await allureReport.done();
30
35
  const targetPath = resolve(outputPath);
31
36
  await writeKnownIssues(allureReport.store, outputPath);
@@ -42,5 +47,13 @@ KnownIssueCommand.usage = Command.Usage({
42
47
  "known-issue ./allure-results --output custom-issues.json",
43
48
  "Generate a known issue list from the ./allure-results directory to the custom-issues.json file",
44
49
  ],
50
+ [
51
+ "known-issue ./packages/*/allure-results",
52
+ "Generate a known issue list from all Allure result directories matching the pattern",
53
+ ],
54
+ [
55
+ "known-issue ./packages/foo/allure-results ./packages/bar/allure-results",
56
+ "Generate a known issue list from two Allure result directories",
57
+ ],
45
58
  ],
46
59
  });
@@ -2,7 +2,7 @@ import { Command } from "clipanion";
2
2
  export declare class LogCommand extends Command {
3
3
  static paths: string[][];
4
4
  static usage: import("clipanion").Usage;
5
- resultsDir: string;
5
+ resultsDir: string[];
6
6
  config: string | undefined;
7
7
  cwd: string | undefined;
8
8
  groupBy: string | undefined;