@allurereport/core 3.0.0-beta.15 → 3.0.0-beta.16
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 +28 -5
- package/dist/config.js +19 -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 +102 -26
- package/dist/store/convert.js +36 -16
- package/dist/store/store.d.ts +5 -2
- package/dist/store/store.js +54 -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 +19 -18
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,26 @@ 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;
|
|
20
|
+
export declare const enforcePlugin: (config: FullConfig, pluginInstance: PluginInstance) => {
|
|
21
|
+
name: string;
|
|
22
|
+
output: string;
|
|
23
|
+
historyPath: string;
|
|
24
|
+
knownIssuesPath: string;
|
|
25
|
+
qualityGate?: import("@allurereport/plugin-api").QualityGateConfig;
|
|
26
|
+
defaultLabels?: import("@allurereport/core-api").DefaultLabelsConfig;
|
|
27
|
+
environments?: import("@allurereport/core-api").EnvironmentsConfig;
|
|
28
|
+
variables?: import("@allurereport/core-api").ReportVariables;
|
|
29
|
+
reportFiles: import("@allurereport/plugin-api").ReportFiles;
|
|
30
|
+
readers?: import("@allurereport/reader-api").ResultsReader[];
|
|
31
|
+
plugins?: PluginInstance[];
|
|
32
|
+
appendHistory?: boolean;
|
|
33
|
+
known?: import("@allurereport/core-api").KnownTestFailure[];
|
|
34
|
+
realTime?: any;
|
|
35
|
+
allureService?: {
|
|
36
|
+
url?: string;
|
|
37
|
+
project?: string;
|
|
38
|
+
accessToken?: string;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
18
41
|
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,20 @@ 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
|
+
};
|
|
107
|
+
export const enforcePlugin = (config, pluginInstance) => {
|
|
108
|
+
const newConfig = { ...config };
|
|
109
|
+
const instance = getPluginInstance(newConfig, (item) => item.plugin.constructor === pluginInstance.plugin.constructor);
|
|
110
|
+
if (!instance) {
|
|
111
|
+
newConfig.plugins = [pluginInstance];
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
newConfig.plugins = [instance];
|
|
115
|
+
}
|
|
116
|
+
return newConfig;
|
|
117
|
+
};
|
|
105
118
|
export const resolvePlugin = async (path) => {
|
|
106
119
|
if (!path.startsWith("@allurereport/plugin-")) {
|
|
107
120
|
try {
|
|
@@ -122,9 +135,10 @@ const resolvePlugins = async (plugins) => {
|
|
|
122
135
|
const pluginInstances = [];
|
|
123
136
|
for (const id in plugins) {
|
|
124
137
|
const pluginConfig = plugins[id];
|
|
138
|
+
const pluginId = getPluginId(id);
|
|
125
139
|
const Plugin = await resolvePlugin(pluginConfig.import ?? id);
|
|
126
140
|
pluginInstances.push({
|
|
127
|
-
id:
|
|
141
|
+
id: pluginId,
|
|
128
142
|
enabled: pluginConfig.enabled ?? true,
|
|
129
143
|
options: pluginConfig.options ?? {},
|
|
130
144
|
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, enforcePlugin } 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, enforcePlugin } 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,10 @@ 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_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
13
|
import { allure1, allure2, attachments, cucumberjson, junitXml, readXcResultBundle } from "@allurereport/reader";
|
|
14
14
|
import { PathResultFile } from "@allurereport/reader-api";
|
|
15
|
+
import { AllureRemoteHistory, AllureServiceClient, KnownError, UnknownError } from "@allurereport/service";
|
|
15
16
|
import { generateSummary } from "@allurereport/summary";
|
|
16
17
|
import console from "node:console";
|
|
17
18
|
import { randomUUID } from "node:crypto";
|
|
@@ -19,7 +20,7 @@ import { EventEmitter } from "node:events";
|
|
|
19
20
|
import { readFileSync } from "node:fs";
|
|
20
21
|
import { lstat, opendir, readdir, realpath, rename, rm } from "node:fs/promises";
|
|
21
22
|
import { dirname, join, resolve } from "node:path";
|
|
22
|
-
import {
|
|
23
|
+
import { AllureLocalHistory, createHistory } from "./history.js";
|
|
23
24
|
import { DefaultPluginState, PluginFiles } from "./plugin.js";
|
|
24
25
|
import { QualityGate } from "./qualityGate.js";
|
|
25
26
|
import { DefaultAllureStore } from "./store/store.js";
|
|
@@ -29,7 +30,6 @@ const initRequired = "report is not initialised. Call the start() method first."
|
|
|
29
30
|
export class AllureReport {
|
|
30
31
|
constructor(opts) {
|
|
31
32
|
_AllureReport_instances.add(this);
|
|
32
|
-
_AllureReport_reportUuid.set(this, void 0);
|
|
33
33
|
_AllureReport_reportName.set(this, void 0);
|
|
34
34
|
_AllureReport_store.set(this, void 0);
|
|
35
35
|
_AllureReport_readers.set(this, void 0);
|
|
@@ -38,10 +38,10 @@ export class AllureReport {
|
|
|
38
38
|
_AllureReport_eventEmitter.set(this, void 0);
|
|
39
39
|
_AllureReport_events.set(this, void 0);
|
|
40
40
|
_AllureReport_qualityGate.set(this, void 0);
|
|
41
|
-
_AllureReport_appendHistory.set(this, void 0);
|
|
42
|
-
_AllureReport_historyPath.set(this, void 0);
|
|
43
41
|
_AllureReport_realTime.set(this, void 0);
|
|
44
42
|
_AllureReport_output.set(this, void 0);
|
|
43
|
+
_AllureReport_history.set(this, void 0);
|
|
44
|
+
_AllureReport_allureServiceClient.set(this, void 0);
|
|
45
45
|
_AllureReport_state.set(this, void 0);
|
|
46
46
|
_AllureReport_stage.set(this, "init");
|
|
47
47
|
this.readDirectory = async (resultsDir) => {
|
|
@@ -86,6 +86,7 @@ export class AllureReport {
|
|
|
86
86
|
}
|
|
87
87
|
};
|
|
88
88
|
this.start = async () => {
|
|
89
|
+
await __classPrivateFieldGet(this, _AllureReport_store, "f").readHistory();
|
|
89
90
|
if (__classPrivateFieldGet(this, _AllureReport_stage, "f") === "running") {
|
|
90
91
|
throw new Error("the report is already started");
|
|
91
92
|
}
|
|
@@ -93,6 +94,13 @@ export class AllureReport {
|
|
|
93
94
|
throw new Error("the report is already stopped, the restart isn't supported at the moment");
|
|
94
95
|
}
|
|
95
96
|
__classPrivateFieldSet(this, _AllureReport_stage, "running", "f");
|
|
97
|
+
if (__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f") && __classPrivateFieldGet(this, _AllureReport_instances, "a", _AllureReport_publish_get)) {
|
|
98
|
+
const { url } = await __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f").createReport({
|
|
99
|
+
reportUuid: this.reportUuid,
|
|
100
|
+
reportName: __classPrivateFieldGet(this, _AllureReport_reportName, "f"),
|
|
101
|
+
});
|
|
102
|
+
this.reportUrl = url;
|
|
103
|
+
}
|
|
96
104
|
await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, true, async (plugin, context) => {
|
|
97
105
|
await plugin.start?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"), __classPrivateFieldGet(this, _AllureReport_events, "f"));
|
|
98
106
|
});
|
|
@@ -113,27 +121,51 @@ export class AllureReport {
|
|
|
113
121
|
});
|
|
114
122
|
this.done = async () => {
|
|
115
123
|
const summaries = [];
|
|
124
|
+
const remoteHrefs = [];
|
|
116
125
|
if (__classPrivateFieldGet(this, _AllureReport_stage, "f") !== "running") {
|
|
117
126
|
throw new Error(initRequired);
|
|
118
127
|
}
|
|
119
128
|
__classPrivateFieldGet(this, _AllureReport_events, "f").offAll();
|
|
120
129
|
__classPrivateFieldSet(this, _AllureReport_stage, "done", "f");
|
|
121
|
-
await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, false, async (plugin, context
|
|
130
|
+
await __classPrivateFieldGet(this, _AllureReport_eachPlugin, "f").call(this, false, async (plugin, context) => {
|
|
122
131
|
await plugin.done?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"));
|
|
132
|
+
if (__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f") && context.publish) {
|
|
133
|
+
const pluginFiles = (await context.state.get("files")) ?? {};
|
|
134
|
+
for (const [filename, filepath] of Object.entries(pluginFiles)) {
|
|
135
|
+
if (/^(data|widgets|index\.html$)/.test(filename)) {
|
|
136
|
+
__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f").addReportFile({
|
|
137
|
+
reportUuid: this.reportUuid,
|
|
138
|
+
pluginId: context.id,
|
|
139
|
+
filename,
|
|
140
|
+
filepath,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f").addReportAsset({
|
|
145
|
+
filename,
|
|
146
|
+
filepath,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
123
151
|
const summary = await plugin?.info?.(context, __classPrivateFieldGet(this, _AllureReport_store, "f"));
|
|
124
152
|
if (!summary) {
|
|
125
153
|
return;
|
|
126
154
|
}
|
|
155
|
+
if (context.publish) {
|
|
156
|
+
summary.remoteHref = `${this.reportUrl}/${context.id}/`;
|
|
157
|
+
remoteHrefs.push(summary.remoteHref);
|
|
158
|
+
}
|
|
127
159
|
summaries.push({
|
|
128
160
|
...summary,
|
|
129
|
-
href: `${id}/`,
|
|
161
|
+
href: `${context.id}/`,
|
|
130
162
|
});
|
|
163
|
+
context.reportFiles.addFile("summary.json", Buffer.from(JSON.stringify(summary)));
|
|
131
164
|
});
|
|
132
|
-
if (__classPrivateFieldGet(this,
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
await writeHistory(__classPrivateFieldGet(this, _AllureReport_historyPath, "f"), historyDataPoint);
|
|
165
|
+
if (__classPrivateFieldGet(this, _AllureReport_instances, "a", _AllureReport_publish_get)) {
|
|
166
|
+
await __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f")?.completeReport({
|
|
167
|
+
reportUuid: this.reportUuid,
|
|
168
|
+
});
|
|
137
169
|
}
|
|
138
170
|
const outputDirFiles = await readdir(__classPrivateFieldGet(this, _AllureReport_output, "f"));
|
|
139
171
|
if (outputDirFiles.length === 0) {
|
|
@@ -150,37 +182,71 @@ export class AllureReport {
|
|
|
150
182
|
await rename(currentFilePath, newFilePath);
|
|
151
183
|
}
|
|
152
184
|
await rm(reportPath, { recursive: true });
|
|
153
|
-
|
|
185
|
+
}
|
|
186
|
+
if (__classPrivateFieldGet(this, _AllureReport_history, "f")) {
|
|
187
|
+
const testResults = await __classPrivateFieldGet(this, _AllureReport_store, "f").allTestResults();
|
|
188
|
+
const testCases = await __classPrivateFieldGet(this, _AllureReport_store, "f").allTestCases();
|
|
189
|
+
const historyDataPoint = createHistory(this.reportUuid, __classPrivateFieldGet(this, _AllureReport_reportName, "f"), testCases, testResults, this.reportUrl);
|
|
190
|
+
try {
|
|
191
|
+
await __classPrivateFieldGet(this, _AllureReport_store, "f").appendHistory(historyDataPoint);
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
if (err instanceof KnownError) {
|
|
195
|
+
console.error("Failed to append history", err.message);
|
|
196
|
+
}
|
|
197
|
+
else if (err instanceof UnknownError) {
|
|
198
|
+
console.error("Failed to append history due to unexpected error", err.message);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
throw err;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
154
204
|
}
|
|
155
205
|
if (summaries.length > 1) {
|
|
156
206
|
await generateSummary(__classPrivateFieldGet(this, _AllureReport_output, "f"), summaries);
|
|
157
207
|
}
|
|
208
|
+
if (remoteHrefs.length > 0) {
|
|
209
|
+
console.info("Next reports have been published:");
|
|
210
|
+
remoteHrefs.forEach((href) => {
|
|
211
|
+
console.info(`- ${href}`);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
158
214
|
};
|
|
159
215
|
_AllureReport_eachPlugin.set(this, async (initState, consumer) => {
|
|
160
216
|
if (initState) {
|
|
161
217
|
__classPrivateFieldSet(this, _AllureReport_state, {}, "f");
|
|
162
218
|
}
|
|
163
|
-
for (const
|
|
164
|
-
if (!
|
|
219
|
+
for (const { enabled, id, plugin, options } of __classPrivateFieldGet(this, _AllureReport_plugins, "f")) {
|
|
220
|
+
if (!enabled) {
|
|
165
221
|
continue;
|
|
166
222
|
}
|
|
167
|
-
const id = descriptor.id;
|
|
168
|
-
const plugin = descriptor.plugin;
|
|
169
223
|
const pluginState = __classPrivateFieldGet(this, _AllureReport_instances, "m", _AllureReport_getPluginState).call(this, initState, id);
|
|
170
224
|
if (!pluginState) {
|
|
171
225
|
console.error("plugin error: state is empty");
|
|
172
226
|
continue;
|
|
173
227
|
}
|
|
174
|
-
|
|
228
|
+
if (initState) {
|
|
229
|
+
await pluginState.set("files", {});
|
|
230
|
+
}
|
|
231
|
+
const pluginFiles = new PluginFiles(__classPrivateFieldGet(this, _AllureReport_reportFiles, "f"), id, async (key, filepath) => {
|
|
232
|
+
const currentPluginState = __classPrivateFieldGet(this, _AllureReport_instances, "m", _AllureReport_getPluginState).call(this, false, id);
|
|
233
|
+
const files = await currentPluginState?.get("files");
|
|
234
|
+
if (!files) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
files[key] = filepath;
|
|
238
|
+
});
|
|
175
239
|
const pluginContext = {
|
|
240
|
+
id,
|
|
241
|
+
publish: !!options?.publish,
|
|
176
242
|
allureVersion: version,
|
|
177
|
-
reportUuid:
|
|
243
|
+
reportUuid: this.reportUuid,
|
|
178
244
|
reportName: __classPrivateFieldGet(this, _AllureReport_reportName, "f"),
|
|
179
245
|
state: pluginState,
|
|
180
246
|
reportFiles: pluginFiles,
|
|
181
247
|
};
|
|
182
248
|
try {
|
|
183
|
-
await consumer.call(this, plugin, pluginContext
|
|
249
|
+
await consumer.call(this, plugin, pluginContext);
|
|
184
250
|
if (initState) {
|
|
185
251
|
__classPrivateFieldGet(this, _AllureReport_state, "f")[id] = pluginState;
|
|
186
252
|
}
|
|
@@ -193,19 +259,24 @@ export class AllureReport {
|
|
|
193
259
|
this.validate = async () => {
|
|
194
260
|
await __classPrivateFieldGet(this, _AllureReport_qualityGate, "f").validate(__classPrivateFieldGet(this, _AllureReport_store, "f"));
|
|
195
261
|
};
|
|
196
|
-
const { name, readers = [allure1, allure2, cucumberjson, junitXml, attachments], plugins = [],
|
|
197
|
-
__classPrivateFieldSet(this,
|
|
262
|
+
const { name, readers = [allure1, allure2, cucumberjson, junitXml, attachments], plugins = [], known, reportFiles, qualityGate, realTime, historyPath, defaultLabels = {}, variables = {}, environments, output, allureService: allureServiceConfig, } = opts;
|
|
263
|
+
__classPrivateFieldSet(this, _AllureReport_allureServiceClient, allureServiceConfig?.url ? new AllureServiceClient(allureServiceConfig) : undefined, "f");
|
|
264
|
+
this.reportUuid = randomUUID();
|
|
198
265
|
__classPrivateFieldSet(this, _AllureReport_reportName, name, "f");
|
|
199
266
|
__classPrivateFieldSet(this, _AllureReport_eventEmitter, new EventEmitter(), "f");
|
|
200
267
|
__classPrivateFieldSet(this, _AllureReport_events, new Events(__classPrivateFieldGet(this, _AllureReport_eventEmitter, "f")), "f");
|
|
201
268
|
__classPrivateFieldSet(this, _AllureReport_realTime, realTime, "f");
|
|
202
|
-
|
|
203
|
-
|
|
269
|
+
if (__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f")) {
|
|
270
|
+
__classPrivateFieldSet(this, _AllureReport_history, new AllureRemoteHistory(__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f")), "f");
|
|
271
|
+
}
|
|
272
|
+
else if (historyPath) {
|
|
273
|
+
__classPrivateFieldSet(this, _AllureReport_history, new AllureLocalHistory(historyPath), "f");
|
|
274
|
+
}
|
|
204
275
|
__classPrivateFieldSet(this, _AllureReport_store, new DefaultAllureStore({
|
|
205
276
|
eventEmitter: __classPrivateFieldGet(this, _AllureReport_eventEmitter, "f"),
|
|
206
277
|
reportVariables: variables,
|
|
207
278
|
environmentsConfig: environments,
|
|
208
|
-
history,
|
|
279
|
+
history: __classPrivateFieldGet(this, _AllureReport_history, "f"),
|
|
209
280
|
known,
|
|
210
281
|
defaultLabels,
|
|
211
282
|
}), "f");
|
|
@@ -214,6 +285,9 @@ export class AllureReport {
|
|
|
214
285
|
__classPrivateFieldSet(this, _AllureReport_reportFiles, reportFiles, "f");
|
|
215
286
|
__classPrivateFieldSet(this, _AllureReport_output, output, "f");
|
|
216
287
|
__classPrivateFieldSet(this, _AllureReport_qualityGate, new QualityGate(qualityGate), "f");
|
|
288
|
+
__classPrivateFieldSet(this, _AllureReport_history, __classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f")
|
|
289
|
+
? new AllureRemoteHistory(__classPrivateFieldGet(this, _AllureReport_allureServiceClient, "f"))
|
|
290
|
+
: new AllureLocalHistory(historyPath), "f");
|
|
217
291
|
}
|
|
218
292
|
get store() {
|
|
219
293
|
return __classPrivateFieldGet(this, _AllureReport_store, "f");
|
|
@@ -225,6 +299,8 @@ export class AllureReport {
|
|
|
225
299
|
return __classPrivateFieldGet(this, _AllureReport_qualityGate, "f").result;
|
|
226
300
|
}
|
|
227
301
|
}
|
|
228
|
-
|
|
302
|
+
_AllureReport_reportName = 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() {
|
|
303
|
+
return __classPrivateFieldGet(this, _AllureReport_plugins, "f").some(({ enabled, options }) => enabled && options.publish);
|
|
304
|
+
}, _AllureReport_getPluginState = function _AllureReport_getPluginState(init, id) {
|
|
229
305
|
return init ? new DefaultPluginState({}) : __classPrivateFieldGet(this, _AllureReport_state, "f")?.[id];
|
|
230
306
|
};
|
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,
|
|
@@ -172,26 +172,46 @@ const convertLabel = (label) => {
|
|
|
172
172
|
value: label.value,
|
|
173
173
|
};
|
|
174
174
|
};
|
|
175
|
-
const convertSteps = (stateData, steps) =>
|
|
175
|
+
const convertSteps = (stateData, steps) => {
|
|
176
|
+
const convertedStepData = steps?.filter(notNull)?.map((step) => convertStep(stateData, step)) ?? [];
|
|
177
|
+
return {
|
|
178
|
+
convertedSteps: convertedStepData.map(({ convertedStep }) => convertedStep),
|
|
179
|
+
messages: new Set(convertedStepData.reduce((acc, { messages }) => {
|
|
180
|
+
if (messages) {
|
|
181
|
+
acc.push(...messages);
|
|
182
|
+
}
|
|
183
|
+
return acc;
|
|
184
|
+
}, [])),
|
|
185
|
+
};
|
|
186
|
+
};
|
|
176
187
|
const convertStep = (stateData, step) => {
|
|
177
188
|
if (step.type === "step") {
|
|
178
|
-
const
|
|
179
|
-
const
|
|
189
|
+
const { message } = step;
|
|
190
|
+
const { convertedSteps: subSteps, messages } = convertSteps(stateData, step.steps);
|
|
191
|
+
const hasSimilarErrorInSubSteps = !!message && messages.has(message);
|
|
192
|
+
if (message && !hasSimilarErrorInSubSteps) {
|
|
193
|
+
messages.add(message);
|
|
194
|
+
}
|
|
180
195
|
return {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
196
|
+
convertedStep: {
|
|
197
|
+
stepId: md5(`${step.name}${step.start}`),
|
|
198
|
+
name: step.name ?? __unknown,
|
|
199
|
+
status: step.status ?? defaultStatus,
|
|
200
|
+
steps: subSteps,
|
|
201
|
+
parameters: convertParameters(step.parameters),
|
|
202
|
+
...processTimings(step),
|
|
203
|
+
type: "step",
|
|
204
|
+
message,
|
|
205
|
+
trace: step.trace,
|
|
206
|
+
hasSimilarErrorInSubSteps,
|
|
207
|
+
},
|
|
208
|
+
messages,
|
|
191
209
|
};
|
|
192
210
|
}
|
|
193
211
|
return {
|
|
194
|
-
|
|
212
|
+
convertedStep: {
|
|
213
|
+
...processAttachmentLink(stateData, step),
|
|
214
|
+
},
|
|
195
215
|
};
|
|
196
216
|
};
|
|
197
217
|
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>;
|
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,7 +214,7 @@ 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");
|
|
@@ -219,9 +256,19 @@ export class DefaultAllureStore {
|
|
|
219
256
|
if (!tr?.historyId) {
|
|
220
257
|
return [];
|
|
221
258
|
}
|
|
222
|
-
return [...__classPrivateFieldGet(this,
|
|
259
|
+
return [...__classPrivateFieldGet(this, _DefaultAllureStore_historyPoints, "f")]
|
|
223
260
|
.filter((dp) => !!dp.testResults[tr.historyId])
|
|
224
|
-
.map((dp) =>
|
|
261
|
+
.map((dp) => {
|
|
262
|
+
if (!dp.url) {
|
|
263
|
+
return dp.testResults[tr.historyId];
|
|
264
|
+
}
|
|
265
|
+
const url = new URL(dp.url);
|
|
266
|
+
url.hash = tr.id;
|
|
267
|
+
return {
|
|
268
|
+
...dp.testResults[tr.historyId],
|
|
269
|
+
url: url.toString(),
|
|
270
|
+
};
|
|
271
|
+
});
|
|
225
272
|
}
|
|
226
273
|
async historyByTrId(trId) {
|
|
227
274
|
const tr = await this.testResultById(trId);
|
|
@@ -265,11 +312,9 @@ export class DefaultAllureStore {
|
|
|
265
312
|
async testsStatistic(filter) {
|
|
266
313
|
const all = await this.allTestResults();
|
|
267
314
|
const allWithStats = await Promise.all(all.map(async (tr) => {
|
|
268
|
-
const trHistory = await this.historyByTr(tr);
|
|
269
315
|
const retries = await this.retriesByTr(tr);
|
|
270
316
|
return {
|
|
271
317
|
...tr,
|
|
272
|
-
flaky: isFlaky(tr, trHistory),
|
|
273
318
|
retries,
|
|
274
319
|
};
|
|
275
320
|
}));
|
|
@@ -327,4 +372,4 @@ export class DefaultAllureStore {
|
|
|
327
372
|
};
|
|
328
373
|
}
|
|
329
374
|
}
|
|
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();
|
|
375
|
+
_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.16",
|
|
4
4
|
"description": "Collection of generic Allure utilities used across the entire project",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure"
|
|
@@ -25,20 +25,21 @@
|
|
|
25
25
|
"test": "vitest run"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@allurereport/core-api": "3.0.0-beta.
|
|
29
|
-
"@allurereport/plugin-allure2": "3.0.0-beta.
|
|
30
|
-
"@allurereport/plugin-api": "3.0.0-beta.
|
|
31
|
-
"@allurereport/plugin-awesome": "3.0.0-beta.
|
|
32
|
-
"@allurereport/plugin-classic": "3.0.0-beta.
|
|
33
|
-
"@allurereport/plugin-csv": "3.0.0-beta.
|
|
34
|
-
"@allurereport/plugin-dashboard": "3.0.0-beta.
|
|
35
|
-
"@allurereport/plugin-log": "3.0.0-beta.
|
|
36
|
-
"@allurereport/plugin-progress": "3.0.0-beta.
|
|
37
|
-
"@allurereport/plugin-slack": "3.0.0-beta.
|
|
38
|
-
"@allurereport/plugin-testplan": "3.0.0-beta.
|
|
39
|
-
"@allurereport/reader": "3.0.0-beta.
|
|
40
|
-
"@allurereport/reader-api": "3.0.0-beta.
|
|
41
|
-
"@allurereport/
|
|
28
|
+
"@allurereport/core-api": "3.0.0-beta.16",
|
|
29
|
+
"@allurereport/plugin-allure2": "3.0.0-beta.16",
|
|
30
|
+
"@allurereport/plugin-api": "3.0.0-beta.16",
|
|
31
|
+
"@allurereport/plugin-awesome": "3.0.0-beta.16",
|
|
32
|
+
"@allurereport/plugin-classic": "3.0.0-beta.16",
|
|
33
|
+
"@allurereport/plugin-csv": "3.0.0-beta.16",
|
|
34
|
+
"@allurereport/plugin-dashboard": "3.0.0-beta.16",
|
|
35
|
+
"@allurereport/plugin-log": "3.0.0-beta.16",
|
|
36
|
+
"@allurereport/plugin-progress": "3.0.0-beta.16",
|
|
37
|
+
"@allurereport/plugin-slack": "3.0.0-beta.16",
|
|
38
|
+
"@allurereport/plugin-testplan": "3.0.0-beta.16",
|
|
39
|
+
"@allurereport/reader": "3.0.0-beta.16",
|
|
40
|
+
"@allurereport/reader-api": "3.0.0-beta.16",
|
|
41
|
+
"@allurereport/service": "3.0.0-beta.16",
|
|
42
|
+
"@allurereport/summary": "3.0.0-beta.16",
|
|
42
43
|
"handlebars": "^4.7.8",
|
|
43
44
|
"markdown-it": "^14.1.0"
|
|
44
45
|
},
|
|
@@ -50,8 +51,8 @@
|
|
|
50
51
|
"@types/node": "^20.17.9",
|
|
51
52
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
52
53
|
"@typescript-eslint/parser": "^8.0.0",
|
|
53
|
-
"@vitest/runner": "^2.1.
|
|
54
|
-
"@vitest/snapshot": "^2.1.
|
|
54
|
+
"@vitest/runner": "^2.1.9",
|
|
55
|
+
"@vitest/snapshot": "^2.1.9",
|
|
55
56
|
"allure-js-commons": "^3.0.9",
|
|
56
57
|
"allure-vitest": "^3.0.9",
|
|
57
58
|
"eslint": "^8.57.0",
|
|
@@ -64,6 +65,6 @@
|
|
|
64
65
|
"rimraf": "^6.0.1",
|
|
65
66
|
"tslib": "^2.7.0",
|
|
66
67
|
"typescript": "^5.6.3",
|
|
67
|
-
"vitest": "^2.1.
|
|
68
|
+
"vitest": "^2.1.9"
|
|
68
69
|
}
|
|
69
70
|
}
|