allure 3.15.0 → 3.16.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/README.md +16 -7
- package/dist/commands/agent-run.d.ts +1 -0
- package/dist/commands/agent-run.js +11 -8
- package/dist/commands/agent.d.ts +1 -0
- package/dist/commands/agent.js +19 -8
- package/dist/commands/allure2.js +10 -10
- package/dist/commands/awesome.js +10 -10
- package/dist/commands/check.js +1 -1
- package/dist/commands/classic.js +10 -10
- package/dist/commands/commons/generate.d.ts +1 -1
- package/dist/commands/commons/generate.js +7 -3
- package/dist/commands/commons/resultsDiscovery.d.ts +5 -0
- package/dist/commands/commons/resultsDiscovery.js +17 -0
- package/dist/commands/commons/run.d.ts +2 -3
- package/dist/commands/commons/run.js +37 -26
- package/dist/commands/csv.js +10 -10
- package/dist/commands/dashboard.js +9 -9
- package/dist/commands/generate.js +5 -4
- package/dist/commands/history.js +6 -4
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.js +1 -0
- package/dist/commands/jira/clear.js +1 -1
- package/dist/commands/log.js +9 -9
- package/dist/commands/open.js +9 -5
- package/dist/commands/qualityGate.js +5 -8
- package/dist/commands/results/pack.d.ts +1 -0
- package/dist/commands/results/pack.js +12 -14
- package/dist/commands/run.d.ts +1 -0
- package/dist/commands/run.js +20 -10
- package/dist/commands/slack.js +9 -9
- package/dist/commands/testopsPlan.d.ts +7 -0
- package/dist/commands/testopsPlan.js +65 -0
- package/dist/commands/testplan.js +7 -5
- package/dist/commands/watch.d.ts +1 -0
- package/dist/commands/watch.js +71 -25
- package/dist/index.js +2 -1
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/process.js +1 -0
- package/dist/utils/resultsPatterns.d.ts +12 -0
- package/dist/utils/resultsPatterns.js +37 -0
- package/dist/utils/signals.d.ts +18 -0
- package/dist/utils/signals.js +52 -0
- package/package.json +21 -21
package/README.md
CHANGED
|
@@ -56,7 +56,15 @@ To hide specific labels use `--hide-labels` option:
|
|
|
56
56
|
npx allure run --hide-labels=owner --hide-labels=tag -- npm test
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
To successfully generate a report, ensure that your test setup outputs results into an `allure-results` directory
|
|
59
|
+
To successfully generate a report, ensure that your test setup outputs results into an `allure-results` directory. With `allure run` / `allure agent` / empty `allure watch`, directories named `allure-results` are discovered dynamically (name-based watcher). With one-shot commands such as `allure generate`, an empty CLI and unset `config.resultsDir` default to the `./**/allure-results` glob. Quote globs in the shell so they are not expanded early.
|
|
60
|
+
|
|
61
|
+
You can also set `resultsDir` in the Allure config (`string | string[]`) or pass `--results-dir` on `run` / `agent`:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx allure run --open --results-dir './artifacts/**/allure-results' -- npm test
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Repeat `--results-dir` for multiple patterns. CLI overrides `config.resultsDir`.
|
|
60
68
|
|
|
61
69
|
After the tests complete, the report is generated automatically. Existing results from previous runs are ignored, as Allure 3 focuses solely on new data to ensure accurate and up-to-date reporting.
|
|
62
70
|
|
|
@@ -191,7 +199,7 @@ export default defineConfig({
|
|
|
191
199
|
});
|
|
192
200
|
```
|
|
193
201
|
|
|
194
|
-
In this example, the generated report is named
|
|
202
|
+
In this example, the generated report is named _Allure Report Example_ and saved to the `./out/allure-report` directory. The **Awesome** plugin is enabled with options to produce a single-file HTML report in English.
|
|
195
203
|
|
|
196
204
|
### TypeScript Configuration File
|
|
197
205
|
|
|
@@ -214,17 +222,18 @@ The configuration file allows you to fine-tune report generation. Key options in
|
|
|
214
222
|
|
|
215
223
|
- **`name`**: Specifies the report’s display name.
|
|
216
224
|
- **`output`**: Defines the directory where the report will be saved.
|
|
217
|
-
- **`
|
|
225
|
+
- **`resultsDir`** _(`string | string[]`)_: Glob patterns or paths used when reading Allure results directories. For one-shot commands, CLI positionals override this value. For `allure run` / `allure agent`, use repeated `--results-dir` (same override priority). When both CLI and `resultsDir` are empty, one-shot commands (`generate`, etc.) use `./**/allure-results`, while live commands (`run`, `agent`, empty `watch`) use name-based discovery of directories named `allure-results`. Quote globs in the shell.
|
|
226
|
+
- **`hideLabels`** _(`(string | RegExp)[]`)_: Hides matching labels by name in report data. Currently, only Allure Awesome report respects the option. Labels with names starting with `_` are hidden by default.
|
|
218
227
|
- **`plugins`**: Enables and configures plugins, with each supporting various options.
|
|
219
228
|
|
|
220
229
|
### Awesome Plugin Options
|
|
221
230
|
|
|
222
231
|
The **Awesome** plugin offers several customizable options:
|
|
223
232
|
|
|
224
|
-
- **`singleFile`**
|
|
225
|
-
- **`reportName`**
|
|
226
|
-
- **`open`**
|
|
227
|
-
- **`reportLanguage`**
|
|
233
|
+
- **`singleFile`** _(boolean)_: If set to `true`, generates the report as a single standalone HTML file.
|
|
234
|
+
- **`reportName`** _(string)_: Overrides the default report name.
|
|
235
|
+
- **`open`** _(boolean)_: Automatically opens the report after generation if enabled.
|
|
236
|
+
- **`reportLanguage`** _(string)_: Sets the UI language of the report. Supported languages include:
|
|
228
237
|
|
|
229
238
|
`az`, `br`, `de`, `en`, `es`, `fr`, `he`, `ja`, `kr`, `nl`, `pl`, `ru`, `sv`, `tr`, `zh`.
|
|
230
239
|
|
|
@@ -32,6 +32,7 @@ export type ExecuteAgentModeParams = {
|
|
|
32
32
|
rerunLabels?: string[];
|
|
33
33
|
reportMode: AgentHumanReportMode;
|
|
34
34
|
args: string[];
|
|
35
|
+
resultsPatterns?: readonly string[];
|
|
35
36
|
};
|
|
36
37
|
export declare const executeAgentMode: (params: ExecuteAgentModeParams) => Promise<void>;
|
|
37
38
|
export type ExecuteAgentInspectModeParams = {
|
|
@@ -8,7 +8,8 @@ import { AllureReport, isFileNotFoundError, readConfig } from "@allurereport/cor
|
|
|
8
8
|
import { createAgentTestPlanContext, AgentUsageError, assertExplicitAgentOutputDirIsSafe, formatAgentOutputLinks, formatAgentRunSummary, isPathInside, loadAgentOutput, normalizeAgentRerunPreset, parseAgentLabelFilters, cleanupAgentRunState, cleanupStaleAgentRunStates, resolveAgentStateDir, writeAgentRunState, } from "@allurereport/plugin-agent";
|
|
9
9
|
import { normalizeCommandEnvironmentOptions, resolveCommandEnvironment } from "../utils/environment.js";
|
|
10
10
|
import { createChildAllureCliEnvironment, getActiveAllureCliCommand } from "../utils/execution-context.js";
|
|
11
|
-
import {
|
|
11
|
+
import { findFilesByGlobs } from "../utils/fileSystem.js";
|
|
12
|
+
import { resolveAndFindResultsDirs, resolveResultsPatterns } from "../utils/resultsPatterns.js";
|
|
12
13
|
import { createAgentHumanReportConfig } from "./agent-human-report.js";
|
|
13
14
|
import { executeAllureRun, executeNestedAllureCommand } from "./commons/run.js";
|
|
14
15
|
export const formatAgentCommand = (args) => args.join(" ");
|
|
@@ -90,7 +91,7 @@ export const cleanupManagedAgentOutputs = async (params) => {
|
|
|
90
91
|
}
|
|
91
92
|
};
|
|
92
93
|
export const executeAgentMode = async (params) => {
|
|
93
|
-
const { configPath, cwd: configuredCwd, output, expectations, inlineExpectations, environment, environmentName, silent, rerunFrom, rerunLatest, rerunPreset, rerunEnvironments, rerunLabels, reportMode, args, } = params;
|
|
94
|
+
const { configPath, cwd: configuredCwd, output, expectations, inlineExpectations, environment, environmentName, silent, rerunFrom, rerunLatest, rerunPreset, rerunEnvironments, rerunLabels, reportMode, args, resultsPatterns: cliResultsPatterns = [], } = params;
|
|
94
95
|
const command = args[0];
|
|
95
96
|
const commandArgs = args.slice(1);
|
|
96
97
|
const cwd = await realpath(configuredCwd ?? process.cwd());
|
|
@@ -196,10 +197,9 @@ export const executeAgentMode = async (params) => {
|
|
|
196
197
|
realTime: false,
|
|
197
198
|
plugins: [...humanReport.plugins, ...(config.plugins ?? [])],
|
|
198
199
|
});
|
|
199
|
-
const
|
|
200
|
+
const resultsPatterns = resolveResultsPatterns(cliResultsPatterns, config.resultsDir);
|
|
200
201
|
const { globalExitCode } = await executeAllureRun({
|
|
201
202
|
allureReport,
|
|
202
|
-
knownIssues,
|
|
203
203
|
cwd,
|
|
204
204
|
command,
|
|
205
205
|
commandArgs,
|
|
@@ -210,6 +210,7 @@ export const executeAgentMode = async (params) => {
|
|
|
210
210
|
silent: true,
|
|
211
211
|
ignoreLogs: false,
|
|
212
212
|
logProcessExit: false,
|
|
213
|
+
resultsPatterns,
|
|
213
214
|
});
|
|
214
215
|
await persistAgentRunState({
|
|
215
216
|
runId,
|
|
@@ -240,13 +241,15 @@ export const executeAgentInspectMode = async (params) => {
|
|
|
240
241
|
const { configPath, cwd: configuredCwd, output, expectations, inlineExpectations, environment, environmentName, reportName, open, port, historyLimit, hideLabels, dumps = [], reportMode, resultsDir, } = params;
|
|
241
242
|
const cwd = await realpath(configuredCwd ?? process.cwd());
|
|
242
243
|
const dumpFiles = dumps.length ? await findFilesByGlobs(cwd, dumps) : [];
|
|
243
|
-
const shouldReadResults = resultsDir.length > 0 || dumps.length === 0;
|
|
244
|
-
const { resultDirectories = [], patterns = resultsDir } = shouldReadResults
|
|
245
|
-
? await findAllureResultDirectories(cwd, resultsDir)
|
|
246
|
-
: {};
|
|
247
244
|
if (dumps.length > 0 && dumpFiles.length === 0) {
|
|
248
245
|
throw new AgentUsageError(`No dump files found matching pattern: ${dumps.join(", ")}`);
|
|
249
246
|
}
|
|
247
|
+
const resultsConfig = await readConfig(cwd, configPath);
|
|
248
|
+
const resolvedPatterns = resolveResultsPatterns(resultsDir, resultsConfig.resultsDir);
|
|
249
|
+
const shouldReadResults = resolvedPatterns.length > 0 || dumpFiles.length === 0;
|
|
250
|
+
const { resultDirectories = [], patterns = resolvedPatterns } = shouldReadResults
|
|
251
|
+
? await resolveAndFindResultsDirs(cwd, resultsDir, resultsConfig.resultsDir)
|
|
252
|
+
: {};
|
|
250
253
|
if (resultDirectories.length === 0 && dumpFiles.length === 0) {
|
|
251
254
|
const inspectedPatterns = [...(patterns ?? []), ...dumps];
|
|
252
255
|
throw new AgentUsageError(`No test results directories or dump files found matching pattern: ${inspectedPatterns}`);
|
package/dist/commands/agent.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ export declare class AgentCommand extends Command {
|
|
|
35
35
|
rerunPreset: string | undefined;
|
|
36
36
|
rerunEnvironments: string[] | undefined;
|
|
37
37
|
rerunLabels: string[] | undefined;
|
|
38
|
+
resultsDir: string[] | undefined;
|
|
38
39
|
commandToRun: string[];
|
|
39
40
|
execute(): Promise<void>;
|
|
40
41
|
}
|
package/dist/commands/agent.js
CHANGED
|
@@ -6,6 +6,7 @@ import { dirname, join, resolve } from "node:path";
|
|
|
6
6
|
import process, { exit } from "node:process";
|
|
7
7
|
import { AGENT_FINDING_CATEGORIES, AGENT_FINDING_SEVERITIES, AGENT_TASK_MAP_HELP, AGENT_TEST_STATUSES, AgentExpectationUsageError, assertExplicitAgentOutputDirIsSafe, buildAgentInlineExpectations, buildAgentQueryPayload, cleanupAgentRunState, cleanupStaleAgentRunStates, createAgentCapabilities, formatAgentOutputLinks, isAgentExpectationUsageError, isAgentTaskMapHelpRequest, isAgentUsageError, loadAgentOutput, normalizeAgentQueryLimit, normalizeAgentQueryView, normalizeAgentRerunPreset, normalizeRepeatedEnumValues, normalizeRepeatedStringValues, parseAgentLabelFilters, readLatestAgentState, resolveAgentSelectionOutputDir, resolveAgentStateDir, selectAgentTestPlan, validateAgentExpectationsFile, writeAgentRunState, writeInvalidAgentExpectationOutput, } from "@allurereport/plugin-agent";
|
|
8
8
|
import { Command, Option, UsageError } from "clipanion";
|
|
9
|
+
import { parseRunCommand } from "../utils/resultsPatterns.js";
|
|
9
10
|
export { AGENT_TASK_MAP_HELP, createAgentCapabilities, isAgentTaskMapHelpRequest };
|
|
10
11
|
const readOptionalString = (value) => (typeof value === "string" ? value : undefined);
|
|
11
12
|
const readOptionalBoolean = (value) => value === true;
|
|
@@ -125,7 +126,7 @@ export class AgentCommand extends Command {
|
|
|
125
126
|
constructor() {
|
|
126
127
|
super(...arguments);
|
|
127
128
|
this.config = Option.String("--config,-c", {
|
|
128
|
-
description: "The path Allure config file",
|
|
129
|
+
description: "The path to Allure config file",
|
|
129
130
|
});
|
|
130
131
|
this.cwd = Option.String("--cwd", {
|
|
131
132
|
description: "The working directory for the command to run (default: current working directory)",
|
|
@@ -195,18 +196,22 @@ export class AgentCommand extends Command {
|
|
|
195
196
|
this.rerunLabels = Option.Array("--rerun-label", {
|
|
196
197
|
description: "Filter rerun selection by exact label name=value. Repeat the option for multiple filters",
|
|
197
198
|
});
|
|
199
|
+
this.resultsDir = Option.Array("--results-dir", {
|
|
200
|
+
description: "Glob pattern or path for Allure results directories (repeatable). Overrides config.resultsDir. Quote globs in the shell",
|
|
201
|
+
});
|
|
198
202
|
this.commandToRun = Option.Rest();
|
|
199
203
|
}
|
|
200
204
|
async execute() {
|
|
201
|
-
const
|
|
205
|
+
const { command, commandArgs } = parseRunCommand(this.commandToRun);
|
|
206
|
+
if (!command) {
|
|
207
|
+
throw new UsageError("expecting command to be specified after --, e.g. allure agent -- npm run test");
|
|
208
|
+
}
|
|
209
|
+
const args = [command, ...commandArgs];
|
|
202
210
|
const configPath = readOptionalString(this.config);
|
|
203
211
|
const configuredCwd = readOptionalString(this.cwd);
|
|
204
212
|
const output = readOptionalString(this.output);
|
|
205
213
|
const reportMode = normalizeAgentHumanReportMode(readOptionalString(this.report));
|
|
206
214
|
const expectations = readOptionalString(this.expectations);
|
|
207
|
-
if (!args.length) {
|
|
208
|
-
throw new UsageError("expecting command to be specified after --, e.g. allure agent -- npm run test");
|
|
209
|
-
}
|
|
210
215
|
try {
|
|
211
216
|
if (output) {
|
|
212
217
|
await assertExplicitAgentOutputDirIsSafe(resolve(await realpath(configuredCwd ?? process.cwd()), output));
|
|
@@ -250,6 +255,7 @@ export class AgentCommand extends Command {
|
|
|
250
255
|
rerunLabels: readOptionalStringArray(this.rerunLabels),
|
|
251
256
|
reportMode,
|
|
252
257
|
args,
|
|
258
|
+
resultsPatterns: this.resultsDir ?? [],
|
|
253
259
|
});
|
|
254
260
|
}
|
|
255
261
|
catch (error) {
|
|
@@ -291,7 +297,8 @@ export class AgentCommand extends Command {
|
|
|
291
297
|
AgentCommand.paths = [["agent"]];
|
|
292
298
|
AgentCommand.usage = Command.Usage({
|
|
293
299
|
description: "Run specified command in Allure agent mode",
|
|
294
|
-
details: "This command runs the specified command with an agent-mode Allure profile and optional human-readable report output. With the default --report auto mode, runs with 1000 or fewer stored visible logical results also write a single-file Awesome report at <output>/awesome/index.html and record its status in <output>/manifest/human-report.json. If a user asks for the report after a run, use `allure agent latest` to recover the output directory and check the human-report manifest before regenerating anything."
|
|
300
|
+
details: "This command runs the specified command with an agent-mode Allure profile and optional human-readable report output. With the default --report auto mode, runs with 1000 or fewer stored visible logical results also write a single-file Awesome report at <output>/awesome/index.html and record its status in <output>/manifest/human-report.json. If a user asks for the report after a run, use `allure agent latest` to recover the output directory and check the human-report manifest before regenerating anything. " +
|
|
301
|
+
"Override results discovery with repeated `--results-dir` (CLI overrides `config.resultsDir`). Quote globs in the shell. When neither is set, directories named `allure-results` are discovered dynamically.",
|
|
295
302
|
examples: [
|
|
296
303
|
["agent -- npm test", "Run npm test and capture agent-mode output with the default human report policy"],
|
|
297
304
|
["agent --report off -- npm test", "Run npm test and capture only the agent-mode artifacts"],
|
|
@@ -299,16 +306,20 @@ AgentCommand.usage = Command.Usage({
|
|
|
299
306
|
"agent --expectations ./expected.yaml -- npm test",
|
|
300
307
|
"Run npm test with agent-mode expectations loaded from ./expected.yaml",
|
|
301
308
|
],
|
|
309
|
+
[
|
|
310
|
+
"agent --results-dir './artifacts/**/allure-results' -- npm test",
|
|
311
|
+
"Override results discovery with a quoted glob",
|
|
312
|
+
],
|
|
302
313
|
],
|
|
303
314
|
});
|
|
304
315
|
export class AgentInspectCommand extends Command {
|
|
305
316
|
constructor() {
|
|
306
317
|
super(...arguments);
|
|
307
318
|
this.resultsDir = Option.Rest({
|
|
308
|
-
name: "Patterns to match test results directories
|
|
319
|
+
name: "Patterns to match test results directories. Overrides config.resultsDir. Defaults to ./**/allure-results when neither is set.",
|
|
309
320
|
});
|
|
310
321
|
this.config = Option.String("--config,-c", {
|
|
311
|
-
description: "The path Allure config file",
|
|
322
|
+
description: "The path to Allure config file",
|
|
312
323
|
});
|
|
313
324
|
this.cwd = Option.String("--cwd", {
|
|
314
325
|
description: "The working directory for resolving results and dumps (default: current working directory)",
|
package/dist/commands/allure2.js
CHANGED
|
@@ -5,15 +5,15 @@ import { AllureReport, readConfig } from "@allurereport/core";
|
|
|
5
5
|
import Allure2Plugin from "@allurereport/plugin-allure2";
|
|
6
6
|
import { Command, Option } from "clipanion";
|
|
7
7
|
import { red } from "yoctocolors";
|
|
8
|
-
import {
|
|
8
|
+
import { resolveAndFindResultsDirs } from "../utils/resultsPatterns.js";
|
|
9
9
|
export class Allure2Command extends Command {
|
|
10
10
|
constructor() {
|
|
11
11
|
super(...arguments);
|
|
12
12
|
this.resultsDir = Option.Rest({
|
|
13
|
-
name: "Patterns to match test results directories
|
|
13
|
+
name: "Patterns to match test results directories. Overrides config.resultsDir. Defaults to ./**/allure-results when neither is set.",
|
|
14
14
|
});
|
|
15
15
|
this.config = Option.String("--config,-c", {
|
|
16
|
-
description: "The path Allure config file",
|
|
16
|
+
description: "The path to Allure config file",
|
|
17
17
|
});
|
|
18
18
|
this.cwd = Option.String("--cwd", {
|
|
19
19
|
description: "The working directory for the command to run (default: current working directory)",
|
|
@@ -39,12 +39,6 @@ export class Allure2Command extends Command {
|
|
|
39
39
|
}
|
|
40
40
|
async execute() {
|
|
41
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}`));
|
|
45
|
-
exit(1);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
42
|
const before = new Date().getTime();
|
|
49
43
|
const defaultAllure2Options = {
|
|
50
44
|
singleFile: this.singleFile ?? false,
|
|
@@ -53,9 +47,15 @@ export class Allure2Command extends Command {
|
|
|
53
47
|
const config = await readConfig(cwd, this.config, {
|
|
54
48
|
output: this.output,
|
|
55
49
|
name: this.reportName,
|
|
56
|
-
knownIssuesPath: this.knownIssues,
|
|
50
|
+
resolutions: { knownIssuesPath: this.knownIssues },
|
|
57
51
|
historyPath: this.historyPath,
|
|
58
52
|
});
|
|
53
|
+
const { resultDirectories, patterns } = await resolveAndFindResultsDirs(cwd, this.resultsDir, config.resultsDir);
|
|
54
|
+
if (!resultDirectories.length) {
|
|
55
|
+
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
56
|
+
exit(1);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
59
|
config.plugins = [
|
|
60
60
|
{
|
|
61
61
|
id: "allure2",
|
package/dist/commands/awesome.js
CHANGED
|
@@ -5,15 +5,15 @@ import { AllureReport, readConfig } from "@allurereport/core";
|
|
|
5
5
|
import { default as AwesomePlugin } from "@allurereport/plugin-awesome";
|
|
6
6
|
import { Command, Option } from "clipanion";
|
|
7
7
|
import { red } from "yoctocolors";
|
|
8
|
-
import {
|
|
8
|
+
import { resolveAndFindResultsDirs } from "../utils/resultsPatterns.js";
|
|
9
9
|
export class AwesomeCommand extends Command {
|
|
10
10
|
constructor() {
|
|
11
11
|
super(...arguments);
|
|
12
12
|
this.resultsDir = Option.Rest({
|
|
13
|
-
name: "Patterns to match test results directories
|
|
13
|
+
name: "Patterns to match test results directories. Overrides config.resultsDir. Defaults to ./**/allure-results when neither is set.",
|
|
14
14
|
});
|
|
15
15
|
this.config = Option.String("--config,-c", {
|
|
16
|
-
description: "The path Allure config file",
|
|
16
|
+
description: "The path to Allure config file",
|
|
17
17
|
});
|
|
18
18
|
this.cwd = Option.String("--cwd", {
|
|
19
19
|
description: "The working directory for the command to run (default: current working directory)",
|
|
@@ -51,21 +51,21 @@ export class AwesomeCommand extends Command {
|
|
|
51
51
|
}
|
|
52
52
|
async execute() {
|
|
53
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}`));
|
|
57
|
-
exit(1);
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
54
|
const before = new Date().getTime();
|
|
61
55
|
const hideLabels = this.hideLabels?.length ? this.hideLabels : undefined;
|
|
62
56
|
const config = await readConfig(cwd, this.config, {
|
|
63
57
|
output: this.output,
|
|
64
58
|
name: this.reportName,
|
|
65
|
-
knownIssuesPath: this.knownIssues,
|
|
59
|
+
resolutions: { knownIssuesPath: this.knownIssues },
|
|
66
60
|
historyPath: this.historyPath,
|
|
67
61
|
hideLabels,
|
|
68
62
|
});
|
|
63
|
+
const { resultDirectories, patterns } = await resolveAndFindResultsDirs(cwd, this.resultsDir, config.resultsDir);
|
|
64
|
+
if (!resultDirectories.length) {
|
|
65
|
+
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
66
|
+
exit(1);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
69
|
const defaultAwesomeOptions = {
|
|
70
70
|
singleFile: this.singleFile ?? false,
|
|
71
71
|
logo: this.logo,
|
package/dist/commands/check.js
CHANGED
|
@@ -95,7 +95,7 @@ export class CheckCommand extends Command {
|
|
|
95
95
|
description: "Add a tag to the check result. Repeat the option for multiple tags",
|
|
96
96
|
});
|
|
97
97
|
this.config = Option.String("--config,-c", {
|
|
98
|
-
description: "The path Allure config file",
|
|
98
|
+
description: "The path to Allure config file",
|
|
99
99
|
});
|
|
100
100
|
this.cwd = Option.String("--cwd", {
|
|
101
101
|
description: "The working directory for the command to run (default: current working directory)",
|
package/dist/commands/classic.js
CHANGED
|
@@ -5,15 +5,15 @@ import { AllureReport, readConfig } from "@allurereport/core";
|
|
|
5
5
|
import ClassicPlugin from "@allurereport/plugin-classic";
|
|
6
6
|
import { Command, Option } from "clipanion";
|
|
7
7
|
import { red } from "yoctocolors";
|
|
8
|
-
import {
|
|
8
|
+
import { resolveAndFindResultsDirs } from "../utils/resultsPatterns.js";
|
|
9
9
|
export class ClassicCommand extends Command {
|
|
10
10
|
constructor() {
|
|
11
11
|
super(...arguments);
|
|
12
12
|
this.resultsDir = Option.Rest({
|
|
13
|
-
name: "Patterns to match test results directories
|
|
13
|
+
name: "Patterns to match test results directories. Overrides config.resultsDir. Defaults to ./**/allure-results when neither is set.",
|
|
14
14
|
});
|
|
15
15
|
this.config = Option.String("--config,-c", {
|
|
16
|
-
description: "The path Allure config file",
|
|
16
|
+
description: "The path to Allure config file",
|
|
17
17
|
});
|
|
18
18
|
this.cwd = Option.String("--cwd", {
|
|
19
19
|
description: "The working directory for the command to run (default: current working directory)",
|
|
@@ -39,12 +39,6 @@ export class ClassicCommand extends Command {
|
|
|
39
39
|
}
|
|
40
40
|
async execute() {
|
|
41
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}`));
|
|
45
|
-
exit(1);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
42
|
const before = new Date().getTime();
|
|
49
43
|
const defaultClassicOptions = {
|
|
50
44
|
singleFile: this.singleFile ?? false,
|
|
@@ -53,9 +47,15 @@ export class ClassicCommand extends Command {
|
|
|
53
47
|
const config = await readConfig(cwd, this.config, {
|
|
54
48
|
output: this.output,
|
|
55
49
|
name: this.reportName,
|
|
56
|
-
knownIssuesPath: this.knownIssues,
|
|
50
|
+
resolutions: { knownIssuesPath: this.knownIssues },
|
|
57
51
|
historyPath: this.historyPath,
|
|
58
52
|
});
|
|
53
|
+
const { resultDirectories, patterns } = await resolveAndFindResultsDirs(cwd, this.resultsDir, config.resultsDir);
|
|
54
|
+
if (!resultDirectories.length) {
|
|
55
|
+
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
56
|
+
exit(1);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
59
|
config.plugins = [
|
|
60
60
|
{
|
|
61
61
|
id: "classic",
|
|
@@ -2,12 +2,16 @@ import { exit } from "node:process";
|
|
|
2
2
|
import { AllureReport } from "@allurereport/core";
|
|
3
3
|
import { KnownError } from "@allurereport/service";
|
|
4
4
|
import { red } from "yoctocolors";
|
|
5
|
-
import {
|
|
5
|
+
import { findFilesByGlobs } from "../../utils/fileSystem.js";
|
|
6
6
|
import { logError } from "../../utils/logs.js";
|
|
7
|
+
import { resolveAndFindResultsDirs, resolveResultsPatterns } from "../../utils/resultsPatterns.js";
|
|
7
8
|
export const generate = async (params) => {
|
|
8
9
|
const dumpFiles = params?.dump?.length ? await findFilesByGlobs(params.cwd, params.dump) : [];
|
|
9
|
-
const
|
|
10
|
-
|
|
10
|
+
const cliPatterns = params.resultsDir ?? [];
|
|
11
|
+
const resolvedPatterns = resolveResultsPatterns(cliPatterns, params.config.resultsDir);
|
|
12
|
+
const shouldReadResults = resolvedPatterns.length > 0 || dumpFiles.length === 0;
|
|
13
|
+
const { resultDirectories = [], patterns = resolvedPatterns } = shouldReadResults
|
|
14
|
+
? await resolveAndFindResultsDirs(params.cwd, cliPatterns, params.config.resultsDir)
|
|
11
15
|
: {};
|
|
12
16
|
if (resultDirectories.length === 0 && dumpFiles.length === 0) {
|
|
13
17
|
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Watcher } from "@allurereport/directory-watcher";
|
|
2
|
+
export declare const allureResultsDirectoriesGlobWatcher: (cwd: string, patterns: readonly string[], update: (newAllureResults: Set<string>, deletedAllureResults: Set<string>) => Promise<void>, options?: {
|
|
3
|
+
indexDelay?: number;
|
|
4
|
+
abortController?: AbortController;
|
|
5
|
+
}) => Watcher;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { difference, watch } from "@allurereport/directory-watcher";
|
|
2
|
+
import { findDirectoriesByGlobs } from "../../utils/fileSystem.js";
|
|
3
|
+
export const allureResultsDirectoriesGlobWatcher = (cwd, patterns, update, options = {}) => {
|
|
4
|
+
const { abortController = new AbortController(), indexDelay = 600 } = options;
|
|
5
|
+
let previousAllureResults = new Set();
|
|
6
|
+
const callback = async () => {
|
|
7
|
+
if (abortController.signal.aborted) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const matched = await findDirectoriesByGlobs(cwd, patterns);
|
|
11
|
+
const currentAllureResults = new Set(matched);
|
|
12
|
+
const [added, deleted] = difference(previousAllureResults, currentAllureResults);
|
|
13
|
+
await update(added, deleted);
|
|
14
|
+
previousAllureResults = currentAllureResults;
|
|
15
|
+
};
|
|
16
|
+
return watch(callback, callback, callback, { indexDelay, abortController });
|
|
17
|
+
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { AllureReport } from "@allurereport/core";
|
|
2
|
-
import { type KnownTestFailure } from "@allurereport/core-api";
|
|
3
2
|
import type { ExitCode, QualityGateValidationResult } from "@allurereport/plugin-api";
|
|
4
3
|
export type TestProcessResult = {
|
|
5
4
|
code: number | null;
|
|
@@ -18,7 +17,6 @@ export declare const executeNestedAllureCommand: (params: {
|
|
|
18
17
|
}) => Promise<number | null>;
|
|
19
18
|
export declare const runTests: (params: {
|
|
20
19
|
allureReport: AllureReport;
|
|
21
|
-
knownIssues: KnownTestFailure[];
|
|
22
20
|
cwd: string;
|
|
23
21
|
command: string;
|
|
24
22
|
commandArgs: string[];
|
|
@@ -28,10 +26,10 @@ export declare const runTests: (params: {
|
|
|
28
26
|
silent?: boolean;
|
|
29
27
|
logs?: RunLogsMode;
|
|
30
28
|
logProcessExit?: boolean;
|
|
29
|
+
resultsPatterns?: readonly string[];
|
|
31
30
|
}) => Promise<TestProcessResult | null>;
|
|
32
31
|
export declare const executeAllureRun: (params: {
|
|
33
32
|
allureReport: AllureReport;
|
|
34
|
-
knownIssues: KnownTestFailure[];
|
|
35
33
|
cwd: string;
|
|
36
34
|
command: string;
|
|
37
35
|
commandArgs: string[];
|
|
@@ -43,6 +41,7 @@ export declare const executeAllureRun: (params: {
|
|
|
43
41
|
ignoreLogs?: boolean;
|
|
44
42
|
maxRerun?: number;
|
|
45
43
|
logProcessExit?: boolean;
|
|
44
|
+
resultsPatterns?: readonly string[];
|
|
46
45
|
}) => Promise<{
|
|
47
46
|
globalExitCode: ExitCode;
|
|
48
47
|
testProcessResult: TestProcessResult | null;
|
|
@@ -14,6 +14,7 @@ import { red } from "yoctocolors";
|
|
|
14
14
|
import { logTests, runProcess, terminationOf } from "../../utils/index.js";
|
|
15
15
|
import { logError } from "../../utils/logs.js";
|
|
16
16
|
import { stopProcessTree } from "../../utils/process.js";
|
|
17
|
+
import { allureResultsDirectoriesGlobWatcher } from "./resultsDiscovery.js";
|
|
17
18
|
export const executeNestedAllureCommand = async (params) => {
|
|
18
19
|
const nestedProcess = runProcess({
|
|
19
20
|
command: params.command,
|
|
@@ -24,8 +25,16 @@ export const executeNestedAllureCommand = async (params) => {
|
|
|
24
25
|
});
|
|
25
26
|
return await terminationOf(nestedProcess);
|
|
26
27
|
};
|
|
28
|
+
const attachResultsDirectoryWatchers = (params) => {
|
|
29
|
+
if (params.resultsPatterns.length > 0) {
|
|
30
|
+
return allureResultsDirectoriesGlobWatcher(params.cwd, params.resultsPatterns, params.onUpdate, {
|
|
31
|
+
indexDelay: 600,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return allureResultsDirectoriesWatcher(params.cwd, params.onUpdate, { indexDelay: 600 });
|
|
35
|
+
};
|
|
27
36
|
export const runTests = async (params) => {
|
|
28
|
-
const { allureReport,
|
|
37
|
+
const { allureReport, cwd, command, commandArgs, logs, environmentVariables, environment, withQualityGate, silent, logProcessExit = true, resultsPatterns = [], } = params;
|
|
29
38
|
let testProcessStarted = false;
|
|
30
39
|
const allureResultsWatchers = new Map();
|
|
31
40
|
const processWatcher = delayedFileProcessingWatcher(async (path) => {
|
|
@@ -34,28 +43,32 @@ export const runTests = async (params) => {
|
|
|
34
43
|
indexDelay: 200,
|
|
35
44
|
minProcessingDelay: 1000,
|
|
36
45
|
});
|
|
37
|
-
const allureResultsWatch =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
const allureResultsWatch = attachResultsDirectoryWatchers({
|
|
47
|
+
cwd,
|
|
48
|
+
resultsPatterns,
|
|
49
|
+
onUpdate: async (newAllureResults, deletedAllureResults) => {
|
|
50
|
+
for (const delAr of deletedAllureResults) {
|
|
51
|
+
const watcher = allureResultsWatchers.get(delAr);
|
|
52
|
+
if (watcher) {
|
|
53
|
+
await watcher.abort();
|
|
54
|
+
}
|
|
55
|
+
allureResultsWatchers.delete(delAr);
|
|
42
56
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
57
|
+
for (const newAr of newAllureResults) {
|
|
58
|
+
if (allureResultsWatchers.has(newAr)) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const watcher = newFilesInDirectoryWatcher(newAr, async (path) => {
|
|
62
|
+
await processWatcher.addFile(path);
|
|
63
|
+
}, {
|
|
64
|
+
ignoreInitial: !testProcessStarted,
|
|
65
|
+
indexDelay: 300,
|
|
66
|
+
});
|
|
67
|
+
allureResultsWatchers.set(newAr, watcher);
|
|
68
|
+
await watcher.initialScan();
|
|
48
69
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}, {
|
|
52
|
-
ignoreInitial: !testProcessStarted,
|
|
53
|
-
indexDelay: 300,
|
|
54
|
-
});
|
|
55
|
-
allureResultsWatchers.set(newAr, watcher);
|
|
56
|
-
await watcher.initialScan();
|
|
57
|
-
}
|
|
58
|
-
}, { indexDelay: 600 });
|
|
70
|
+
},
|
|
71
|
+
});
|
|
59
72
|
await allureResultsWatch.initialScan();
|
|
60
73
|
testProcessStarted = true;
|
|
61
74
|
const beforeProcess = Date.now();
|
|
@@ -86,7 +99,6 @@ export const runTests = async (params) => {
|
|
|
86
99
|
trs: filteredTrs,
|
|
87
100
|
state: qualityGateState,
|
|
88
101
|
environment,
|
|
89
|
-
knownIssues,
|
|
90
102
|
});
|
|
91
103
|
if (!fastFailed) {
|
|
92
104
|
return;
|
|
@@ -148,7 +160,7 @@ export const runTests = async (params) => {
|
|
|
148
160
|
};
|
|
149
161
|
};
|
|
150
162
|
export const executeAllureRun = async (params) => {
|
|
151
|
-
const { allureReport,
|
|
163
|
+
const { allureReport, cwd, command, commandArgs, environmentVariables = {}, environment, withQualityGate, silent, logs, ignoreLogs, maxRerun = 0, logProcessExit = true, resultsPatterns = [], } = params;
|
|
152
164
|
await allureReport.start();
|
|
153
165
|
const globalExitCode = {
|
|
154
166
|
original: 0,
|
|
@@ -161,7 +173,6 @@ export const executeAllureRun = async (params) => {
|
|
|
161
173
|
logs,
|
|
162
174
|
silent,
|
|
163
175
|
allureReport,
|
|
164
|
-
knownIssues,
|
|
165
176
|
cwd,
|
|
166
177
|
command,
|
|
167
178
|
commandArgs,
|
|
@@ -169,6 +180,7 @@ export const executeAllureRun = async (params) => {
|
|
|
169
180
|
environmentVariables,
|
|
170
181
|
withQualityGate,
|
|
171
182
|
logProcessExit,
|
|
183
|
+
resultsPatterns,
|
|
172
184
|
});
|
|
173
185
|
const allFailuresAfterInitialRun = await allureReport.store.failedTestResults();
|
|
174
186
|
const blockingFailuresAfterInitialRun = await allureReport.store.blockingFailedTestResults();
|
|
@@ -191,7 +203,6 @@ export const executeAllureRun = async (params) => {
|
|
|
191
203
|
silent,
|
|
192
204
|
logs,
|
|
193
205
|
allureReport,
|
|
194
|
-
knownIssues,
|
|
195
206
|
cwd,
|
|
196
207
|
command,
|
|
197
208
|
commandArgs,
|
|
@@ -203,6 +214,7 @@ export const executeAllureRun = async (params) => {
|
|
|
203
214
|
},
|
|
204
215
|
withQualityGate,
|
|
205
216
|
logProcessExit,
|
|
217
|
+
resultsPatterns,
|
|
206
218
|
});
|
|
207
219
|
await rm(tmpDir, { recursive: true });
|
|
208
220
|
logTests(await allureReport.store.allTestResults());
|
|
@@ -217,7 +229,6 @@ export const executeAllureRun = async (params) => {
|
|
|
217
229
|
if (withQualityGate && !qualityGateResults.length) {
|
|
218
230
|
const { results } = await allureReport.validate({
|
|
219
231
|
trs,
|
|
220
|
-
knownIssues,
|
|
221
232
|
environment,
|
|
222
233
|
});
|
|
223
234
|
qualityGateResults = results;
|
package/dist/commands/csv.js
CHANGED
|
@@ -6,15 +6,15 @@ import { AllureReport, readConfig } from "@allurereport/core";
|
|
|
6
6
|
import CsvPlugin from "@allurereport/plugin-csv";
|
|
7
7
|
import { Command, Option } from "clipanion";
|
|
8
8
|
import { red } from "yoctocolors";
|
|
9
|
-
import {
|
|
9
|
+
import { resolveAndFindResultsDirs } from "../utils/resultsPatterns.js";
|
|
10
10
|
export class CsvCommand extends Command {
|
|
11
11
|
constructor() {
|
|
12
12
|
super(...arguments);
|
|
13
13
|
this.resultsDir = Option.Rest({
|
|
14
|
-
name: "Patterns to match test results directories
|
|
14
|
+
name: "Patterns to match test results directories. Overrides config.resultsDir. Defaults to ./**/allure-results when neither is set.",
|
|
15
15
|
});
|
|
16
16
|
this.config = Option.String("--config,-c", {
|
|
17
|
-
description: "The path Allure config file",
|
|
17
|
+
description: "The path to Allure config file",
|
|
18
18
|
});
|
|
19
19
|
this.cwd = Option.String("--cwd", {
|
|
20
20
|
description: "The working directory for the command to run (default: current working directory)",
|
|
@@ -34,12 +34,6 @@ export class CsvCommand extends Command {
|
|
|
34
34
|
}
|
|
35
35
|
async execute() {
|
|
36
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}`));
|
|
40
|
-
exit(1);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
37
|
const before = new Date().getTime();
|
|
44
38
|
const defaultCsvOptions = {
|
|
45
39
|
separator: this.separator ?? ",",
|
|
@@ -47,8 +41,14 @@ export class CsvCommand extends Command {
|
|
|
47
41
|
fileName: this.output && isAbsolute(this.output) ? this.output : this.output ? join(cwd, this.output) : undefined,
|
|
48
42
|
};
|
|
49
43
|
const config = await readConfig(cwd, this.config, {
|
|
50
|
-
knownIssuesPath: this.knownIssues,
|
|
44
|
+
resolutions: { knownIssuesPath: this.knownIssues },
|
|
51
45
|
});
|
|
46
|
+
const { resultDirectories, patterns } = await resolveAndFindResultsDirs(cwd, this.resultsDir, config.resultsDir);
|
|
47
|
+
if (!resultDirectories.length) {
|
|
48
|
+
console.error(red(`No test results directories found matching pattern: ${patterns}`));
|
|
49
|
+
exit(1);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
52
|
config.plugins = [
|
|
53
53
|
{
|
|
54
54
|
id: "csv",
|