allure 0.0.0 β 3.0.0-beta.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.
- package/README.md +33 -0
- package/cli.js +2 -0
- package/dist/commands/awesome.d.ts +12 -0
- package/dist/commands/awesome.js +81 -0
- package/dist/commands/classic.d.ts +11 -0
- package/dist/commands/classic.js +69 -0
- package/dist/commands/csv.d.ts +9 -0
- package/dist/commands/csv.js +51 -0
- package/dist/commands/generate.d.ts +9 -0
- package/dist/commands/generate.js +35 -0
- package/dist/commands/history.d.ts +7 -0
- package/dist/commands/history.js +34 -0
- package/dist/commands/index.d.ts +15 -0
- package/dist/commands/index.js +15 -0
- package/dist/commands/knownIssue.d.ts +6 -0
- package/dist/commands/knownIssue.js +27 -0
- package/dist/commands/log.d.ts +7 -0
- package/dist/commands/log.js +46 -0
- package/dist/commands/open.d.ts +8 -0
- package/dist/commands/open.js +39 -0
- package/dist/commands/qualityGate.d.ts +6 -0
- package/dist/commands/qualityGate.js +46 -0
- package/dist/commands/run.d.ts +10 -0
- package/dist/commands/run.js +167 -0
- package/dist/commands/slack.d.ts +7 -0
- package/dist/commands/slack.js +37 -0
- package/dist/commands/testplan.d.ts +6 -0
- package/dist/commands/testplan.js +37 -0
- package/dist/commands/watch.d.ts +10 -0
- package/dist/commands/watch.js +118 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +33 -0
- package/dist/utils/commands.d.ts +16 -0
- package/dist/utils/commands.js +14 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/process.d.ts +3 -0
- package/dist/utils/process.js +15 -0
- package/dist/utils/terminal.d.ts +3 -0
- package/dist/utils/terminal.js +20 -0
- package/package.json +60 -7
package/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Allure CLI
|
|
2
|
+
|
|
3
|
+
[<img src="https://allurereport.org/public/img/allure-report.svg" height="85px" alt="Allure Report logo" align="right" />](https://allurereport.org "Allure Report")
|
|
4
|
+
|
|
5
|
+
- Learn more about Allure Report at https://allurereport.org
|
|
6
|
+
- π [Documentation](https://allurereport.org/docs/) β discover official documentation for Allure Report
|
|
7
|
+
- β [Questions and Support](https://github.com/orgs/allure-framework/discussions/categories/questions-support) β get help from the team and community
|
|
8
|
+
- π’ [Official announcements](https://github.com/orgs/allure-framework/discussions/categories/announcements) β be in touch with the latest updates
|
|
9
|
+
- π¬ [General Discussion ](https://github.com/orgs/allure-framework/discussions/categories/general-discussion) β engage in casual conversations, share insights and ideas with the community
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
The Allure CLI is a main entry point which includes many sub-commands
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
Use your favorite package manager to install the package:
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
npm add allure
|
|
23
|
+
yarn add allure
|
|
24
|
+
pnpm add allure
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
The CLI provides a set of commands to work with Allure Report features. To see the list of available commands, run:
|
|
30
|
+
|
|
31
|
+
```shell
|
|
32
|
+
allure --help
|
|
33
|
+
```
|
package/cli.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type AwesomeCommandOptions = {
|
|
2
|
+
output?: string;
|
|
3
|
+
reportName?: string;
|
|
4
|
+
reportLanguage?: string;
|
|
5
|
+
logo?: string;
|
|
6
|
+
singleFile?: boolean;
|
|
7
|
+
historyPath?: string;
|
|
8
|
+
knownIssues?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare const AwesomeCommandAction: (resultsDir: string, options: AwesomeCommandOptions) => Promise<void>;
|
|
11
|
+
export declare const AwesomeCommand: (cli: import("cac").CAC) => void;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { AllureReport, resolveConfig } from "@allure/core";
|
|
2
|
+
import { createCommand } from "../utils/commands.js";
|
|
3
|
+
export const AwesomeCommandAction = async (resultsDir, options) => {
|
|
4
|
+
const before = new Date().getTime();
|
|
5
|
+
const { output, reportName: name, historyPath, knownIssues: knownIssuesPath, ...rest } = options;
|
|
6
|
+
const config = await resolveConfig({
|
|
7
|
+
output,
|
|
8
|
+
name,
|
|
9
|
+
historyPath,
|
|
10
|
+
knownIssuesPath,
|
|
11
|
+
plugins: {
|
|
12
|
+
"@allure/plugin-awesome": {
|
|
13
|
+
options: rest,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
const allureReport = new AllureReport(config);
|
|
18
|
+
await allureReport.start();
|
|
19
|
+
await allureReport.readDirectory(resultsDir);
|
|
20
|
+
await allureReport.done();
|
|
21
|
+
const after = new Date().getTime();
|
|
22
|
+
console.log(`the report successfully generated (${after - before}ms)`);
|
|
23
|
+
};
|
|
24
|
+
export const AwesomeCommand = createCommand({
|
|
25
|
+
name: "awesome <resultsDir>",
|
|
26
|
+
description: "Generates Allure Awesome report based on provided Allure Results",
|
|
27
|
+
options: [
|
|
28
|
+
[
|
|
29
|
+
"--output, -o <file>",
|
|
30
|
+
{
|
|
31
|
+
description: "The output directory name. Absolute paths are accepted as well",
|
|
32
|
+
default: "allure-report",
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
"--report-name, --name <string>",
|
|
37
|
+
{
|
|
38
|
+
description: "The report name",
|
|
39
|
+
default: "Allure Report",
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
[
|
|
43
|
+
"--single-file",
|
|
44
|
+
{
|
|
45
|
+
description: "Generate single file report",
|
|
46
|
+
default: false,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
[
|
|
50
|
+
"--logo <string>",
|
|
51
|
+
{
|
|
52
|
+
description: "Path to the report logo which will be displayed in the header",
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
[
|
|
56
|
+
"--theme <string>",
|
|
57
|
+
{
|
|
58
|
+
description: "Default theme of the report (default: OS theme)",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
[
|
|
62
|
+
"--report-language, --lang <string>",
|
|
63
|
+
{
|
|
64
|
+
description: "Default language of the report (default: OS language)",
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
[
|
|
68
|
+
"--history-path, -h <file>",
|
|
69
|
+
{
|
|
70
|
+
description: "The path to history file",
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
[
|
|
74
|
+
"--known-issues <file>",
|
|
75
|
+
{
|
|
76
|
+
description: "Path to the known issues file. Updates the file and quarantines failed tests when specified",
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
],
|
|
80
|
+
action: AwesomeCommandAction,
|
|
81
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type ClassicCommandOptions = {
|
|
2
|
+
output?: string;
|
|
3
|
+
reportName?: string;
|
|
4
|
+
reportLanguage?: string;
|
|
5
|
+
singleFile?: boolean;
|
|
6
|
+
historyPath?: string;
|
|
7
|
+
knownIssues?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const ClassicCommandAction: (resultsDir: string, options: ClassicCommandOptions) => Promise<void>;
|
|
10
|
+
export declare const ClassicCommand: (cli: import("cac").CAC) => void;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { AllureReport, resolveConfig } from "@allure/core";
|
|
2
|
+
import { createCommand } from "../utils/commands.js";
|
|
3
|
+
export const ClassicCommandAction = async (resultsDir, options) => {
|
|
4
|
+
const before = new Date().getTime();
|
|
5
|
+
const { output, reportName: name, historyPath, knownIssues: knownIssuesPath, ...rest } = options;
|
|
6
|
+
const config = await resolveConfig({
|
|
7
|
+
output,
|
|
8
|
+
name,
|
|
9
|
+
historyPath,
|
|
10
|
+
knownIssuesPath,
|
|
11
|
+
plugins: {
|
|
12
|
+
"@allure/plugin-classic": {
|
|
13
|
+
options: rest,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
const allureReport = new AllureReport(config);
|
|
18
|
+
await allureReport.start();
|
|
19
|
+
await allureReport.readDirectory(resultsDir);
|
|
20
|
+
await allureReport.done();
|
|
21
|
+
const after = new Date().getTime();
|
|
22
|
+
console.log(`the report successfully generated (${after - before}ms)`);
|
|
23
|
+
};
|
|
24
|
+
export const ClassicCommand = createCommand({
|
|
25
|
+
name: "classic <resultsDir>",
|
|
26
|
+
description: "Generates Allure Classic report based on provided Allure Results",
|
|
27
|
+
options: [
|
|
28
|
+
[
|
|
29
|
+
"--output, -o <file>",
|
|
30
|
+
{
|
|
31
|
+
description: "The output directory name. Absolute paths are accepted as well",
|
|
32
|
+
default: "allure-report",
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
[
|
|
36
|
+
"--report-name, --name <string>",
|
|
37
|
+
{
|
|
38
|
+
description: "The report name",
|
|
39
|
+
default: "Allure Report",
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
[
|
|
43
|
+
"--report-language, --lang <string>",
|
|
44
|
+
{
|
|
45
|
+
description: "Default language of the report (default: OS language)",
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
[
|
|
49
|
+
"--single-file",
|
|
50
|
+
{
|
|
51
|
+
description: "Generate single file report",
|
|
52
|
+
default: false,
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
[
|
|
56
|
+
"--history-path, -h <file>",
|
|
57
|
+
{
|
|
58
|
+
description: "The path to history file",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
[
|
|
62
|
+
"--known-issues <file>",
|
|
63
|
+
{
|
|
64
|
+
description: "Path to the known issues file. Updates the file and quarantines failed tests when specified",
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
],
|
|
68
|
+
action: ClassicCommandAction,
|
|
69
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type CsvCommandOptions = {
|
|
2
|
+
separator?: string;
|
|
3
|
+
disableHeaders?: boolean;
|
|
4
|
+
output?: string;
|
|
5
|
+
knownIssues?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const CsvCommandAction: (resultsDir: string, options: CsvCommandOptions) => Promise<void>;
|
|
8
|
+
export declare const CsvCommand: (cli: import("cac").CAC) => void;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { AllureReport, resolveConfig } from "@allure/core";
|
|
2
|
+
import { createCommand } from "../utils/commands.js";
|
|
3
|
+
export const CsvCommandAction = async (resultsDir, options) => {
|
|
4
|
+
const before = new Date().getTime();
|
|
5
|
+
const config = await resolveConfig({
|
|
6
|
+
plugins: {
|
|
7
|
+
"@allure/plugin-csv": {
|
|
8
|
+
options,
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
const allureReport = new AllureReport(config);
|
|
13
|
+
await allureReport.start();
|
|
14
|
+
await allureReport.readDirectory(resultsDir);
|
|
15
|
+
await allureReport.done();
|
|
16
|
+
const after = new Date().getTime();
|
|
17
|
+
console.log(`the report successfully generated (${after - before}ms)`);
|
|
18
|
+
};
|
|
19
|
+
export const CsvCommand = createCommand({
|
|
20
|
+
name: "csv <resultsDir>",
|
|
21
|
+
description: "Generates CSV report based on provided Allure Results",
|
|
22
|
+
options: [
|
|
23
|
+
[
|
|
24
|
+
"--output, -o <file>",
|
|
25
|
+
{
|
|
26
|
+
description: "The output file name. Absolute paths are accepted as well",
|
|
27
|
+
default: "allure.csv",
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
"--disable-headers",
|
|
32
|
+
{
|
|
33
|
+
description: "Specify, to disable CSV headers",
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
[
|
|
37
|
+
"--separator <string>",
|
|
38
|
+
{
|
|
39
|
+
description: "The csv separator",
|
|
40
|
+
default: ",",
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
[
|
|
44
|
+
"--known-issues <file>",
|
|
45
|
+
{
|
|
46
|
+
description: "Path to the known issues file. Updates the file and quarantines failed tests when specified",
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
],
|
|
50
|
+
action: CsvCommandAction,
|
|
51
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
type CommandOptions = {
|
|
2
|
+
config?: string;
|
|
3
|
+
output?: string;
|
|
4
|
+
cwd?: string;
|
|
5
|
+
reportName?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const GenerateCommandAction: (resultsDir: string, options: CommandOptions) => Promise<void>;
|
|
8
|
+
export declare const GenerateCommand: (cli: import("cac").CAC) => void;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AllureReport, readRuntimeConfig } from "@allure/core";
|
|
2
|
+
import { createCommand } from "../utils/commands.js";
|
|
3
|
+
export const GenerateCommandAction = async (resultsDir, options) => {
|
|
4
|
+
const { config: configPath, output, cwd, reportName } = options;
|
|
5
|
+
const config = await readRuntimeConfig(configPath, cwd, output, reportName);
|
|
6
|
+
const allureReport = new AllureReport(config);
|
|
7
|
+
await allureReport.start();
|
|
8
|
+
await allureReport.readDirectory(resultsDir);
|
|
9
|
+
await allureReport.done();
|
|
10
|
+
};
|
|
11
|
+
export const GenerateCommand = createCommand({
|
|
12
|
+
name: "generate <resultsDir>",
|
|
13
|
+
description: "Generates the report to specified directory",
|
|
14
|
+
options: [
|
|
15
|
+
[
|
|
16
|
+
"--config, -c <file>",
|
|
17
|
+
{
|
|
18
|
+
description: "The path Allure config file",
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
[
|
|
22
|
+
"--output, -o <file>",
|
|
23
|
+
{
|
|
24
|
+
description: "The output directory name. Absolute paths are accepted as well (default: allure-report)",
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
[
|
|
28
|
+
"--cwd <cwd>",
|
|
29
|
+
{
|
|
30
|
+
description: "The working directory for the command to run (default: current working directory)",
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
],
|
|
34
|
+
action: GenerateCommandAction,
|
|
35
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type CommandOptions = {
|
|
2
|
+
historyPath?: string;
|
|
3
|
+
reportName?: string;
|
|
4
|
+
};
|
|
5
|
+
export declare const HistoryCommandAction: (resultsDir: string, options: CommandOptions) => Promise<void>;
|
|
6
|
+
export declare const HistoryCommand: (cli: import("cac").CAC) => void;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { AllureReport, resolveConfig } from "@allure/core";
|
|
2
|
+
import { createCommand } from "../utils/commands.js";
|
|
3
|
+
export const HistoryCommandAction = async (resultsDir, options) => {
|
|
4
|
+
const config = await resolveConfig({
|
|
5
|
+
historyPath: options.historyPath,
|
|
6
|
+
name: options.reportName,
|
|
7
|
+
plugins: {},
|
|
8
|
+
});
|
|
9
|
+
const allureReport = new AllureReport(config);
|
|
10
|
+
await allureReport.start();
|
|
11
|
+
await allureReport.readDirectory(resultsDir);
|
|
12
|
+
await allureReport.done();
|
|
13
|
+
};
|
|
14
|
+
export const HistoryCommand = createCommand({
|
|
15
|
+
name: "history <resultsDir>",
|
|
16
|
+
description: "Generates the history to specified folder",
|
|
17
|
+
options: [
|
|
18
|
+
[
|
|
19
|
+
"--history-path, -h <file>",
|
|
20
|
+
{
|
|
21
|
+
description: "The path to history file",
|
|
22
|
+
default: "history.jsonl",
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
[
|
|
26
|
+
"--report-name, --name <string>",
|
|
27
|
+
{
|
|
28
|
+
description: "The report name",
|
|
29
|
+
default: "Allure Report",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
],
|
|
33
|
+
action: HistoryCommandAction,
|
|
34
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./history.js";
|
|
2
|
+
export * from "./testplan.js";
|
|
3
|
+
export * from "./classic.js";
|
|
4
|
+
export * from "./awesome.js";
|
|
5
|
+
export * from "./csv.js";
|
|
6
|
+
export * from "./history.js";
|
|
7
|
+
export * from "./knownIssue.js";
|
|
8
|
+
export * from "./run.js";
|
|
9
|
+
export * from "./slack.js";
|
|
10
|
+
export * from "./testplan.js";
|
|
11
|
+
export * from "./watch.js";
|
|
12
|
+
export * from "./open.js";
|
|
13
|
+
export * from "./qualityGate.js";
|
|
14
|
+
export * from "./log.js";
|
|
15
|
+
export * from "./generate.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./history.js";
|
|
2
|
+
export * from "./testplan.js";
|
|
3
|
+
export * from "./classic.js";
|
|
4
|
+
export * from "./awesome.js";
|
|
5
|
+
export * from "./csv.js";
|
|
6
|
+
export * from "./history.js";
|
|
7
|
+
export * from "./knownIssue.js";
|
|
8
|
+
export * from "./run.js";
|
|
9
|
+
export * from "./slack.js";
|
|
10
|
+
export * from "./testplan.js";
|
|
11
|
+
export * from "./watch.js";
|
|
12
|
+
export * from "./open.js";
|
|
13
|
+
export * from "./qualityGate.js";
|
|
14
|
+
export * from "./log.js";
|
|
15
|
+
export * from "./generate.js";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { AllureReport, createConfig, writeKnownIssues } from "@allure/core";
|
|
2
|
+
import console from "node:console";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { createCommand } from "../utils/commands.js";
|
|
5
|
+
export const KnownIssueCommandAction = async (resultsDir, options) => {
|
|
6
|
+
const { output = "known-issues.json" } = options;
|
|
7
|
+
const config = await createConfig({});
|
|
8
|
+
const allureReport = new AllureReport(config);
|
|
9
|
+
const targetPath = resolve(output);
|
|
10
|
+
await allureReport.readDirectory(resultsDir);
|
|
11
|
+
await writeKnownIssues(allureReport.store, output);
|
|
12
|
+
console.log(`writing known-issues.json to ${targetPath}`);
|
|
13
|
+
};
|
|
14
|
+
export const KnownIssueCommand = createCommand({
|
|
15
|
+
name: "known-issue <resultsDir>",
|
|
16
|
+
description: "Generates a known issue list",
|
|
17
|
+
options: [
|
|
18
|
+
[
|
|
19
|
+
"--output, -o <file>",
|
|
20
|
+
{
|
|
21
|
+
description: "The output file name. Absolute paths are accepted as well",
|
|
22
|
+
default: "known-issues.json",
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
],
|
|
26
|
+
action: KnownIssueCommandAction,
|
|
27
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type LogCommandOptions = {
|
|
2
|
+
allSteps?: boolean;
|
|
3
|
+
withTrace?: boolean;
|
|
4
|
+
groupBy?: "suites" | "features" | "packages" | "none";
|
|
5
|
+
};
|
|
6
|
+
export declare const LogCommandAction: (resultsDir: string, options: LogCommandOptions) => Promise<void>;
|
|
7
|
+
export declare const LogCommand: (cli: import("cac").CAC) => void;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { AllureReport, resolveConfig } from "@allure/core";
|
|
2
|
+
import { createCommand } from "../utils/commands.js";
|
|
3
|
+
export const LogCommandAction = async (resultsDir, options) => {
|
|
4
|
+
const before = new Date().getTime();
|
|
5
|
+
const config = await resolveConfig({
|
|
6
|
+
plugins: {
|
|
7
|
+
"@allure/plugin-log": {
|
|
8
|
+
options,
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
const allureReport = new AllureReport(config);
|
|
13
|
+
await allureReport.start();
|
|
14
|
+
await allureReport.readDirectory(resultsDir);
|
|
15
|
+
await allureReport.done();
|
|
16
|
+
const after = new Date().getTime();
|
|
17
|
+
console.log(`the report successfully generated (${after - before}ms)`);
|
|
18
|
+
};
|
|
19
|
+
export const LogCommand = createCommand({
|
|
20
|
+
name: "log <resultsDir>",
|
|
21
|
+
description: "Prints Allure Results to the console",
|
|
22
|
+
options: [
|
|
23
|
+
[
|
|
24
|
+
"--group-by <label>",
|
|
25
|
+
{
|
|
26
|
+
description: "Group tests by type (none, suite, feature, package, etc.)",
|
|
27
|
+
default: "suite",
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
"--all-steps",
|
|
32
|
+
{
|
|
33
|
+
description: "Show all steps. By default only failed steps are shown",
|
|
34
|
+
default: false,
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
[
|
|
38
|
+
"--with-trace",
|
|
39
|
+
{
|
|
40
|
+
description: "Print stack trace for failed tests",
|
|
41
|
+
default: false,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
],
|
|
45
|
+
action: LogCommandAction,
|
|
46
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type CommandOptions = {
|
|
2
|
+
config?: string;
|
|
3
|
+
port?: number;
|
|
4
|
+
live: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare const OpenCommandAction: (reportDir: string | undefined, options: CommandOptions) => Promise<void>;
|
|
7
|
+
export declare const OpenCommand: (cli: import("cac").CAC) => void;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { readRuntimeConfig } from "@allure/core";
|
|
2
|
+
import { serve } from "@allure/static-server";
|
|
3
|
+
import { createCommand } from "../utils/commands.js";
|
|
4
|
+
export const OpenCommandAction = async (reportDir, options) => {
|
|
5
|
+
const { config: configPath, port, live } = options;
|
|
6
|
+
const config = await readRuntimeConfig(configPath, undefined, reportDir);
|
|
7
|
+
await serve({
|
|
8
|
+
port: port,
|
|
9
|
+
servePath: config.output,
|
|
10
|
+
live: Boolean(live),
|
|
11
|
+
open: true,
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
export const OpenCommand = createCommand({
|
|
15
|
+
name: "open [reportDir]",
|
|
16
|
+
description: "Serves specified directory",
|
|
17
|
+
options: [
|
|
18
|
+
[
|
|
19
|
+
"--config, -c <file>",
|
|
20
|
+
{
|
|
21
|
+
description: "The path Allure config file",
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
[
|
|
25
|
+
"--port <string>",
|
|
26
|
+
{
|
|
27
|
+
description: "The port to serve the reports on. If not set, the server starts on a random port",
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
"--live",
|
|
32
|
+
{
|
|
33
|
+
description: "Reload pages on any file change in the served directory",
|
|
34
|
+
default: false,
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
],
|
|
38
|
+
action: OpenCommandAction,
|
|
39
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { AllureReport, readRuntimeConfig } from "@allure/core";
|
|
2
|
+
import console from "node:console";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { bold, red } from "yoctocolors";
|
|
5
|
+
import { createCommand } from "../utils/commands.js";
|
|
6
|
+
export const QualityGateCommandAction = async (resultsDir, options) => {
|
|
7
|
+
const cwd = options.cwd ?? process.cwd();
|
|
8
|
+
const fullConfig = await readRuntimeConfig(cwd, "./allure-report");
|
|
9
|
+
const allureReport = new AllureReport(fullConfig);
|
|
10
|
+
await allureReport.start();
|
|
11
|
+
await allureReport.readDirectory(resultsDir);
|
|
12
|
+
await allureReport.done();
|
|
13
|
+
await allureReport.validate();
|
|
14
|
+
if (allureReport.exitCode === 0) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const failedResults = allureReport.validationResults.filter((result) => !result.success);
|
|
18
|
+
console.error(red(`Quality gate has failed with ${bold(failedResults.length.toString())} errors:\n`));
|
|
19
|
+
for (const result of failedResults) {
|
|
20
|
+
let scope = "";
|
|
21
|
+
switch (result.meta?.type) {
|
|
22
|
+
case "label":
|
|
23
|
+
scope = `(label[${result.meta.name}="${result.meta.value}"])`;
|
|
24
|
+
break;
|
|
25
|
+
case "parameter":
|
|
26
|
+
scope = `(parameter[${result.meta.name}="${result.meta.value}"])`;
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
console.error(red(`β¨― ${bold(`${result.rule}${scope}`)}: expected ${result.expected}, actual ${result.actual}`));
|
|
30
|
+
}
|
|
31
|
+
console.error(red(`\nThe process has been exited with code 1`));
|
|
32
|
+
process.exit(allureReport.exitCode);
|
|
33
|
+
};
|
|
34
|
+
export const QualityGateCommand = createCommand({
|
|
35
|
+
name: "quality-gate <resultsDir>",
|
|
36
|
+
description: "Returns status code 1 if there any test failure above specified success rate",
|
|
37
|
+
options: [
|
|
38
|
+
[
|
|
39
|
+
"--cwd <cwd>",
|
|
40
|
+
{
|
|
41
|
+
description: "The working directory for the command to run (default: current working directory)",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
],
|
|
45
|
+
action: QualityGateCommandAction,
|
|
46
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type RunCommandOptions = {
|
|
2
|
+
config?: string;
|
|
3
|
+
cwd?: string;
|
|
4
|
+
output?: string;
|
|
5
|
+
reportName?: string;
|
|
6
|
+
rerun?: number;
|
|
7
|
+
silent?: boolean;
|
|
8
|
+
} & Record<"--", string[]>;
|
|
9
|
+
export declare const RunCommandAction: (options: RunCommandOptions) => Promise<never>;
|
|
10
|
+
export declare const RunCommand: (cli: import("cac").CAC) => void;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { AllureReport, isFileNotFoundError, readRuntimeConfig } from "@allure/core";
|
|
2
|
+
import { createTestPlan } from "@allure/core-api";
|
|
3
|
+
import { allureResultsDirectoriesWatcher, delayedFileProcessingWatcher, newFilesInDirectoryWatcher, } from "@allure/directory-watcher";
|
|
4
|
+
import AllureAwesome from "@allure/plugin-awesome";
|
|
5
|
+
import { PathResultFile } from "@allure/reader-api";
|
|
6
|
+
import * as console from "node:console";
|
|
7
|
+
import { mkdtemp, realpath, rm, writeFile } from "node:fs/promises";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
import { join, resolve } from "node:path";
|
|
10
|
+
import process from "node:process";
|
|
11
|
+
import { createCommand } from "../utils/commands.js";
|
|
12
|
+
import { logTests, runProcess, terminationOf } from "../utils/index.js";
|
|
13
|
+
const runTests = async (allureReport, cwd, command, commandArgs, environment, silent) => {
|
|
14
|
+
let testProcessStarted = false;
|
|
15
|
+
const allureResultsWatchers = new Map();
|
|
16
|
+
const processWatcher = delayedFileProcessingWatcher(async (path) => {
|
|
17
|
+
await allureReport.readResult(new PathResultFile(path));
|
|
18
|
+
}, {
|
|
19
|
+
indexDelay: 200,
|
|
20
|
+
minProcessingDelay: 1000,
|
|
21
|
+
});
|
|
22
|
+
const allureResultsWatch = allureResultsDirectoriesWatcher(cwd, async (newAllureResults, deletedAllureResults) => {
|
|
23
|
+
for (const delAr of deletedAllureResults) {
|
|
24
|
+
const watcher = allureResultsWatchers.get(delAr);
|
|
25
|
+
if (watcher) {
|
|
26
|
+
await watcher.abort();
|
|
27
|
+
}
|
|
28
|
+
allureResultsWatchers.delete(delAr);
|
|
29
|
+
}
|
|
30
|
+
for (const newAr of newAllureResults) {
|
|
31
|
+
if (allureResultsWatchers.has(newAr)) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const watcher = newFilesInDirectoryWatcher(newAr, async (path) => {
|
|
35
|
+
await processWatcher.addFile(path);
|
|
36
|
+
}, {
|
|
37
|
+
ignoreInitial: !testProcessStarted,
|
|
38
|
+
indexDelay: 300,
|
|
39
|
+
});
|
|
40
|
+
allureResultsWatchers.set(newAr, watcher);
|
|
41
|
+
await watcher.initialScan();
|
|
42
|
+
}
|
|
43
|
+
}, { indexDelay: 600 });
|
|
44
|
+
await allureResultsWatch.initialScan();
|
|
45
|
+
testProcessStarted = true;
|
|
46
|
+
const beforeProcess = Date.now();
|
|
47
|
+
const testProcess = runProcess(command, commandArgs, cwd, environment, silent);
|
|
48
|
+
const code = await terminationOf(testProcess);
|
|
49
|
+
const afterProcess = Date.now();
|
|
50
|
+
console.log(`process finished with code ${code ?? 0} (${afterProcess - beforeProcess})ms`);
|
|
51
|
+
await allureResultsWatch.abort();
|
|
52
|
+
for (const [ar, watcher] of allureResultsWatchers) {
|
|
53
|
+
await watcher.abort();
|
|
54
|
+
allureResultsWatchers.delete(ar);
|
|
55
|
+
}
|
|
56
|
+
await processWatcher.abort();
|
|
57
|
+
};
|
|
58
|
+
export const RunCommandAction = async (options) => {
|
|
59
|
+
const args = options["--"];
|
|
60
|
+
if (!args || !args.length) {
|
|
61
|
+
throw new Error("expecting command to be specified after --, e.g. allure run -- npm run test");
|
|
62
|
+
}
|
|
63
|
+
const before = new Date().getTime();
|
|
64
|
+
process.on("exit", (code) => {
|
|
65
|
+
const after = new Date().getTime();
|
|
66
|
+
console.log(`exit code ${code} (${after - before}ms)`);
|
|
67
|
+
});
|
|
68
|
+
const command = args[0];
|
|
69
|
+
const commandArgs = args.slice(1);
|
|
70
|
+
const cwd = await realpath(options.cwd ?? process.cwd());
|
|
71
|
+
console.log(`${command} ${commandArgs.join(" ")}`);
|
|
72
|
+
const { config: configPath, output, reportName, rerun: maxRerun = 0, silent = false } = options;
|
|
73
|
+
const config = await readRuntimeConfig(configPath, cwd, output, reportName);
|
|
74
|
+
try {
|
|
75
|
+
await rm(config.output, { recursive: true });
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
if (!isFileNotFoundError(e)) {
|
|
79
|
+
console.error("could not clean output directory", e);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const allureReport = new AllureReport({
|
|
83
|
+
...config,
|
|
84
|
+
realTime: false,
|
|
85
|
+
plugins: [
|
|
86
|
+
...(config.plugins?.length
|
|
87
|
+
? config.plugins
|
|
88
|
+
: [
|
|
89
|
+
{
|
|
90
|
+
id: "awesome",
|
|
91
|
+
enabled: true,
|
|
92
|
+
options: {},
|
|
93
|
+
plugin: new AllureAwesome({
|
|
94
|
+
reportName: config.name,
|
|
95
|
+
}),
|
|
96
|
+
},
|
|
97
|
+
]),
|
|
98
|
+
],
|
|
99
|
+
});
|
|
100
|
+
await allureReport.start();
|
|
101
|
+
await runTests(allureReport, cwd, command, commandArgs, {}, silent);
|
|
102
|
+
for (let rerun = 0; rerun < maxRerun; rerun++) {
|
|
103
|
+
const failed = await allureReport.store.failedTestResults();
|
|
104
|
+
if (failed.length === 0) {
|
|
105
|
+
console.log("no failed tests is detected.");
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
const testPlan = createTestPlan(failed);
|
|
109
|
+
console.log(`rerun number ${rerun} of ${testPlan.tests.length} tests:`);
|
|
110
|
+
logTests(failed);
|
|
111
|
+
const tmpDir = await mkdtemp(join(tmpdir(), "allure-run-"));
|
|
112
|
+
const testPlanPath = resolve(tmpDir, `${rerun}-testplan.json`);
|
|
113
|
+
await writeFile(testPlanPath, JSON.stringify(testPlan));
|
|
114
|
+
await runTests(allureReport, cwd, command, commandArgs, {
|
|
115
|
+
ALLURE_TESTPLAN_PATH: testPlanPath,
|
|
116
|
+
ALLURE_RERUN: `${rerun}`,
|
|
117
|
+
}, silent);
|
|
118
|
+
await rm(tmpDir, { recursive: true });
|
|
119
|
+
logTests(await allureReport.store.allTestResults());
|
|
120
|
+
}
|
|
121
|
+
await allureReport.done();
|
|
122
|
+
await allureReport.validate();
|
|
123
|
+
process.exit(allureReport.exitCode);
|
|
124
|
+
};
|
|
125
|
+
export const RunCommand = createCommand({
|
|
126
|
+
name: "run",
|
|
127
|
+
description: "Run specified command",
|
|
128
|
+
options: [
|
|
129
|
+
[
|
|
130
|
+
"--config, -c <file>",
|
|
131
|
+
{
|
|
132
|
+
description: "The path Allure config file",
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
[
|
|
136
|
+
"--cwd <cwd>",
|
|
137
|
+
{
|
|
138
|
+
description: "The working directory for the command to run (Default: current working directory)",
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
[
|
|
142
|
+
"--output, -o <file>",
|
|
143
|
+
{
|
|
144
|
+
description: "The output file name, allure.csv by default. Accepts absolute paths (Default: ./allure-report)",
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
[
|
|
148
|
+
"--report-name, --name <string>",
|
|
149
|
+
{
|
|
150
|
+
description: "The report name (Default: Allure Report)",
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
[
|
|
154
|
+
"--rerun <number>",
|
|
155
|
+
{
|
|
156
|
+
description: "The number of reruns for failed tests (Default: 0)",
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
[
|
|
160
|
+
"--silent",
|
|
161
|
+
{
|
|
162
|
+
description: "Don't pipe the process output logs to console (Default: 0)",
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
],
|
|
166
|
+
action: RunCommandAction,
|
|
167
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { AllureReport, resolveConfig } from "@allure/core";
|
|
2
|
+
import { createCommand } from "../utils/commands.js";
|
|
3
|
+
export const SlackCommandAction = async (resultsDir, options) => {
|
|
4
|
+
const before = new Date().getTime();
|
|
5
|
+
const config = await resolveConfig({
|
|
6
|
+
plugins: {
|
|
7
|
+
"@allure/plugin-slack": {
|
|
8
|
+
options,
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
const allureReport = new AllureReport(config);
|
|
13
|
+
await allureReport.start();
|
|
14
|
+
await allureReport.readDirectory(resultsDir);
|
|
15
|
+
await allureReport.done();
|
|
16
|
+
const after = new Date().getTime();
|
|
17
|
+
console.log(`the report successfully generated (${after - before}ms)`);
|
|
18
|
+
};
|
|
19
|
+
export const SlackCommand = createCommand({
|
|
20
|
+
name: "slack <resultsDir>",
|
|
21
|
+
description: "Posts test results into Slack Channel",
|
|
22
|
+
options: [
|
|
23
|
+
[
|
|
24
|
+
"--token, -t <token>",
|
|
25
|
+
{
|
|
26
|
+
description: "Slack Bot User OAuth Token",
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
"--channel, -c <channel>",
|
|
31
|
+
{
|
|
32
|
+
description: "Slack channelId",
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
],
|
|
36
|
+
action: SlackCommandAction,
|
|
37
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { AllureReport, resolveConfig } from "@allure/core";
|
|
2
|
+
import { basename, dirname, resolve } from "node:path";
|
|
3
|
+
import { createCommand } from "../utils/commands.js";
|
|
4
|
+
export const TestPlanCommandAction = async (resultsDir, options) => {
|
|
5
|
+
const before = new Date().getTime();
|
|
6
|
+
const resolved = resolve(options.output ?? "./testplan.json");
|
|
7
|
+
const output = dirname(resolved);
|
|
8
|
+
const fileName = basename(resolved);
|
|
9
|
+
const config = await resolveConfig({
|
|
10
|
+
output: output,
|
|
11
|
+
plugins: {
|
|
12
|
+
"@allure/plugin-testplan": {
|
|
13
|
+
options: { fileName },
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
const allureReport = new AllureReport(config);
|
|
18
|
+
await allureReport.start();
|
|
19
|
+
await allureReport.readDirectory(resultsDir);
|
|
20
|
+
await allureReport.done();
|
|
21
|
+
const after = new Date().getTime();
|
|
22
|
+
console.log(`the report successfully generated (${after - before}ms)`);
|
|
23
|
+
};
|
|
24
|
+
export const TestPlanCommand = createCommand({
|
|
25
|
+
name: "testplan <resultsDir>",
|
|
26
|
+
description: "Generates testplan.json based on provided Allure Results",
|
|
27
|
+
options: [
|
|
28
|
+
[
|
|
29
|
+
"--output, -o <file>",
|
|
30
|
+
{
|
|
31
|
+
description: "The output file name. Absolute paths are accepted as well",
|
|
32
|
+
default: "testplan.json",
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
],
|
|
36
|
+
action: TestPlanCommandAction,
|
|
37
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type WatchCommandOptions = {
|
|
2
|
+
config?: string;
|
|
3
|
+
output?: string;
|
|
4
|
+
cwd?: string;
|
|
5
|
+
reportName?: string;
|
|
6
|
+
port?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const WatchCommandAction: (resultsDir: string, options: WatchCommandOptions) => Promise<void>;
|
|
9
|
+
export declare const WatchCommand: (cli: import("cac").CAC) => void;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { AllureReport, isFileNotFoundError, readRuntimeConfig } from "@allure/core";
|
|
2
|
+
import { newFilesInDirectoryWatcher } from "@allure/directory-watcher";
|
|
3
|
+
import AllureAwesome from "@allure/plugin-awesome";
|
|
4
|
+
import ProgressPlugin from "@allure/plugin-progress";
|
|
5
|
+
import ServerReloadPlugin from "@allure/plugin-server-reload";
|
|
6
|
+
import { PathResultFile } from "@allure/reader-api";
|
|
7
|
+
import { serve } from "@allure/static-server";
|
|
8
|
+
import * as console from "node:console";
|
|
9
|
+
import { rm } from "node:fs/promises";
|
|
10
|
+
import { join, resolve } from "node:path";
|
|
11
|
+
import process from "node:process";
|
|
12
|
+
import { createCommand } from "../utils/commands.js";
|
|
13
|
+
export const WatchCommandAction = async (resultsDir, options) => {
|
|
14
|
+
const before = new Date().getTime();
|
|
15
|
+
process.on("exit", (code) => {
|
|
16
|
+
const after = new Date().getTime();
|
|
17
|
+
console.log(`exit code ${code} (${after - before}ms)`);
|
|
18
|
+
});
|
|
19
|
+
const { config: configPath, output, cwd, reportName } = options;
|
|
20
|
+
const config = await readRuntimeConfig(configPath, cwd, output, reportName);
|
|
21
|
+
try {
|
|
22
|
+
await rm(config.output, { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
if (!isFileNotFoundError(e)) {
|
|
26
|
+
console.error("could not clean output directory", e);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const server = await serve({
|
|
30
|
+
servePath: config.output,
|
|
31
|
+
port: options.port ? parseInt(options.port) : undefined,
|
|
32
|
+
live: false,
|
|
33
|
+
open: false,
|
|
34
|
+
});
|
|
35
|
+
const allureReport = new AllureReport({
|
|
36
|
+
...config,
|
|
37
|
+
realTime: true,
|
|
38
|
+
plugins: [
|
|
39
|
+
...(config.plugins?.length
|
|
40
|
+
? config.plugins
|
|
41
|
+
: [
|
|
42
|
+
{
|
|
43
|
+
id: "awesome",
|
|
44
|
+
enabled: true,
|
|
45
|
+
options: {},
|
|
46
|
+
plugin: new AllureAwesome({
|
|
47
|
+
reportName: config.name,
|
|
48
|
+
}),
|
|
49
|
+
},
|
|
50
|
+
]),
|
|
51
|
+
{
|
|
52
|
+
id: "watch log",
|
|
53
|
+
enabled: true,
|
|
54
|
+
options: {},
|
|
55
|
+
plugin: new ProgressPlugin(),
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "server reload",
|
|
59
|
+
enabled: true,
|
|
60
|
+
options: {},
|
|
61
|
+
plugin: new ServerReloadPlugin({
|
|
62
|
+
server,
|
|
63
|
+
}),
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
});
|
|
67
|
+
await allureReport.start();
|
|
68
|
+
const input = resolve(resultsDir);
|
|
69
|
+
const { abort } = newFilesInDirectoryWatcher(input, async (path) => {
|
|
70
|
+
await allureReport.readResult(new PathResultFile(path));
|
|
71
|
+
});
|
|
72
|
+
const pluginIdToOpen = config.plugins?.find((plugin) => !!plugin.options.open)?.id;
|
|
73
|
+
if (pluginIdToOpen) {
|
|
74
|
+
await server.open(join(server.url, pluginIdToOpen));
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
await server.open(server.url);
|
|
78
|
+
}
|
|
79
|
+
console.info("Press Ctrl+C to exit");
|
|
80
|
+
process.on("SIGINT", async () => {
|
|
81
|
+
console.log("");
|
|
82
|
+
await abort();
|
|
83
|
+
await server.stop();
|
|
84
|
+
await allureReport.done();
|
|
85
|
+
process.exit(0);
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
export const WatchCommand = createCommand({
|
|
89
|
+
name: "watch <resultsDir>",
|
|
90
|
+
description: "Watches Allure Results changes in Real-time",
|
|
91
|
+
options: [
|
|
92
|
+
[
|
|
93
|
+
"--cwd <cwd>",
|
|
94
|
+
{
|
|
95
|
+
description: "The working directory for the command to run (default: current working directory)",
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
[
|
|
99
|
+
"--output, -o <file>",
|
|
100
|
+
{
|
|
101
|
+
description: "The output file name, allure.csv by default. Accepts absolute paths (default: ./allure-report)",
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
[
|
|
105
|
+
"--report-name, --name <string>",
|
|
106
|
+
{
|
|
107
|
+
description: "The report name (default: Allure Report)",
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
[
|
|
111
|
+
"--port <port>",
|
|
112
|
+
{
|
|
113
|
+
description: "The port to serve the reports on (default: random port)",
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
],
|
|
117
|
+
action: WatchCommandAction,
|
|
118
|
+
});
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { defineConfig } from "@allure/core";
|
|
2
|
+
import { cac } from "cac";
|
|
3
|
+
import console from "node:console";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import { cwd } from "node:process";
|
|
6
|
+
import { ClassicCommand, AwesomeCommand, CsvCommand, GenerateCommand, HistoryCommand, KnownIssueCommand, LogCommand, OpenCommand, QualityGateCommand, RunCommand, SlackCommand, TestPlanCommand, WatchCommand, } from "./commands/index.js";
|
|
7
|
+
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
8
|
+
const cli = cac(pkg.name).usage(pkg.description).help().version(pkg.version);
|
|
9
|
+
const commands = [
|
|
10
|
+
ClassicCommand,
|
|
11
|
+
AwesomeCommand,
|
|
12
|
+
CsvCommand,
|
|
13
|
+
GenerateCommand,
|
|
14
|
+
HistoryCommand,
|
|
15
|
+
KnownIssueCommand,
|
|
16
|
+
LogCommand,
|
|
17
|
+
OpenCommand,
|
|
18
|
+
QualityGateCommand,
|
|
19
|
+
RunCommand,
|
|
20
|
+
SlackCommand,
|
|
21
|
+
TestPlanCommand,
|
|
22
|
+
WatchCommand,
|
|
23
|
+
];
|
|
24
|
+
commands.forEach((command) => {
|
|
25
|
+
command(cli);
|
|
26
|
+
});
|
|
27
|
+
cli.on("command:*", () => {
|
|
28
|
+
console.error("Invalid command: %s", cli.args.join(" "));
|
|
29
|
+
process.exit(1);
|
|
30
|
+
});
|
|
31
|
+
console.log(cwd());
|
|
32
|
+
cli.parse();
|
|
33
|
+
export { defineConfig };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CAC } from "cac";
|
|
2
|
+
export type OptionDescription = [string] | [
|
|
3
|
+
string,
|
|
4
|
+
{
|
|
5
|
+
description?: string;
|
|
6
|
+
type?: any[];
|
|
7
|
+
default?: any;
|
|
8
|
+
}
|
|
9
|
+
];
|
|
10
|
+
export type CreateCommandOptions = {
|
|
11
|
+
name: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
options?: OptionDescription[];
|
|
14
|
+
action: (...args: any[]) => Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
export declare const createCommand: (payload: CreateCommandOptions) => (cli: CAC) => void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const createCommand = (payload) => {
|
|
2
|
+
if (!payload.name)
|
|
3
|
+
throw new Error("Command name is not provided!");
|
|
4
|
+
if (!payload.action)
|
|
5
|
+
throw new Error("Command action is not provided!");
|
|
6
|
+
return (cli) => {
|
|
7
|
+
const command = cli.command(payload.name, payload.description);
|
|
8
|
+
payload?.options?.forEach(([name, parameters]) => {
|
|
9
|
+
const { description = "", ...rest } = parameters || {};
|
|
10
|
+
command.option(name, description, rest);
|
|
11
|
+
});
|
|
12
|
+
command.action(payload.action);
|
|
13
|
+
};
|
|
14
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { ChildProcess } from "node:child_process";
|
|
2
|
+
export declare const runProcess: (command: string, commandArgs: string[], cwd: string | undefined, environment: Record<string, string>, silent?: boolean) => ChildProcess;
|
|
3
|
+
export declare const terminationOf: (testProcess: ChildProcess) => Promise<number | null>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
export const runProcess = (command, commandArgs, cwd, environment, silent) => {
|
|
3
|
+
return spawn(command, commandArgs, {
|
|
4
|
+
env: {
|
|
5
|
+
...process.env,
|
|
6
|
+
...environment,
|
|
7
|
+
},
|
|
8
|
+
cwd,
|
|
9
|
+
stdio: silent ? "ignore" : "inherit",
|
|
10
|
+
shell: true,
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
export const terminationOf = (testProcess) => new Promise((resolve) => {
|
|
14
|
+
testProcess.on("exit", (code) => resolve(code));
|
|
15
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { formatDuration } from "@allure/core-api";
|
|
2
|
+
import console from "node:console";
|
|
3
|
+
import { blue, gray, green, red, yellow } from "yoctocolors";
|
|
4
|
+
export const status2color = (status) => {
|
|
5
|
+
switch (status) {
|
|
6
|
+
case "failed":
|
|
7
|
+
return red;
|
|
8
|
+
case "broken":
|
|
9
|
+
return yellow;
|
|
10
|
+
case "passed":
|
|
11
|
+
return green;
|
|
12
|
+
case "skipped":
|
|
13
|
+
return gray;
|
|
14
|
+
default:
|
|
15
|
+
return blue;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
export const logTests = (testResults) => {
|
|
19
|
+
testResults.forEach((tr) => console.log(`${tr.fullName} ${status2color(tr.status)(tr.status)} ${tr.duration !== undefined ? gray(`(${formatDuration(tr.duration)})`) : ""}`));
|
|
20
|
+
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,64 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "allure",
|
|
3
|
-
"version": "0.0.0",
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
3
|
+
"version": "3.0.0-beta.0",
|
|
4
|
+
"description": "Allure Commandline Tool",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"allure",
|
|
7
|
+
"testing",
|
|
8
|
+
"report"
|
|
9
|
+
],
|
|
10
|
+
"repository": "https://github.com/allure-framework/allure3",
|
|
11
|
+
"license": "Apache-2.0",
|
|
12
|
+
"author": "Qameta Software",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"module": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"bin": "./cli.js",
|
|
21
|
+
"files": [
|
|
22
|
+
"./dist"
|
|
23
|
+
],
|
|
6
24
|
"scripts": {
|
|
7
|
-
"
|
|
25
|
+
"build": "run clean && tsc --project ./tsconfig.json",
|
|
26
|
+
"clean": "rimraf ./dist",
|
|
27
|
+
"start": "node ./cli.js",
|
|
28
|
+
"test": "vitest run"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@allure/core": "3.0.0-beta.0",
|
|
32
|
+
"@allure/core-api": "3.0.0-beta.0",
|
|
33
|
+
"@allure/directory-watcher": "3.0.0-beta.0",
|
|
34
|
+
"@allure/plugin-awesome": "3.0.0-beta.0",
|
|
35
|
+
"@allure/plugin-progress": "3.0.0-beta.0",
|
|
36
|
+
"@allure/plugin-server-reload": "3.0.0-beta.0",
|
|
37
|
+
"@allure/plugin-slack": "3.0.0-beta.0",
|
|
38
|
+
"@allure/reader-api": "3.0.0-beta.0",
|
|
39
|
+
"@allure/static-server": "3.0.0-beta.0",
|
|
40
|
+
"cac": "^6.7.14",
|
|
41
|
+
"lodash.omit": "^4.5.0",
|
|
42
|
+
"yoctocolors": "^2.1.1"
|
|
8
43
|
},
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@stylistic/eslint-plugin": "^2.6.1",
|
|
46
|
+
"@types/eslint": "^8.56.11",
|
|
47
|
+
"@types/lodash.omit": "^4.5.9",
|
|
48
|
+
"@types/node": "^20.17.9",
|
|
49
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
50
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
51
|
+
"@vitest/runner": "^2.1.8",
|
|
52
|
+
"allure-vitest": "^3.0.7",
|
|
53
|
+
"eslint": "^8.57.0",
|
|
54
|
+
"eslint-config-prettier": "^9.1.0",
|
|
55
|
+
"eslint-plugin-import": "^2.29.1",
|
|
56
|
+
"eslint-plugin-jsdoc": "^50.0.0",
|
|
57
|
+
"eslint-plugin-n": "^17.10.1",
|
|
58
|
+
"eslint-plugin-no-null": "^1.0.2",
|
|
59
|
+
"eslint-plugin-prefer-arrow": "^1.2.3",
|
|
60
|
+
"rimraf": "^6.0.1",
|
|
61
|
+
"typescript": "^5.6.3",
|
|
62
|
+
"vitest": "^2.1.8"
|
|
63
|
+
}
|
|
64
|
+
}
|