@allurereport/core 3.0.0-beta.15 → 3.0.0-beta.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.d.ts +6 -2
- package/dist/config.d.ts +7 -5
- package/dist/config.js +8 -5
- package/dist/history.d.ts +8 -3
- package/dist/history.js +34 -19
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -1
- package/dist/plugin.d.ts +6 -5
- package/dist/plugin.js +7 -2
- package/dist/report.d.ts +2 -0
- package/dist/report.js +110 -27
- package/dist/store/convert.js +37 -16
- package/dist/store/store.d.ts +6 -2
- package/dist/store/store.js +64 -9
- package/dist/utils/flaky.js +1 -1
- package/dist/utils/git.d.ts +2 -0
- package/dist/utils/git.js +46 -0
- package/dist/utils/new.d.ts +4 -0
- package/dist/utils/new.js +23 -0
- package/dist/utils/stats.js +3 -0
- package/package.json +22 -20
package/dist/api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DefaultLabelsConfig, EnvironmentsConfig,
|
|
1
|
+
import type { DefaultLabelsConfig, EnvironmentsConfig, KnownTestFailure, ReportVariables } from "@allurereport/core-api";
|
|
2
2
|
import type { Plugin, QualityGateConfig, ReportFiles } from "@allurereport/plugin-api";
|
|
3
3
|
import type { ResultsReader } from "@allurereport/reader-api";
|
|
4
4
|
export interface PluginInstance {
|
|
@@ -19,8 +19,12 @@ export interface FullConfig {
|
|
|
19
19
|
reportFiles: ReportFiles;
|
|
20
20
|
readers?: ResultsReader[];
|
|
21
21
|
plugins?: PluginInstance[];
|
|
22
|
-
history: HistoryDataPoint[];
|
|
23
22
|
appendHistory?: boolean;
|
|
24
23
|
known?: KnownTestFailure[];
|
|
25
24
|
realTime?: any;
|
|
25
|
+
allureService?: {
|
|
26
|
+
url?: string;
|
|
27
|
+
project?: string;
|
|
28
|
+
accessToken?: string;
|
|
29
|
+
};
|
|
26
30
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { Config } from "@allurereport/plugin-api";
|
|
2
|
-
import type { FullConfig } from "./api.js";
|
|
2
|
+
import type { FullConfig, PluginInstance } from "./api.js";
|
|
3
3
|
export declare const getPluginId: (key: string) => string;
|
|
4
4
|
export declare const findConfig: (cwd: string, configPath?: string) => Promise<string | undefined>;
|
|
5
5
|
export interface ConfigOverride {
|
|
6
|
-
name?:
|
|
7
|
-
output?:
|
|
8
|
-
historyPath?:
|
|
9
|
-
knownIssuesPath?:
|
|
6
|
+
name?: Config["name"];
|
|
7
|
+
output?: Config["output"];
|
|
8
|
+
historyPath?: Config["historyPath"];
|
|
9
|
+
knownIssuesPath?: Config["knownIssuesPath"];
|
|
10
|
+
plugins?: Config["plugins"];
|
|
10
11
|
}
|
|
11
12
|
export declare const validateConfig: (config: Config) => {
|
|
12
13
|
valid: boolean;
|
|
@@ -15,4 +16,5 @@ export declare const validateConfig: (config: Config) => {
|
|
|
15
16
|
export declare const loadConfig: (configPath: string) => Promise<Config>;
|
|
16
17
|
export declare const resolveConfig: (config: Config, override?: ConfigOverride) => Promise<FullConfig>;
|
|
17
18
|
export declare const readConfig: (cwd?: string, configPath?: string, override?: ConfigOverride) => Promise<FullConfig>;
|
|
19
|
+
export declare const getPluginInstance: (config: FullConfig, predicate: (plugin: PluginInstance) => boolean) => PluginInstance | undefined;
|
|
18
20
|
export declare const resolvePlugin: (path: string) => Promise<any>;
|
package/dist/config.js
CHANGED
|
@@ -2,7 +2,6 @@ import * as console from "node:console";
|
|
|
2
2
|
import { stat } from "node:fs/promises";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import * as process from "node:process";
|
|
5
|
-
import { readHistory } from "./history.js";
|
|
6
5
|
import { readKnownIssues } from "./known.js";
|
|
7
6
|
import { FileSystemReportFiles } from "./plugin.js";
|
|
8
7
|
import { importWrapper } from "./utils/module.js";
|
|
@@ -50,6 +49,7 @@ export const validateConfig = (config) => {
|
|
|
50
49
|
"variables",
|
|
51
50
|
"environments",
|
|
52
51
|
"appendHistory",
|
|
52
|
+
"allureService",
|
|
53
53
|
];
|
|
54
54
|
const unsupportedFields = Object.keys(config).filter((key) => !supportedFields.includes(key));
|
|
55
55
|
return {
|
|
@@ -70,11 +70,10 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
70
70
|
const appendHistory = config.appendHistory ?? true;
|
|
71
71
|
const knownIssuesPath = resolve(override.knownIssuesPath ?? config.knownIssuesPath ?? "./allure/known.json");
|
|
72
72
|
const output = resolve(override.output ?? config.output ?? "./allure-report");
|
|
73
|
-
const history = await readHistory(historyPath);
|
|
74
73
|
const known = await readKnownIssues(knownIssuesPath);
|
|
75
74
|
const variables = config.variables ?? {};
|
|
76
75
|
const environments = config.environments ?? {};
|
|
77
|
-
const plugins = Object.keys(config?.plugins ?? {}).length === 0
|
|
76
|
+
const plugins = Object.keys(override?.plugins ?? config?.plugins ?? {}).length === 0
|
|
78
77
|
? {
|
|
79
78
|
awesome: {
|
|
80
79
|
options: {},
|
|
@@ -85,7 +84,6 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
85
84
|
return {
|
|
86
85
|
name,
|
|
87
86
|
output,
|
|
88
|
-
history,
|
|
89
87
|
historyPath,
|
|
90
88
|
knownIssuesPath,
|
|
91
89
|
known,
|
|
@@ -95,6 +93,7 @@ export const resolveConfig = async (config, override = {}) => {
|
|
|
95
93
|
reportFiles: new FileSystemReportFiles(output),
|
|
96
94
|
plugins: pluginInstances,
|
|
97
95
|
qualityGate: config.qualityGate,
|
|
96
|
+
allureService: config.allureService,
|
|
98
97
|
};
|
|
99
98
|
};
|
|
100
99
|
export const readConfig = async (cwd = process.cwd(), configPath, override) => {
|
|
@@ -102,6 +101,9 @@ export const readConfig = async (cwd = process.cwd(), configPath, override) => {
|
|
|
102
101
|
const config = cfg ? await loadConfig(cfg) : { ...defaultConfig };
|
|
103
102
|
return await resolveConfig(config, override);
|
|
104
103
|
};
|
|
104
|
+
export const getPluginInstance = (config, predicate) => {
|
|
105
|
+
return config?.plugins?.find(predicate);
|
|
106
|
+
};
|
|
105
107
|
export const resolvePlugin = async (path) => {
|
|
106
108
|
if (!path.startsWith("@allurereport/plugin-")) {
|
|
107
109
|
try {
|
|
@@ -122,9 +124,10 @@ const resolvePlugins = async (plugins) => {
|
|
|
122
124
|
const pluginInstances = [];
|
|
123
125
|
for (const id in plugins) {
|
|
124
126
|
const pluginConfig = plugins[id];
|
|
127
|
+
const pluginId = getPluginId(id);
|
|
125
128
|
const Plugin = await resolvePlugin(pluginConfig.import ?? id);
|
|
126
129
|
pluginInstances.push({
|
|
127
|
-
id:
|
|
130
|
+
id: pluginId,
|
|
128
131
|
enabled: pluginConfig.enabled ?? true,
|
|
129
132
|
options: pluginConfig.options ?? {},
|
|
130
133
|
plugin: new Plugin(pluginConfig.options),
|
package/dist/history.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type { HistoryDataPoint, TestCase, TestResult } from "@allurereport/core-api";
|
|
2
|
-
export declare const createHistory: (reportUuid: string, reportName: string | undefined, testCases: TestCase[], testResults: TestResult[]) => HistoryDataPoint;
|
|
3
|
-
export declare const readHistory: (historyPath: string) => Promise<HistoryDataPoint[]>;
|
|
1
|
+
import type { AllureHistory, HistoryDataPoint, TestCase, TestResult } from "@allurereport/core-api";
|
|
2
|
+
export declare const createHistory: (reportUuid: string, reportName: string | undefined, testCases: TestCase[], testResults: TestResult[], remoteUrl?: string) => HistoryDataPoint;
|
|
4
3
|
export declare const writeHistory: (historyPath: string, data: HistoryDataPoint) => Promise<void>;
|
|
4
|
+
export declare class AllureLocalHistory implements AllureHistory {
|
|
5
|
+
private readonly historyPath;
|
|
6
|
+
constructor(historyPath: string);
|
|
7
|
+
readHistory(): Promise<HistoryDataPoint[]>;
|
|
8
|
+
appendHistory(data: HistoryDataPoint): Promise<void>;
|
|
9
|
+
}
|
package/dist/history.js
CHANGED
|
@@ -20,12 +20,15 @@ const createHistoryItems = (testResults) => {
|
|
|
20
20
|
reportLinks: [],
|
|
21
21
|
};
|
|
22
22
|
})
|
|
23
|
-
.reduce((
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
.reduce((acc, item) => {
|
|
24
|
+
acc[item.historyId] = {
|
|
25
|
+
...item,
|
|
26
|
+
url: "",
|
|
27
|
+
};
|
|
28
|
+
return acc;
|
|
26
29
|
}, {});
|
|
27
30
|
};
|
|
28
|
-
export const createHistory = (reportUuid, reportName = "Allure Report", testCases, testResults) => {
|
|
31
|
+
export const createHistory = (reportUuid, reportName = "Allure Report", testCases, testResults, remoteUrl = "") => {
|
|
29
32
|
const knownTestCaseIds = testCases.map((tc) => tc.id);
|
|
30
33
|
return {
|
|
31
34
|
uuid: reportUuid,
|
|
@@ -34,26 +37,38 @@ export const createHistory = (reportUuid, reportName = "Allure Report", testCase
|
|
|
34
37
|
knownTestCaseIds,
|
|
35
38
|
testResults: createHistoryItems(testResults),
|
|
36
39
|
metrics: {},
|
|
40
|
+
url: remoteUrl,
|
|
37
41
|
};
|
|
38
42
|
};
|
|
39
|
-
export const readHistory = async (historyPath) => {
|
|
40
|
-
const path = resolve(historyPath);
|
|
41
|
-
try {
|
|
42
|
-
return (await readFile(path, { encoding: "utf-8" }))
|
|
43
|
-
.split("\n")
|
|
44
|
-
.filter((line) => line && line.trim() !== "")
|
|
45
|
-
.map((line) => JSON.parse(line));
|
|
46
|
-
}
|
|
47
|
-
catch (e) {
|
|
48
|
-
if (isFileNotFoundError(e)) {
|
|
49
|
-
return [];
|
|
50
|
-
}
|
|
51
|
-
throw e;
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
43
|
export const writeHistory = async (historyPath, data) => {
|
|
55
44
|
const path = resolve(historyPath);
|
|
56
45
|
const parentDir = dirname(path);
|
|
57
46
|
await mkdir(parentDir, { recursive: true });
|
|
58
47
|
await writeFile(path, `${JSON.stringify(data)}\n`, { encoding: "utf-8", flag: "a+" });
|
|
59
48
|
};
|
|
49
|
+
export class AllureLocalHistory {
|
|
50
|
+
constructor(historyPath) {
|
|
51
|
+
this.historyPath = historyPath;
|
|
52
|
+
}
|
|
53
|
+
async readHistory() {
|
|
54
|
+
const path = resolve(this.historyPath);
|
|
55
|
+
try {
|
|
56
|
+
return (await readFile(path, { encoding: "utf-8" }))
|
|
57
|
+
.split("\n")
|
|
58
|
+
.filter((line) => line && line.trim() !== "")
|
|
59
|
+
.map((line) => JSON.parse(line));
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
if (isFileNotFoundError(e)) {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
throw e;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async appendHistory(data) {
|
|
69
|
+
const path = resolve(this.historyPath);
|
|
70
|
+
const parentDir = dirname(path);
|
|
71
|
+
await mkdir(parentDir, { recursive: true });
|
|
72
|
+
await writeFile(path, `${JSON.stringify(data)}\n`, { encoding: "utf-8", flag: "a+" });
|
|
73
|
+
}
|
|
74
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,9 +3,12 @@ export * from "./utils/misc.js";
|
|
|
3
3
|
export * from "./utils/crypto.js";
|
|
4
4
|
export * from "./utils/path.js";
|
|
5
5
|
export * from "./utils/stats.js";
|
|
6
|
+
export * from "./utils/git.js";
|
|
7
|
+
export * from "./utils/new.js";
|
|
8
|
+
export * from "./utils/flaky.js";
|
|
6
9
|
export * from "./history.js";
|
|
7
10
|
export * from "./known.js";
|
|
8
|
-
export { resolveConfig, readConfig } from "./config.js";
|
|
11
|
+
export { resolveConfig, readConfig, getPluginInstance } from "./config.js";
|
|
9
12
|
export * from "./report.js";
|
|
10
13
|
export * from "./plugin.js";
|
|
11
14
|
export * from "./qualityGate.js";
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,12 @@ export * from "./utils/misc.js";
|
|
|
2
2
|
export * from "./utils/crypto.js";
|
|
3
3
|
export * from "./utils/path.js";
|
|
4
4
|
export * from "./utils/stats.js";
|
|
5
|
+
export * from "./utils/git.js";
|
|
6
|
+
export * from "./utils/new.js";
|
|
7
|
+
export * from "./utils/flaky.js";
|
|
5
8
|
export * from "./history.js";
|
|
6
9
|
export * from "./known.js";
|
|
7
|
-
export { resolveConfig, readConfig } from "./config.js";
|
|
10
|
+
export { resolveConfig, readConfig, getPluginInstance } from "./config.js";
|
|
8
11
|
export * from "./report.js";
|
|
9
12
|
export * from "./plugin.js";
|
|
10
13
|
export * from "./qualityGate.js";
|
package/dist/plugin.d.ts
CHANGED
|
@@ -3,20 +3,21 @@ export declare class DefaultPluginState implements PluginState {
|
|
|
3
3
|
#private;
|
|
4
4
|
constructor(state: Record<string, any>);
|
|
5
5
|
set: (key: string, value: any) => Promise<void>;
|
|
6
|
-
get: (key: string) => Promise<
|
|
6
|
+
get: <T>(key: string) => Promise<T>;
|
|
7
7
|
unset: (key: string) => Promise<void>;
|
|
8
8
|
}
|
|
9
9
|
export declare class PluginFiles implements ReportFiles {
|
|
10
10
|
#private;
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
readonly callback?: ((key: string, path: string) => void) | undefined;
|
|
12
|
+
constructor(parent: ReportFiles, pluginId: string, callback?: ((key: string, path: string) => void) | undefined);
|
|
13
|
+
addFile: (key: string, data: Buffer) => Promise<string>;
|
|
13
14
|
}
|
|
14
15
|
export declare class InMemoryReportFiles implements ReportFiles {
|
|
15
16
|
#private;
|
|
16
|
-
addFile: (path: string, data: Buffer) => Promise<
|
|
17
|
+
addFile: (path: string, data: Buffer) => Promise<string>;
|
|
17
18
|
}
|
|
18
19
|
export declare class FileSystemReportFiles implements ReportFiles {
|
|
19
20
|
#private;
|
|
20
21
|
constructor(output: string);
|
|
21
|
-
addFile: (path: string, data: Buffer) => Promise<
|
|
22
|
+
addFile: (path: string, data: Buffer) => Promise<string>;
|
|
22
23
|
}
|
package/dist/plugin.js
CHANGED
|
@@ -30,11 +30,14 @@ export class DefaultPluginState {
|
|
|
30
30
|
}
|
|
31
31
|
_DefaultPluginState_state = new WeakMap();
|
|
32
32
|
export class PluginFiles {
|
|
33
|
-
constructor(parent, pluginId) {
|
|
33
|
+
constructor(parent, pluginId, callback) {
|
|
34
|
+
this.callback = callback;
|
|
34
35
|
_PluginFiles_parent.set(this, void 0);
|
|
35
36
|
_PluginFiles_pluginId.set(this, void 0);
|
|
36
37
|
this.addFile = async (key, data) => {
|
|
37
|
-
await __classPrivateFieldGet(this, _PluginFiles_parent, "f").addFile(joinPosix(__classPrivateFieldGet(this, _PluginFiles_pluginId, "f"), key), data);
|
|
38
|
+
const filepath = await __classPrivateFieldGet(this, _PluginFiles_parent, "f").addFile(joinPosix(__classPrivateFieldGet(this, _PluginFiles_pluginId, "f"), key), data);
|
|
39
|
+
this.callback?.(key, filepath);
|
|
40
|
+
return filepath;
|
|
38
41
|
};
|
|
39
42
|
__classPrivateFieldSet(this, _PluginFiles_parent, parent, "f");
|
|
40
43
|
__classPrivateFieldSet(this, _PluginFiles_pluginId, pluginId, "f");
|
|
@@ -46,6 +49,7 @@ export class InMemoryReportFiles {
|
|
|
46
49
|
_InMemoryReportFiles_state.set(this, {});
|
|
47
50
|
this.addFile = async (path, data) => {
|
|
48
51
|
__classPrivateFieldGet(this, _InMemoryReportFiles_state, "f")[path] = data;
|
|
52
|
+
return path;
|
|
49
53
|
};
|
|
50
54
|
}
|
|
51
55
|
}
|
|
@@ -58,6 +62,7 @@ export class FileSystemReportFiles {
|
|
|
58
62
|
const targetDirPath = dirname(targetPath);
|
|
59
63
|
await mkdir(targetDirPath, { recursive: true });
|
|
60
64
|
await writeFile(targetPath, data, { encoding: "utf-8" });
|
|
65
|
+
return targetPath;
|
|
61
66
|
};
|
|
62
67
|
__classPrivateFieldSet(this, _FileSystemReportFiles_output, resolve(output), "f");
|
|
63
68
|
}
|
package/dist/report.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ import type { FullConfig } from "./api.js";
|
|
|
3
3
|
import { DefaultAllureStore } from "./store/store.js";
|
|
4
4
|
export declare class AllureReport {
|
|
5
5
|
#private;
|
|
6
|
+
readonly reportUuid: string;
|
|
7
|
+
reportUrl?: string;
|
|
6
8
|
constructor(opts: FullConfig);
|
|
7
9
|
get store(): DefaultAllureStore;
|
|
8
10
|
get exitCode(): 0 | 1;
|
package/dist/report.js
CHANGED
|
@@ -9,9 +9,11 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _AllureReport_instances,
|
|
12
|
+
var _AllureReport_instances, _AllureReport_reportName, _AllureReport_ci, _AllureReport_store, _AllureReport_readers, _AllureReport_plugins, _AllureReport_reportFiles, _AllureReport_eventEmitter, _AllureReport_events, _AllureReport_qualityGate, _AllureReport_realTime, _AllureReport_output, _AllureReport_history, _AllureReport_allureServiceClient, _AllureReport_state, _AllureReport_stage, _AllureReport_publish_get, _AllureReport_update, _AllureReport_eachPlugin, _AllureReport_getPluginState;
|
|
13
|
+
import { detect } from "@allurereport/ci";
|
|
13
14
|
import { allure1, allure2, attachments, cucumberjson, junitXml, readXcResultBundle } from "@allurereport/reader";
|
|
14
15
|
import { PathResultFile } from "@allurereport/reader-api";
|
|
16
|
+
import { AllureRemoteHistory, AllureServiceClient, KnownError, UnknownError } from "@allurereport/service";
|
|
15
17
|
import { generateSummary } from "@allurereport/summary";
|
|
16
18
|
import console from "node:console";
|
|
17
19
|
import { randomUUID } from "node:crypto";
|
|
@@ -19,7 +21,7 @@ import { EventEmitter } from "node:events";
|
|
|
19
21
|
import { readFileSync } from "node:fs";
|
|
20
22
|
import { lstat, opendir, readdir, realpath, rename, rm } from "node:fs/promises";
|
|
21
23
|
import { dirname, join, resolve } from "node:path";
|
|
22
|
-
import {
|
|
24
|
+
import { AllureLocalHistory, createHistory } from "./history.js";
|
|
23
25
|
import { DefaultPluginState, PluginFiles } from "./plugin.js";
|
|
24
26
|
import { QualityGate } from "./qualityGate.js";
|
|
25
27
|
import { DefaultAllureStore } from "./store/store.js";
|
|
@@ -29,8 +31,8 @@ const initRequired = "report is not initialised. Call the start() method first."
|
|
|
29
31
|
export class AllureReport {
|
|
30
32
|
constructor(opts) {
|
|
31
33
|
_AllureReport_instances.add(this);
|
|
32
|
-
_AllureReport_reportUuid.set(this, void 0);
|
|
33
34
|
_AllureReport_reportName.set(this, void 0);
|
|
35
|
+
_AllureReport_ci.set(this, void 0);
|
|
34
36
|
_AllureReport_store.set(this, void 0);
|
|
35
37
|
_AllureReport_readers.set(this, void 0);
|
|
36
38
|
_AllureReport_plugins.set(this, void 0);
|
|
@@ -38,10 +40,10 @@ export class AllureReport {
|
|
|
38
40
|
_AllureReport_eventEmitter.set(this, void 0);
|
|
39
41
|
_AllureReport_events.set(this, void 0);
|
|
40
42
|
_AllureReport_qualityGate.set(this, void 0);
|
|
41
|
-
_AllureReport_appendHistory.set(this, void 0);
|
|
42
|
-
_AllureReport_historyPath.set(this, void 0);
|
|
43
43
|
_AllureReport_realTime.set(this, void 0);
|
|
44
44
|
_AllureReport_output.set(this, void 0);
|
|
45
|
+
_AllureReport_history.set(this, void 0);
|
|
46
|
+
_AllureReport_allureServiceClient.set(this, void 0);
|
|
45
47
|
_AllureReport_state.set(this, void 0);
|
|
46
48
|
_AllureReport_stage.set(this, "init");
|
|
47
49
|
this.readDirectory = async (resultsDir) => {
|
|
@@ -86,6 +88,7 @@ export class AllureReport {
|
|
|
86
88
|
}
|
|
87
89
|
};
|
|
88
90
|
this.start = async () => {
|
|
91
|
+
await __classPrivateFieldGet(this, _AllureReport_store, "f").readHistory();
|
|
89
92
|
if (__classPrivateFieldGet(this, _AllureReport_stage, "f") === "running") {
|
|
90
93
|
throw new Error("the report is already started");
|
|
91
94
|
}
|
|
@@ -93,6 +96,13 @@ export class AllureReport {
|
|
|
93
96
|
throw new Error("the report is already stopped, the restart isn't supported at the moment");
|
|
94
97
|
}
|
|
95
98
|
__classPrivateFieldSet(this, _AllureReport_stage, "running", "f");
|
|
99
|
+
if (__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f") && __classPrivateFieldGet(this, _AllureReport_instances, "a", _AllureReport_publish_get)) {
|
|
100
|
+
const { url } = await __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f").createReport({
|
|
101
|
+
reportUuid: this.reportUuid,
|
|
102
|
+
reportName: __classPrivateFieldGet(this, _AllureReport_reportName, "f"),
|
|
103
|
+
});
|
|
104
|
+
this.reportUrl = url;
|
|
105
|
+
}
|
|
96
106
|
await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, true, async (plugin, context) => {
|
|
97
107
|
await plugin.start?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"), __classPrivateFieldGet(this, _AllureReport_events, "f"));
|
|
98
108
|
});
|
|
@@ -113,27 +123,53 @@ export class AllureReport {
|
|
|
113
123
|
});
|
|
114
124
|
this.done = async () => {
|
|
115
125
|
const summaries = [];
|
|
126
|
+
const remoteHrefs = [];
|
|
116
127
|
if (__classPrivateFieldGet(this, _AllureReport_stage, "f") !== "running") {
|
|
117
128
|
throw new Error(initRequired);
|
|
118
129
|
}
|
|
119
130
|
__classPrivateFieldGet(this, _AllureReport_events, "f").offAll();
|
|
120
131
|
__classPrivateFieldSet(this, _AllureReport_stage, "done", "f");
|
|
121
|
-
await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, false, async (plugin, context
|
|
132
|
+
await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, false, async (plugin, context) => {
|
|
122
133
|
await plugin.done?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"));
|
|
134
|
+
if (__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f") && context.publish) {
|
|
135
|
+
const pluginFiles = (await context.state.get("files")) ?? {};
|
|
136
|
+
for (const [filename, filepath] of Object.entries(pluginFiles)) {
|
|
137
|
+
if (/^(data|widgets|index\.html$)/.test(filename)) {
|
|
138
|
+
await __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f").addReportFile({
|
|
139
|
+
reportUuid: this.reportUuid,
|
|
140
|
+
pluginId: context.id,
|
|
141
|
+
filename,
|
|
142
|
+
filepath,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
await __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f").addReportAsset({
|
|
147
|
+
filename,
|
|
148
|
+
filepath,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
123
153
|
const summary = await plugin?.info?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"));
|
|
124
154
|
if (!summary) {
|
|
125
155
|
return;
|
|
126
156
|
}
|
|
157
|
+
summary.pullRequestHref = __classPrivateFieldGet(this, _AllureReport_ci, "f")?.pullRequestUrl;
|
|
158
|
+
summary.jobHref = __classPrivateFieldGet(this, _AllureReport_ci, "f")?.jobUrl;
|
|
159
|
+
if (context.publish) {
|
|
160
|
+
summary.remoteHref = `${this.reportUrl}/${context.id}/`;
|
|
161
|
+
remoteHrefs.push(summary.remoteHref);
|
|
162
|
+
}
|
|
127
163
|
summaries.push({
|
|
128
164
|
...summary,
|
|
129
|
-
href: `${id}/`,
|
|
165
|
+
href: `${context.id}/`,
|
|
130
166
|
});
|
|
167
|
+
await context.reportFiles.addFile("summary.json", Buffer.from(JSON.stringify(summary)));
|
|
131
168
|
});
|
|
132
|
-
if (__classPrivateFieldGet(this,
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
await writeHistory(__classPrivateFieldGet(this, _AllureReport_historyPath, "f"), historyDataPoint);
|
|
169
|
+
if (__classPrivateFieldGet(this, _AllureReport_instances, "a", _AllureReport_publish_get)) {
|
|
170
|
+
await __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f")?.completeReport({
|
|
171
|
+
reportUuid: this.reportUuid,
|
|
172
|
+
});
|
|
137
173
|
}
|
|
138
174
|
const outputDirFiles = await readdir(__classPrivateFieldGet(this, _AllureReport_output, "f"));
|
|
139
175
|
if (outputDirFiles.length === 0) {
|
|
@@ -150,37 +186,72 @@ export class AllureReport {
|
|
|
150
186
|
await rename(currentFilePath, newFilePath);
|
|
151
187
|
}
|
|
152
188
|
await rm(reportPath, { recursive: true });
|
|
153
|
-
|
|
189
|
+
}
|
|
190
|
+
if (__classPrivateFieldGet(this, _AllureReport_history, "f")) {
|
|
191
|
+
const testResults = await __classPrivateFieldGet(this, _AllureReport_store, "f").allTestResults();
|
|
192
|
+
const testCases = await __classPrivateFieldGet(this, _AllureReport_store, "f").allTestCases();
|
|
193
|
+
const historyDataPoint = createHistory(this.reportUuid, __classPrivateFieldGet(this, _AllureReport_reportName, "f"), testCases, testResults, this.reportUrl);
|
|
194
|
+
try {
|
|
195
|
+
await __classPrivateFieldGet(this, _AllureReport_store, "f").appendHistory(historyDataPoint);
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
if (err instanceof KnownError) {
|
|
199
|
+
console.error("Failed to append history", err.message);
|
|
200
|
+
}
|
|
201
|
+
else if (err instanceof UnknownError) {
|
|
202
|
+
console.error("Failed to append history due to unexpected error", err.message);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
throw err;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
154
208
|
}
|
|
155
209
|
if (summaries.length > 1) {
|
|
156
210
|
await generateSummary(__classPrivateFieldGet(this, _AllureReport_output, "f"), summaries);
|
|
157
211
|
}
|
|
212
|
+
if (remoteHrefs.length > 0) {
|
|
213
|
+
console.info("Next reports have been published:");
|
|
214
|
+
remoteHrefs.forEach((href) => {
|
|
215
|
+
console.info(`- ${href}`);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
158
218
|
};
|
|
159
219
|
_AllureReport_eachPlugin.set(this, async (initState, consumer) => {
|
|
160
220
|
if (initState) {
|
|
161
221
|
__classPrivateFieldSet(this, _AllureReport_state, {}, "f");
|
|
162
222
|
}
|
|
163
|
-
for (const
|
|
164
|
-
if (!
|
|
223
|
+
for (const { enabled, id, plugin, options } of __classPrivateFieldGet(this, _AllureReport_plugins, "f")) {
|
|
224
|
+
if (!enabled) {
|
|
165
225
|
continue;
|
|
166
226
|
}
|
|
167
|
-
const id = descriptor.id;
|
|
168
|
-
const plugin = descriptor.plugin;
|
|
169
227
|
const pluginState = __classPrivateFieldGet(this, _AllureReport_instances, "m", _AllureReport_getPluginState).call(this, initState, id);
|
|
170
228
|
if (!pluginState) {
|
|
171
229
|
console.error("plugin error: state is empty");
|
|
172
230
|
continue;
|
|
173
231
|
}
|
|
174
|
-
|
|
232
|
+
if (initState) {
|
|
233
|
+
await pluginState.set("files", {});
|
|
234
|
+
}
|
|
235
|
+
const pluginFiles = new PluginFiles(__classPrivateFieldGet(this, _AllureReport_reportFiles, "f"), id, async (key, filepath) => {
|
|
236
|
+
const currentPluginState = __classPrivateFieldGet(this, _AllureReport_instances, "m", _AllureReport_getPluginState).call(this, false, id);
|
|
237
|
+
const files = await currentPluginState?.get("files");
|
|
238
|
+
if (!files) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
files[key] = filepath;
|
|
242
|
+
});
|
|
175
243
|
const pluginContext = {
|
|
244
|
+
id,
|
|
245
|
+
publish: !!options?.publish,
|
|
176
246
|
allureVersion: version,
|
|
177
|
-
reportUuid:
|
|
247
|
+
reportUuid: this.reportUuid,
|
|
178
248
|
reportName: __classPrivateFieldGet(this, _AllureReport_reportName, "f"),
|
|
179
249
|
state: pluginState,
|
|
180
250
|
reportFiles: pluginFiles,
|
|
251
|
+
ci: __classPrivateFieldGet(this, _AllureReport_ci, "f"),
|
|
181
252
|
};
|
|
182
253
|
try {
|
|
183
|
-
await consumer.call(this, plugin, pluginContext
|
|
254
|
+
await consumer.call(this, plugin, pluginContext);
|
|
184
255
|
if (initState) {
|
|
185
256
|
__classPrivateFieldGet(this, _AllureReport_state, "f")[id] = pluginState;
|
|
186
257
|
}
|
|
@@ -193,19 +264,26 @@ export class AllureReport {
|
|
|
193
264
|
this.validate = async () => {
|
|
194
265
|
await __classPrivateFieldGet(this, _AllureReport_qualityGate, "f").validate(__classPrivateFieldGet(this, _AllureReport_store, "f"));
|
|
195
266
|
};
|
|
196
|
-
const { name, readers = [allure1, allure2, cucumberjson, junitXml, attachments], plugins = [],
|
|
197
|
-
__classPrivateFieldSet(this,
|
|
198
|
-
|
|
267
|
+
const { name, readers = [allure1, allure2, cucumberjson, junitXml, attachments], plugins = [], known, reportFiles, qualityGate, realTime, historyPath, defaultLabels = {}, variables = {}, environments, output, allureService: allureServiceConfig, } = opts;
|
|
268
|
+
__classPrivateFieldSet(this, _AllureReport_allureServiceClient, allureServiceConfig?.url ? new AllureServiceClient(allureServiceConfig) : undefined, "f");
|
|
269
|
+
this.reportUuid = randomUUID();
|
|
270
|
+
__classPrivateFieldSet(this, _AllureReport_ci, detect(), "f");
|
|
271
|
+
const reportTitleSuffix = __classPrivateFieldGet(this, _AllureReport_ci, "f")?.pullRequestName ?? __classPrivateFieldGet(this, _AllureReport_ci, "f")?.jobRunName;
|
|
272
|
+
__classPrivateFieldSet(this, _AllureReport_reportName, [name, reportTitleSuffix].filter(Boolean).join(" – "), "f");
|
|
199
273
|
__classPrivateFieldSet(this, _AllureReport_eventEmitter, new EventEmitter(), "f");
|
|
200
274
|
__classPrivateFieldSet(this, _AllureReport_events, new Events(__classPrivateFieldGet(this, _AllureReport_eventEmitter, "f")), "f");
|
|
201
275
|
__classPrivateFieldSet(this, _AllureReport_realTime, realTime, "f");
|
|
202
|
-
|
|
203
|
-
|
|
276
|
+
if (__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f")) {
|
|
277
|
+
__classPrivateFieldSet(this, _AllureReport_history, new AllureRemoteHistory(__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f")), "f");
|
|
278
|
+
}
|
|
279
|
+
else if (historyPath) {
|
|
280
|
+
__classPrivateFieldSet(this, _AllureReport_history, new AllureLocalHistory(historyPath), "f");
|
|
281
|
+
}
|
|
204
282
|
__classPrivateFieldSet(this, _AllureReport_store, new DefaultAllureStore({
|
|
205
283
|
eventEmitter: __classPrivateFieldGet(this, _AllureReport_eventEmitter, "f"),
|
|
206
284
|
reportVariables: variables,
|
|
207
285
|
environmentsConfig: environments,
|
|
208
|
-
history,
|
|
286
|
+
history: __classPrivateFieldGet(this, _AllureReport_history, "f"),
|
|
209
287
|
known,
|
|
210
288
|
defaultLabels,
|
|
211
289
|
}), "f");
|
|
@@ -214,6 +292,9 @@ export class AllureReport {
|
|
|
214
292
|
__classPrivateFieldSet(this, _AllureReport_reportFiles, reportFiles, "f");
|
|
215
293
|
__classPrivateFieldSet(this, _AllureReport_output, output, "f");
|
|
216
294
|
__classPrivateFieldSet(this, _AllureReport_qualityGate, new QualityGate(qualityGate), "f");
|
|
295
|
+
__classPrivateFieldSet(this, _AllureReport_history, __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f")
|
|
296
|
+
? new AllureRemoteHistory(__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f"))
|
|
297
|
+
: new AllureLocalHistory(historyPath), "f");
|
|
217
298
|
}
|
|
218
299
|
get store() {
|
|
219
300
|
return __classPrivateFieldGet(this, _AllureReport_store, "f");
|
|
@@ -225,6 +306,8 @@ export class AllureReport {
|
|
|
225
306
|
return __classPrivateFieldGet(this, _AllureReport_qualityGate, "f").result;
|
|
226
307
|
}
|
|
227
308
|
}
|
|
228
|
-
|
|
309
|
+
_AllureReport_reportName = new WeakMap(), _AllureReport_ci = new WeakMap(), _AllureReport_store = new WeakMap(), _AllureReport_readers = new WeakMap(), _AllureReport_plugins = new WeakMap(), _AllureReport_reportFiles = new WeakMap(), _AllureReport_eventEmitter = new WeakMap(), _AllureReport_events = new WeakMap(), _AllureReport_qualityGate = new WeakMap(), _AllureReport_realTime = new WeakMap(), _AllureReport_output = new WeakMap(), _AllureReport_history = new WeakMap(), _AllureReport_allureServiceClient = new WeakMap(), _AllureReport_state = new WeakMap(), _AllureReport_stage = new WeakMap(), _AllureReport_update = new WeakMap(), _AllureReport_eachPlugin = new WeakMap(), _AllureReport_instances = new WeakSet(), _AllureReport_publish_get = function _AllureReport_publish_get() {
|
|
310
|
+
return __classPrivateFieldGet(this, _AllureReport_plugins, "f").some(({ enabled, options }) => enabled && options.publish);
|
|
311
|
+
}, _AllureReport_getPluginState = function _AllureReport_getPluginState(init, id) {
|
|
229
312
|
return init ? new DefaultPluginState({}) : __classPrivateFieldGet(this, _AllureReport_state, "f")?.[id];
|
|
230
313
|
};
|
package/dist/store/convert.js
CHANGED
|
@@ -19,7 +19,7 @@ export const testFixtureResultRawToState = (stateData, raw, context) => {
|
|
|
19
19
|
...(raw.actual && raw.expected ? { expected: raw.expected, actual: raw.actual } : {}),
|
|
20
20
|
},
|
|
21
21
|
...processTimings(raw),
|
|
22
|
-
steps: convertSteps(stateData, raw.steps),
|
|
22
|
+
steps: convertSteps(stateData, raw.steps).convertedSteps,
|
|
23
23
|
sourceMetadata: {
|
|
24
24
|
readerId: context.readerId,
|
|
25
25
|
metadata: context.metadata ?? {},
|
|
@@ -57,7 +57,7 @@ export const testResultRawToState = (stateData, raw, context) => {
|
|
|
57
57
|
known: raw.known ?? false,
|
|
58
58
|
hidden: false,
|
|
59
59
|
labels,
|
|
60
|
-
steps: convertSteps(stateData, raw.steps),
|
|
60
|
+
steps: convertSteps(stateData, raw.steps).convertedSteps,
|
|
61
61
|
parameters,
|
|
62
62
|
links: convertLinks(raw.links),
|
|
63
63
|
hostId,
|
|
@@ -66,6 +66,7 @@ export const testResultRawToState = (stateData, raw, context) => {
|
|
|
66
66
|
readerId: context.readerId,
|
|
67
67
|
metadata: context.metadata ?? {},
|
|
68
68
|
},
|
|
69
|
+
titlePath: raw.titlePath ?? [],
|
|
69
70
|
};
|
|
70
71
|
};
|
|
71
72
|
const processTestCase = ({ testCases }, raw) => {
|
|
@@ -172,26 +173,46 @@ const convertLabel = (label) => {
|
|
|
172
173
|
value: label.value,
|
|
173
174
|
};
|
|
174
175
|
};
|
|
175
|
-
const convertSteps = (stateData, steps) =>
|
|
176
|
+
const convertSteps = (stateData, steps) => {
|
|
177
|
+
const convertedStepData = steps?.filter(notNull)?.map((step) => convertStep(stateData, step)) ?? [];
|
|
178
|
+
return {
|
|
179
|
+
convertedSteps: convertedStepData.map(({ convertedStep }) => convertedStep),
|
|
180
|
+
messages: new Set(convertedStepData.reduce((acc, { messages }) => {
|
|
181
|
+
if (messages) {
|
|
182
|
+
acc.push(...messages);
|
|
183
|
+
}
|
|
184
|
+
return acc;
|
|
185
|
+
}, [])),
|
|
186
|
+
};
|
|
187
|
+
};
|
|
176
188
|
const convertStep = (stateData, step) => {
|
|
177
189
|
if (step.type === "step") {
|
|
178
|
-
const
|
|
179
|
-
const
|
|
190
|
+
const { message } = step;
|
|
191
|
+
const { convertedSteps: subSteps, messages } = convertSteps(stateData, step.steps);
|
|
192
|
+
const hasSimilarErrorInSubSteps = !!message && messages.has(message);
|
|
193
|
+
if (message && !hasSimilarErrorInSubSteps) {
|
|
194
|
+
messages.add(message);
|
|
195
|
+
}
|
|
180
196
|
return {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
197
|
+
convertedStep: {
|
|
198
|
+
stepId: md5(`${step.name}${step.start}`),
|
|
199
|
+
name: step.name ?? __unknown,
|
|
200
|
+
status: step.status ?? defaultStatus,
|
|
201
|
+
steps: subSteps,
|
|
202
|
+
parameters: convertParameters(step.parameters),
|
|
203
|
+
...processTimings(step),
|
|
204
|
+
type: "step",
|
|
205
|
+
message,
|
|
206
|
+
trace: step.trace,
|
|
207
|
+
hasSimilarErrorInSubSteps,
|
|
208
|
+
},
|
|
209
|
+
messages,
|
|
191
210
|
};
|
|
192
211
|
}
|
|
193
212
|
return {
|
|
194
|
-
|
|
213
|
+
convertedStep: {
|
|
214
|
+
...processAttachmentLink(stateData, step),
|
|
215
|
+
},
|
|
195
216
|
};
|
|
196
217
|
};
|
|
197
218
|
const convertParameters = (parameters) => parameters
|
package/dist/store/store.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AttachmentLink, type DefaultLabelsConfig, type EnvironmentsConfig, type HistoryDataPoint, type HistoryTestResult, type KnownTestFailure, type ReportVariables, type TestCase, type TestEnvGroup, type TestFixtureResult, type TestResult } from "@allurereport/core-api";
|
|
1
|
+
import { type AllureHistory, type AttachmentLink, type DefaultLabelsConfig, type EnvironmentsConfig, type HistoryDataPoint, type HistoryTestResult, type KnownTestFailure, type RepoData, type ReportVariables, type TestCase, type TestEnvGroup, type TestFixtureResult, type TestResult } from "@allurereport/core-api";
|
|
2
2
|
import { type AllureStore, type ResultFile, type TestResultFilter } from "@allurereport/plugin-api";
|
|
3
3
|
import type { RawFixtureResult, RawMetadata, RawTestResult, ReaderContext, ResultsVisitor } from "@allurereport/reader-api";
|
|
4
4
|
import type { EventEmitter } from "node:events";
|
|
@@ -13,13 +13,16 @@ export declare class DefaultAllureStore implements AllureStore, ResultsVisitor {
|
|
|
13
13
|
readonly indexFixturesByTestResult: Map<string, TestFixtureResult[]>;
|
|
14
14
|
readonly indexKnownByHistoryId: Map<string, KnownTestFailure[]>;
|
|
15
15
|
constructor(params?: {
|
|
16
|
-
history?:
|
|
16
|
+
history?: AllureHistory;
|
|
17
17
|
known?: KnownTestFailure[];
|
|
18
18
|
eventEmitter?: EventEmitter<AllureStoreEvents>;
|
|
19
19
|
defaultLabels?: DefaultLabelsConfig;
|
|
20
20
|
environmentsConfig?: EnvironmentsConfig;
|
|
21
21
|
reportVariables?: ReportVariables;
|
|
22
22
|
});
|
|
23
|
+
readHistory(): Promise<HistoryDataPoint[]>;
|
|
24
|
+
appendHistory(history: HistoryDataPoint): Promise<void>;
|
|
25
|
+
repoData(): Promise<RepoData | undefined>;
|
|
23
26
|
visitTestResult(raw: RawTestResult, context: ReaderContext): Promise<void>;
|
|
24
27
|
visitTestFixtureResult(result: RawFixtureResult, context: ReaderContext): Promise<void>;
|
|
25
28
|
visitAttachmentFile(resultFile: ResultFile, context: ReaderContext): Promise<void>;
|
|
@@ -36,6 +39,7 @@ export declare class DefaultAllureStore implements AllureStore, ResultsVisitor {
|
|
|
36
39
|
allFixtures(): Promise<TestFixtureResult[]>;
|
|
37
40
|
allHistoryDataPoints(): Promise<HistoryDataPoint[]>;
|
|
38
41
|
allKnownIssues(): Promise<KnownTestFailure[]>;
|
|
42
|
+
allNewTestResults(): Promise<TestResult[]>;
|
|
39
43
|
testCaseById(tcId: string): Promise<TestCase | undefined>;
|
|
40
44
|
testResultById(trId: string): Promise<TestResult | undefined>;
|
|
41
45
|
attachmentById(attachmentId: string): Promise<AttachmentLink | undefined>;
|
package/dist/store/store.js
CHANGED
|
@@ -9,10 +9,12 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _DefaultAllureStore_testResults, _DefaultAllureStore_attachments, _DefaultAllureStore_attachmentContents, _DefaultAllureStore_testCases, _DefaultAllureStore_metadata, _DefaultAllureStore_history, _DefaultAllureStore_known, _DefaultAllureStore_fixtures, _DefaultAllureStore_defaultLabels, _DefaultAllureStore_environmentsConfig, _DefaultAllureStore_reportVariables, _DefaultAllureStore_eventEmitter;
|
|
12
|
+
var _DefaultAllureStore_testResults, _DefaultAllureStore_attachments, _DefaultAllureStore_attachmentContents, _DefaultAllureStore_testCases, _DefaultAllureStore_metadata, _DefaultAllureStore_history, _DefaultAllureStore_known, _DefaultAllureStore_fixtures, _DefaultAllureStore_defaultLabels, _DefaultAllureStore_environmentsConfig, _DefaultAllureStore_reportVariables, _DefaultAllureStore_eventEmitter, _DefaultAllureStore_historyPoints, _DefaultAllureStore_repoData;
|
|
13
13
|
import { compareBy, getWorstStatus, matchEnvironment, nullsLast, ordinal, reverse, } from "@allurereport/core-api";
|
|
14
14
|
import { md5 } from "@allurereport/plugin-api";
|
|
15
15
|
import { isFlaky } from "../utils/flaky.js";
|
|
16
|
+
import { getGitBranch, getGitRepoName } from "../utils/git.js";
|
|
17
|
+
import { getStatusTransition } from "../utils/new.js";
|
|
16
18
|
import { getTestResultsStats } from "../utils/stats.js";
|
|
17
19
|
import { testFixtureResultRawToState, testResultRawToState } from "./convert.js";
|
|
18
20
|
const index = (indexMap, key, ...items) => {
|
|
@@ -44,14 +46,16 @@ export class DefaultAllureStore {
|
|
|
44
46
|
this.indexAttachmentByFixture = new Map();
|
|
45
47
|
this.indexFixturesByTestResult = new Map();
|
|
46
48
|
this.indexKnownByHistoryId = new Map();
|
|
47
|
-
|
|
49
|
+
_DefaultAllureStore_historyPoints.set(this, []);
|
|
50
|
+
_DefaultAllureStore_repoData.set(this, void 0);
|
|
51
|
+
const { history, known = [], eventEmitter, defaultLabels = {}, environmentsConfig = {}, reportVariables = {}, } = params ?? {};
|
|
48
52
|
__classPrivateFieldSet(this, _DefaultAllureStore_testResults, new Map(), "f");
|
|
49
53
|
__classPrivateFieldSet(this, _DefaultAllureStore_attachments, new Map(), "f");
|
|
50
54
|
__classPrivateFieldSet(this, _DefaultAllureStore_attachmentContents, new Map(), "f");
|
|
51
55
|
__classPrivateFieldSet(this, _DefaultAllureStore_testCases, new Map(), "f");
|
|
52
56
|
__classPrivateFieldSet(this, _DefaultAllureStore_metadata, new Map(), "f");
|
|
53
57
|
__classPrivateFieldSet(this, _DefaultAllureStore_fixtures, new Map(), "f");
|
|
54
|
-
__classPrivateFieldSet(this, _DefaultAllureStore_history,
|
|
58
|
+
__classPrivateFieldSet(this, _DefaultAllureStore_history, history, "f");
|
|
55
59
|
__classPrivateFieldSet(this, _DefaultAllureStore_known, [...known], "f");
|
|
56
60
|
__classPrivateFieldGet(this, _DefaultAllureStore_known, "f").forEach((ktf) => index(this.indexKnownByHistoryId, ktf.historyId, ktf));
|
|
57
61
|
__classPrivateFieldSet(this, _DefaultAllureStore_eventEmitter, eventEmitter, "f");
|
|
@@ -65,6 +69,38 @@ export class DefaultAllureStore {
|
|
|
65
69
|
this.indexLatestEnvTestResultByHistoryId.set(key, new Map());
|
|
66
70
|
});
|
|
67
71
|
}
|
|
72
|
+
async readHistory() {
|
|
73
|
+
if (!__classPrivateFieldGet(this, _DefaultAllureStore_history, "f")) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
const repoData = await this.repoData();
|
|
77
|
+
__classPrivateFieldSet(this, _DefaultAllureStore_historyPoints, (await __classPrivateFieldGet(this, _DefaultAllureStore_history, "f").readHistory(repoData?.branch)) ?? [], "f");
|
|
78
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_historyPoints, "f").sort(compareBy("timestamp", reverse(ordinal())));
|
|
79
|
+
return __classPrivateFieldGet(this, _DefaultAllureStore_historyPoints, "f");
|
|
80
|
+
}
|
|
81
|
+
async appendHistory(history) {
|
|
82
|
+
if (!__classPrivateFieldGet(this, _DefaultAllureStore_history, "f")) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const repoData = await this.repoData();
|
|
86
|
+
__classPrivateFieldGet(this, _DefaultAllureStore_historyPoints, "f").push(history);
|
|
87
|
+
await __classPrivateFieldGet(this, _DefaultAllureStore_history, "f").appendHistory(history, repoData?.branch);
|
|
88
|
+
}
|
|
89
|
+
async repoData() {
|
|
90
|
+
if (__classPrivateFieldGet(this, _DefaultAllureStore_repoData, "f")) {
|
|
91
|
+
return __classPrivateFieldGet(this, _DefaultAllureStore_repoData, "f");
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
__classPrivateFieldSet(this, _DefaultAllureStore_repoData, {
|
|
95
|
+
name: await getGitRepoName(),
|
|
96
|
+
branch: await getGitBranch(),
|
|
97
|
+
}, "f");
|
|
98
|
+
return __classPrivateFieldGet(this, _DefaultAllureStore_repoData, "f");
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
68
104
|
async visitTestResult(raw, context) {
|
|
69
105
|
const attachmentLinks = [];
|
|
70
106
|
const testResult = testResultRawToState({
|
|
@@ -88,6 +124,7 @@ export class DefaultAllureStore {
|
|
|
88
124
|
}
|
|
89
125
|
testResult.environment = matchEnvironment(__classPrivateFieldGet(this, _DefaultAllureStore_environmentsConfig, "f"), testResult);
|
|
90
126
|
const trHistory = await this.historyByTr(testResult);
|
|
127
|
+
testResult.transition = getStatusTransition(testResult, trHistory);
|
|
91
128
|
testResult.flaky = isFlaky(testResult, trHistory);
|
|
92
129
|
__classPrivateFieldGet(this, _DefaultAllureStore_testResults, "f").set(testResult.id, testResult);
|
|
93
130
|
if (testResult.historyId) {
|
|
@@ -177,11 +214,21 @@ export class DefaultAllureStore {
|
|
|
177
214
|
return Array.from(__classPrivateFieldGet(this, _DefaultAllureStore_fixtures, "f").values());
|
|
178
215
|
}
|
|
179
216
|
async allHistoryDataPoints() {
|
|
180
|
-
return __classPrivateFieldGet(this,
|
|
217
|
+
return __classPrivateFieldGet(this, _DefaultAllureStore_historyPoints, "f");
|
|
181
218
|
}
|
|
182
219
|
async allKnownIssues() {
|
|
183
220
|
return __classPrivateFieldGet(this, _DefaultAllureStore_known, "f");
|
|
184
221
|
}
|
|
222
|
+
async allNewTestResults() {
|
|
223
|
+
const allTrs = await this.allTestResults();
|
|
224
|
+
const allHistoryDps = await this.allHistoryDataPoints();
|
|
225
|
+
return allTrs.filter((tr) => {
|
|
226
|
+
if (!tr.historyId) {
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
return !allHistoryDps.some((dp) => dp.testResults[tr.historyId]);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
185
232
|
async testCaseById(tcId) {
|
|
186
233
|
return __classPrivateFieldGet(this, _DefaultAllureStore_testCases, "f").get(tcId);
|
|
187
234
|
}
|
|
@@ -219,9 +266,19 @@ export class DefaultAllureStore {
|
|
|
219
266
|
if (!tr?.historyId) {
|
|
220
267
|
return [];
|
|
221
268
|
}
|
|
222
|
-
return [...__classPrivateFieldGet(this,
|
|
269
|
+
return [...__classPrivateFieldGet(this, _DefaultAllureStore_historyPoints, "f")]
|
|
223
270
|
.filter((dp) => !!dp.testResults[tr.historyId])
|
|
224
|
-
.map((dp) =>
|
|
271
|
+
.map((dp) => {
|
|
272
|
+
if (!dp.url) {
|
|
273
|
+
return dp.testResults[tr.historyId];
|
|
274
|
+
}
|
|
275
|
+
const url = new URL(dp.url);
|
|
276
|
+
url.hash = tr.id;
|
|
277
|
+
return {
|
|
278
|
+
...dp.testResults[tr.historyId],
|
|
279
|
+
url: url.toString(),
|
|
280
|
+
};
|
|
281
|
+
});
|
|
225
282
|
}
|
|
226
283
|
async historyByTrId(trId) {
|
|
227
284
|
const tr = await this.testResultById(trId);
|
|
@@ -265,11 +322,9 @@ export class DefaultAllureStore {
|
|
|
265
322
|
async testsStatistic(filter) {
|
|
266
323
|
const all = await this.allTestResults();
|
|
267
324
|
const allWithStats = await Promise.all(all.map(async (tr) => {
|
|
268
|
-
const trHistory = await this.historyByTr(tr);
|
|
269
325
|
const retries = await this.retriesByTr(tr);
|
|
270
326
|
return {
|
|
271
327
|
...tr,
|
|
272
|
-
flaky: isFlaky(tr, trHistory),
|
|
273
328
|
retries,
|
|
274
329
|
};
|
|
275
330
|
}));
|
|
@@ -327,4 +382,4 @@ export class DefaultAllureStore {
|
|
|
327
382
|
};
|
|
328
383
|
}
|
|
329
384
|
}
|
|
330
|
-
_DefaultAllureStore_testResults = new WeakMap(), _DefaultAllureStore_attachments = new WeakMap(), _DefaultAllureStore_attachmentContents = new WeakMap(), _DefaultAllureStore_testCases = new WeakMap(), _DefaultAllureStore_metadata = new WeakMap(), _DefaultAllureStore_history = new WeakMap(), _DefaultAllureStore_known = new WeakMap(), _DefaultAllureStore_fixtures = new WeakMap(), _DefaultAllureStore_defaultLabels = new WeakMap(), _DefaultAllureStore_environmentsConfig = new WeakMap(), _DefaultAllureStore_reportVariables = new WeakMap(), _DefaultAllureStore_eventEmitter = new WeakMap();
|
|
385
|
+
_DefaultAllureStore_testResults = new WeakMap(), _DefaultAllureStore_attachments = new WeakMap(), _DefaultAllureStore_attachmentContents = new WeakMap(), _DefaultAllureStore_testCases = new WeakMap(), _DefaultAllureStore_metadata = new WeakMap(), _DefaultAllureStore_history = new WeakMap(), _DefaultAllureStore_known = new WeakMap(), _DefaultAllureStore_fixtures = new WeakMap(), _DefaultAllureStore_defaultLabels = new WeakMap(), _DefaultAllureStore_environmentsConfig = new WeakMap(), _DefaultAllureStore_reportVariables = new WeakMap(), _DefaultAllureStore_eventEmitter = new WeakMap(), _DefaultAllureStore_historyPoints = new WeakMap(), _DefaultAllureStore_repoData = new WeakMap();
|
package/dist/utils/flaky.js
CHANGED
|
@@ -4,7 +4,7 @@ const isAllureClassicFlaky = (tr, history) => {
|
|
|
4
4
|
if (history.length === 0 || !badStatuses.includes(tr.status)) {
|
|
5
5
|
return false;
|
|
6
6
|
}
|
|
7
|
-
const limitedLastHistory = history.slice(
|
|
7
|
+
const limitedLastHistory = history.slice(0, MAX_LAST_HISTORY_SIZE);
|
|
8
8
|
const limitedLastHistoryStatuses = limitedLastHistory.map((h) => h.status);
|
|
9
9
|
return (limitedLastHistoryStatuses.includes("passed") &&
|
|
10
10
|
limitedLastHistoryStatuses.indexOf("passed") < limitedLastHistoryStatuses.lastIndexOf("failed"));
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { basename } from "node:path";
|
|
3
|
+
export const getGitBranch = (cwd) => {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
const git = spawn("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd });
|
|
6
|
+
let output = "";
|
|
7
|
+
let errorOutput = "";
|
|
8
|
+
git.stdout.on("data", (data) => {
|
|
9
|
+
output += data;
|
|
10
|
+
});
|
|
11
|
+
git.stderr.on("data", (data) => {
|
|
12
|
+
errorOutput += data;
|
|
13
|
+
});
|
|
14
|
+
git.on("close", (code) => {
|
|
15
|
+
if (code !== 0) {
|
|
16
|
+
return reject(new Error(errorOutput || "Git command failed"));
|
|
17
|
+
}
|
|
18
|
+
return resolve(output.trim());
|
|
19
|
+
});
|
|
20
|
+
git.on("error", (err) => {
|
|
21
|
+
return reject(err);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
export const getGitRepoName = (cwd) => {
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
const git = spawn("git", ["rev-parse", "--show-toplevel"], { cwd });
|
|
28
|
+
let output = "";
|
|
29
|
+
let errorOutput = "";
|
|
30
|
+
git.stdout.on("data", (data) => {
|
|
31
|
+
output += data;
|
|
32
|
+
});
|
|
33
|
+
git.stderr.on("data", (data) => {
|
|
34
|
+
errorOutput += data;
|
|
35
|
+
});
|
|
36
|
+
git.on("close", (code) => {
|
|
37
|
+
if (code !== 0) {
|
|
38
|
+
return reject(new Error(errorOutput || "Git command failed"));
|
|
39
|
+
}
|
|
40
|
+
return resolve(basename(output.trim()));
|
|
41
|
+
});
|
|
42
|
+
git.on("error", (err) => {
|
|
43
|
+
return reject(err);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { HistoryTestResult, TestResult, TestStatusTransition } from "@allurereport/core-api";
|
|
2
|
+
export declare const isNew: (history?: HistoryTestResult[]) => boolean;
|
|
3
|
+
export declare const getLastSignificantStatus: (history?: HistoryTestResult[]) => string | undefined;
|
|
4
|
+
export declare const getStatusTransition: (tr: TestResult, history?: HistoryTestResult[]) => TestStatusTransition | undefined;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const NON_SIGNIFICANT_HISTORY_STATUSES = ["unknown", "skipped"];
|
|
2
|
+
export const isNew = (history = []) => history.length === 0;
|
|
3
|
+
const hasSignificantStatus = (htr) => !NON_SIGNIFICANT_HISTORY_STATUSES.includes(htr.status);
|
|
4
|
+
export const getLastSignificantStatus = (history = []) => {
|
|
5
|
+
const significantHtr = history.find(hasSignificantStatus);
|
|
6
|
+
return significantHtr?.status;
|
|
7
|
+
};
|
|
8
|
+
export const getStatusTransition = (tr, history = []) => {
|
|
9
|
+
if (isNew(history)) {
|
|
10
|
+
return "new";
|
|
11
|
+
}
|
|
12
|
+
const lastStatus = getLastSignificantStatus(history);
|
|
13
|
+
if (lastStatus !== tr.status) {
|
|
14
|
+
switch (tr.status) {
|
|
15
|
+
case "passed":
|
|
16
|
+
return "fixed";
|
|
17
|
+
case "failed":
|
|
18
|
+
return "regressed";
|
|
19
|
+
case "broken":
|
|
20
|
+
return "malfunctioned";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
package/dist/utils/stats.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/core",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.17",
|
|
4
4
|
"description": "Collection of generic Allure utilities used across the entire project",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure"
|
|
@@ -25,20 +25,22 @@
|
|
|
25
25
|
"test": "vitest run"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@allurereport/
|
|
29
|
-
"@allurereport/
|
|
30
|
-
"@allurereport/plugin-
|
|
31
|
-
"@allurereport/plugin-
|
|
32
|
-
"@allurereport/plugin-
|
|
33
|
-
"@allurereport/plugin-
|
|
34
|
-
"@allurereport/plugin-
|
|
35
|
-
"@allurereport/plugin-
|
|
36
|
-
"@allurereport/plugin-
|
|
37
|
-
"@allurereport/plugin-
|
|
38
|
-
"@allurereport/plugin-
|
|
39
|
-
"@allurereport/
|
|
40
|
-
"@allurereport/reader
|
|
41
|
-
"@allurereport/
|
|
28
|
+
"@allurereport/ci": "3.0.0-beta.17",
|
|
29
|
+
"@allurereport/core-api": "3.0.0-beta.17",
|
|
30
|
+
"@allurereport/plugin-allure2": "3.0.0-beta.17",
|
|
31
|
+
"@allurereport/plugin-api": "3.0.0-beta.17",
|
|
32
|
+
"@allurereport/plugin-awesome": "3.0.0-beta.17",
|
|
33
|
+
"@allurereport/plugin-classic": "3.0.0-beta.17",
|
|
34
|
+
"@allurereport/plugin-csv": "3.0.0-beta.17",
|
|
35
|
+
"@allurereport/plugin-dashboard": "3.0.0-beta.17",
|
|
36
|
+
"@allurereport/plugin-log": "3.0.0-beta.17",
|
|
37
|
+
"@allurereport/plugin-progress": "3.0.0-beta.17",
|
|
38
|
+
"@allurereport/plugin-slack": "3.0.0-beta.17",
|
|
39
|
+
"@allurereport/plugin-testplan": "3.0.0-beta.17",
|
|
40
|
+
"@allurereport/reader": "3.0.0-beta.17",
|
|
41
|
+
"@allurereport/reader-api": "3.0.0-beta.17",
|
|
42
|
+
"@allurereport/service": "3.0.0-beta.17",
|
|
43
|
+
"@allurereport/summary": "3.0.0-beta.17",
|
|
42
44
|
"handlebars": "^4.7.8",
|
|
43
45
|
"markdown-it": "^14.1.0"
|
|
44
46
|
},
|
|
@@ -50,10 +52,10 @@
|
|
|
50
52
|
"@types/node": "^20.17.9",
|
|
51
53
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
52
54
|
"@typescript-eslint/parser": "^8.0.0",
|
|
53
|
-
"@vitest/runner": "^2.1.
|
|
54
|
-
"@vitest/snapshot": "^2.1.
|
|
55
|
-
"allure-js-commons": "^3.0
|
|
56
|
-
"allure-vitest": "^3.0
|
|
55
|
+
"@vitest/runner": "^2.1.9",
|
|
56
|
+
"@vitest/snapshot": "^2.1.9",
|
|
57
|
+
"allure-js-commons": "^3.3.0",
|
|
58
|
+
"allure-vitest": "^3.3.0",
|
|
57
59
|
"eslint": "^8.57.0",
|
|
58
60
|
"eslint-config-prettier": "^9.1.0",
|
|
59
61
|
"eslint-plugin-import": "^2.29.1",
|
|
@@ -64,6 +66,6 @@
|
|
|
64
66
|
"rimraf": "^6.0.1",
|
|
65
67
|
"tslib": "^2.7.0",
|
|
66
68
|
"typescript": "^5.6.3",
|
|
67
|
-
"vitest": "^2.1.
|
|
69
|
+
"vitest": "^2.1.9"
|
|
68
70
|
}
|
|
69
71
|
}
|