@allurereport/core-api 3.20.1 → 3.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aggregate.d.ts +1 -0
- package/dist/categories.d.ts +2 -1
- package/dist/ci.d.ts +4 -0
- package/dist/config.d.ts +1 -0
- package/dist/history.d.ts +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -0
- package/dist/model.d.ts +1 -0
- package/dist/resolutions.d.ts +14 -1
- package/dist/resolutions.js +39 -1
- package/dist/static.d.ts +5 -0
- package/dist/static.js +53 -1
- package/dist/utils/flaky.d.ts +5 -0
- package/dist/utils/flaky.js +44 -0
- package/dist/utils/status.d.ts +2 -1
- package/dist/utils/status.js +3 -0
- package/package.json +11 -6
package/dist/aggregate.d.ts
CHANGED
package/dist/categories.d.ts
CHANGED
|
@@ -84,6 +84,7 @@ export type CategoryNodeItem = {
|
|
|
84
84
|
value?: string;
|
|
85
85
|
retryHash?: string;
|
|
86
86
|
retriesCount?: number;
|
|
87
|
+
retriesStatusChange?: boolean;
|
|
87
88
|
transition?: TestStatusTransition;
|
|
88
89
|
tooltips?: Record<string, string>;
|
|
89
90
|
statistic?: Statistic;
|
|
@@ -104,7 +105,7 @@ export declare const matchCategoryMatcher: (matcher: Matcher, d: CategoryMatchin
|
|
|
104
105
|
export declare const matchCategory: (categories: CategoryDefinition[], d: CategoryMatchingData) => CategoryDefinition | undefined;
|
|
105
106
|
export declare const extractErrorMatchingData: (tr: Pick<TestResult, "status" | "labels" | "error" | "flaky" | "duration" | "transition" | "environment">) => CategoryMatchingData;
|
|
106
107
|
export declare const buildEnvironmentSortOrder: (environmentNames: string[], defaultEnvironmentName: string) => Map<string, number>;
|
|
107
|
-
export declare const compareNumbers: (left: number, right: number) =>
|
|
108
|
+
export declare const compareNumbers: (left: number, right: number) => 1 | -1 | 0;
|
|
108
109
|
export declare const compareStrings: (left: string, right: string) => number;
|
|
109
110
|
export declare const isMissingValue: (value: string | undefined) => boolean;
|
|
110
111
|
export declare const getGroupSortKey: (groupKey: string | undefined, groupValue: string | undefined, environmentOrderMap?: Map<string, number>) => GroupSortKey;
|
package/dist/ci.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ export interface CiDescriptor {
|
|
|
21
21
|
jobRunUrl: string;
|
|
22
22
|
jobRunName: string;
|
|
23
23
|
jobRunBranch: string;
|
|
24
|
+
pipelineRunName?: string;
|
|
25
|
+
pipelineRunUrl?: string;
|
|
24
26
|
pullRequestName: string;
|
|
25
27
|
pullRequestUrl: string;
|
|
26
28
|
provider?: GitProvider;
|
|
@@ -28,4 +30,6 @@ export interface CiDescriptor {
|
|
|
28
30
|
sourceBranch?: string;
|
|
29
31
|
targetBranch?: string;
|
|
30
32
|
pullRequest?: GitPullRequestRef;
|
|
33
|
+
commitSha?: string;
|
|
34
|
+
commitUrl?: string;
|
|
31
35
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export type DefaultLabelsConfig = Record<string, string | string[]>;
|
|
2
2
|
export type FlakyDetectionConfig = {
|
|
3
3
|
historyDepth?: number;
|
|
4
|
+
stabilizationPeriod?: number;
|
|
4
5
|
includePassedTests?: boolean;
|
|
5
6
|
};
|
|
6
7
|
export declare const parseIntegerConfigValue: (value: unknown, minValue?: number) => number | undefined;
|
package/dist/history.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export * from "./ci.js";
|
|
|
4
4
|
export * from "./gitFlow.js";
|
|
5
5
|
export type * from "./environment.js";
|
|
6
6
|
export type * from "./history.js";
|
|
7
|
-
export
|
|
7
|
+
export * from "./resolutions.js";
|
|
8
8
|
export type * from "./metadata.js";
|
|
9
9
|
export * from "./metrics.js";
|
|
10
10
|
export type * from "./model.js";
|
|
@@ -25,6 +25,7 @@ export * from "./utils/status.js";
|
|
|
25
25
|
export * from "./utils/successRate.js";
|
|
26
26
|
export * from "./utils/environment.js";
|
|
27
27
|
export * from "./utils/history.js";
|
|
28
|
+
export * from "./utils/flaky.js";
|
|
28
29
|
export * from "./utils/identity.js";
|
|
29
30
|
export * from "./utils/strings.js";
|
|
30
31
|
export * from "./utils/dictionary.js";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "./constants.js";
|
|
2
2
|
export * from "./ci.js";
|
|
3
3
|
export * from "./gitFlow.js";
|
|
4
|
+
export * from "./resolutions.js";
|
|
4
5
|
export * from "./metrics.js";
|
|
5
6
|
export * from "./config.js";
|
|
6
7
|
export * from "./static.js";
|
|
@@ -16,6 +17,7 @@ export * from "./utils/status.js";
|
|
|
16
17
|
export * from "./utils/successRate.js";
|
|
17
18
|
export * from "./utils/environment.js";
|
|
18
19
|
export * from "./utils/history.js";
|
|
20
|
+
export * from "./utils/flaky.js";
|
|
19
21
|
export * from "./utils/identity.js";
|
|
20
22
|
export * from "./utils/strings.js";
|
|
21
23
|
export * from "./utils/dictionary.js";
|
package/dist/model.d.ts
CHANGED
package/dist/resolutions.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { TestLink } from "./metadata.js";
|
|
2
|
-
import type { TestError, TestStatus } from "./model.js";
|
|
2
|
+
import type { TestError, TestResult, TestStatus } from "./model.js";
|
|
3
3
|
export type ResolutionCategory = "issue" | "muted" | "accepted";
|
|
4
|
+
export type MutedResolutionState = "active" | "outdated" | "permanent";
|
|
4
5
|
export interface ResolutionLinkTemplate {
|
|
5
6
|
nameTemplate?: string;
|
|
6
7
|
urlTemplate: string;
|
|
@@ -22,8 +23,19 @@ export interface IssueResolutionRule extends ResolutionMatcher {
|
|
|
22
23
|
export interface IgnoredResolutionRule extends ResolutionMatcher {
|
|
23
24
|
resolution: "muted" | "accepted";
|
|
24
25
|
comment: string;
|
|
26
|
+
expiresAt?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface MutedResolutionRule extends IgnoredResolutionRule {
|
|
29
|
+
resolution: "muted";
|
|
30
|
+
}
|
|
31
|
+
export interface AcceptedResolutionRule extends IgnoredResolutionRule {
|
|
32
|
+
resolution: "accepted";
|
|
25
33
|
}
|
|
26
34
|
export type ResolutionRule = IssueResolutionRule | IgnoredResolutionRule;
|
|
35
|
+
type ResolutionStateSource = Pick<TestResult, "resolution" | "resolutionExpiresAt">;
|
|
36
|
+
export declare const parseResolutionExpiresAt: (value: string) => number | undefined;
|
|
37
|
+
export declare const getMutedResolutionState: (testResult: ResolutionStateSource, now?: number) => MutedResolutionState | undefined;
|
|
38
|
+
export declare const isIgnoredResolution: (testResult: ResolutionStateSource, now?: number) => boolean;
|
|
27
39
|
export interface ResolutionsConfig {
|
|
28
40
|
knownIssuesPath?: string;
|
|
29
41
|
links?: Record<string, ResolutionLinkTemplate>;
|
|
@@ -48,3 +60,4 @@ export interface KnownIssueRecord extends ResolutionIssue {
|
|
|
48
60
|
export interface KnownIssuesFile {
|
|
49
61
|
resolutionIssues: KnownIssueRecord[];
|
|
50
62
|
}
|
|
63
|
+
export {};
|
package/dist/resolutions.js
CHANGED
|
@@ -1 +1,39 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export const parseResolutionExpiresAt = (value) => {
|
|
2
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|[+-](\d{2}):(\d{2}))$/.exec(value);
|
|
3
|
+
if (!match) {
|
|
4
|
+
return undefined;
|
|
5
|
+
}
|
|
6
|
+
const [, yearValue, monthValue, dayValue, hourValue, minuteValue, secondValue, offsetHour, offsetMinute] = match;
|
|
7
|
+
const year = Number(yearValue);
|
|
8
|
+
const month = Number(monthValue);
|
|
9
|
+
const day = Number(dayValue);
|
|
10
|
+
const hour = Number(hourValue);
|
|
11
|
+
const minute = Number(minuteValue);
|
|
12
|
+
const second = Number(secondValue);
|
|
13
|
+
const leapYear = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
14
|
+
const daysInMonth = [31, leapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1];
|
|
15
|
+
if (year <= 0 ||
|
|
16
|
+
daysInMonth === undefined ||
|
|
17
|
+
day < 1 ||
|
|
18
|
+
day > daysInMonth ||
|
|
19
|
+
hour > 23 ||
|
|
20
|
+
minute > 59 ||
|
|
21
|
+
second > 59 ||
|
|
22
|
+
(offsetHour !== undefined && (Number(offsetHour) > 23 || Number(offsetMinute) > 59))) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
const timestamp = new Date(value).getTime();
|
|
26
|
+
return Number.isFinite(timestamp) ? timestamp : undefined;
|
|
27
|
+
};
|
|
28
|
+
export const getMutedResolutionState = (testResult, now = Date.now()) => {
|
|
29
|
+
if (testResult.resolution !== "muted") {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
if (testResult.resolutionExpiresAt === undefined) {
|
|
33
|
+
return "permanent";
|
|
34
|
+
}
|
|
35
|
+
const expiresAt = parseResolutionExpiresAt(testResult.resolutionExpiresAt);
|
|
36
|
+
return expiresAt === undefined || now >= expiresAt ? "outdated" : "active";
|
|
37
|
+
};
|
|
38
|
+
export const isIgnoredResolution = (testResult, now = Date.now()) => testResult.resolution === "accepted" ||
|
|
39
|
+
(testResult.resolution === "muted" && getMutedResolutionState(testResult, now) !== "outdated");
|
package/dist/static.d.ts
CHANGED
|
@@ -11,6 +11,11 @@ export declare const appLoaderStyles = "\n <style>\n .allure-app-loader {\n
|
|
|
11
11
|
export declare const createAppLoaderMarkup: () => string;
|
|
12
12
|
export declare const createBaseUrlScript: () => string;
|
|
13
13
|
export declare const stringifyForInlineScript: (value: unknown) => string;
|
|
14
|
+
export declare const reportDataScriptPlaceholder = "<!-- allure-report-data -->";
|
|
15
|
+
export declare const injectReportDataScript: (html: string, reportFiles?: {
|
|
16
|
+
name: string;
|
|
17
|
+
value: string;
|
|
18
|
+
}[]) => Buffer;
|
|
14
19
|
export declare const createReportDataScript: (reportFiles?: {
|
|
15
20
|
name: string;
|
|
16
21
|
value: string;
|
package/dist/static.js
CHANGED
|
@@ -90,6 +90,58 @@ export const stringifyForInlineScript = (value) => {
|
|
|
90
90
|
.replaceAll("\u2028", "\\u2028")
|
|
91
91
|
.replaceAll("\u2029", "\\u2029");
|
|
92
92
|
};
|
|
93
|
+
export const reportDataScriptPlaceholder = "<!-- allure-report-data -->";
|
|
94
|
+
const createReportDataScriptChunks = (reportFiles = []) => {
|
|
95
|
+
if (!reportFiles.length) {
|
|
96
|
+
return [
|
|
97
|
+
Buffer.from(`
|
|
98
|
+
<script async>
|
|
99
|
+
window.allureReportDataReady = true;
|
|
100
|
+
</script>
|
|
101
|
+
`),
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
const chunks = [
|
|
105
|
+
Buffer.from(`
|
|
106
|
+
<script async>
|
|
107
|
+
window.allureReportDataReady = false;
|
|
108
|
+
window.allureReportData = window.allureReportData || {};
|
|
109
|
+
|
|
110
|
+
function d(name, value){
|
|
111
|
+
return new Promise(function (resolve) {
|
|
112
|
+
window.allureReportData[name] = value;
|
|
113
|
+
|
|
114
|
+
return resolve(true);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
</script>
|
|
118
|
+
<script defer>
|
|
119
|
+
Promise.allSettled([`),
|
|
120
|
+
];
|
|
121
|
+
reportFiles.forEach(({ name, value }, index) => {
|
|
122
|
+
chunks.push(Buffer.from(`${index === 0 ? "" : ","}d(${stringifyForInlineScript(name)},${stringifyForInlineScript(value)})`));
|
|
123
|
+
});
|
|
124
|
+
chunks.push(Buffer.from(`])
|
|
125
|
+
.then(function(){
|
|
126
|
+
window.allureReportDataReady = true;
|
|
127
|
+
})
|
|
128
|
+
</script>
|
|
129
|
+
`));
|
|
130
|
+
return chunks;
|
|
131
|
+
};
|
|
132
|
+
export const injectReportDataScript = (html, reportFiles = []) => {
|
|
133
|
+
const placeholderIndex = html.indexOf(reportDataScriptPlaceholder);
|
|
134
|
+
if (placeholderIndex === -1) {
|
|
135
|
+
throw new Error("Report data script placeholder is missing from the HTML template");
|
|
136
|
+
}
|
|
137
|
+
const prefix = html.slice(0, placeholderIndex);
|
|
138
|
+
const suffix = html.slice(placeholderIndex + reportDataScriptPlaceholder.length);
|
|
139
|
+
return Buffer.concat([
|
|
140
|
+
Buffer.from(prefix, "utf8"),
|
|
141
|
+
...createReportDataScriptChunks(reportFiles),
|
|
142
|
+
Buffer.from(suffix, "utf8"),
|
|
143
|
+
]);
|
|
144
|
+
};
|
|
93
145
|
export const createReportDataScript = (reportFiles = []) => {
|
|
94
146
|
if (!reportFiles?.length) {
|
|
95
147
|
return `
|
|
@@ -99,7 +151,7 @@ export const createReportDataScript = (reportFiles = []) => {
|
|
|
99
151
|
`;
|
|
100
152
|
}
|
|
101
153
|
const reportFilesDeclaration = reportFiles
|
|
102
|
-
.map(({ name, value }) => `d(${
|
|
154
|
+
.map(({ name, value }) => `d(${stringifyForInlineScript(name)},${stringifyForInlineScript(value)})`)
|
|
103
155
|
.join(",");
|
|
104
156
|
return `
|
|
105
157
|
<script async>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FlakyDetectionConfig } from "../config.js";
|
|
2
|
+
import type { HistoryTestResult } from "../history.js";
|
|
3
|
+
import type { TestResult } from "../model.js";
|
|
4
|
+
export type FlakinessOptions = Pick<FlakyDetectionConfig, "historyDepth" | "stabilizationPeriod">;
|
|
5
|
+
export declare const getTestFlakiness: (current: TestResult, history: (HistoryTestResult | undefined)[], options?: FlakinessOptions) => boolean | undefined;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const SIGNIFICANT_STATUSES = new Set(["passed", "failed", "broken"]);
|
|
2
|
+
export const getTestFlakiness = (current, history, options = {}) => {
|
|
3
|
+
const { historyDepth = 10, stabilizationPeriod = 5 } = options;
|
|
4
|
+
if (historyDepth === -1 || !SIGNIFICANT_STATUSES.has(current.status)) {
|
|
5
|
+
return undefined;
|
|
6
|
+
}
|
|
7
|
+
const statuses = [];
|
|
8
|
+
for (const result of history) {
|
|
9
|
+
if (result === undefined) {
|
|
10
|
+
break;
|
|
11
|
+
}
|
|
12
|
+
if (result.id === current.id || !SIGNIFICANT_STATUSES.has(result.status)) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
statuses.push(result.status);
|
|
16
|
+
if (historyDepth > 0 && statuses.length === historyDepth) {
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (statuses.length === 0) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
statuses.reverse();
|
|
24
|
+
statuses.push(current.status);
|
|
25
|
+
const period = historyDepth > 0 ? Math.min(stabilizationPeriod, historyDepth + 1) : stabilizationPeriod;
|
|
26
|
+
let anchor = 0;
|
|
27
|
+
let streak = 0;
|
|
28
|
+
for (let index = 0; index < statuses.length; index++) {
|
|
29
|
+
streak = index > 0 && statuses[index] === statuses[index - 1] ? streak + 1 : 1;
|
|
30
|
+
if (streak >= period) {
|
|
31
|
+
anchor = index;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
let changes = 0;
|
|
35
|
+
for (let index = anchor + 1; index < statuses.length; index++) {
|
|
36
|
+
if (statuses[index] !== statuses[index - 1]) {
|
|
37
|
+
changes++;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (changes <= 1) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return !(changes === 2 && statuses[anchor] === "passed" && current.status === "passed");
|
|
44
|
+
};
|
package/dist/utils/status.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { TestStatus } from "../model.js";
|
|
1
|
+
import type { TestResult, TestStatus } from "../model.js";
|
|
2
2
|
export declare const StatusByPriority: TestStatus[];
|
|
3
3
|
export declare const statusToPriority: (status: TestStatus | undefined) => number;
|
|
4
4
|
export declare const getWorstStatus: (items: TestStatus[]) => TestStatus | undefined;
|
|
5
|
+
export declare const hasRetriesStatusChange: (current: Pick<TestResult, "status">, retries: readonly Pick<TestResult, "status">[]) => boolean;
|
package/dist/utils/status.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const retryStatusChangeStatuses = new Set(["failed", "broken", "passed"]);
|
|
1
2
|
export const StatusByPriority = ["failed", "broken", "passed", "skipped", "unknown"];
|
|
2
3
|
export const statusToPriority = (status) => {
|
|
3
4
|
if (!status) {
|
|
@@ -11,3 +12,5 @@ export const getWorstStatus = (items) => {
|
|
|
11
12
|
}
|
|
12
13
|
return items.sort((a, b) => statusToPriority(a) - statusToPriority(b))[0];
|
|
13
14
|
};
|
|
15
|
+
export const hasRetriesStatusChange = (current, retries) => retryStatusChangeStatuses.has(current.status) &&
|
|
16
|
+
retries.some(({ status }) => retryStatusChangeStatuses.has(status) && status !== current.status);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allurereport/core-api",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.22.0",
|
|
4
4
|
"description": "Allure Core API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"allure"
|
|
@@ -21,22 +21,27 @@
|
|
|
21
21
|
"scripts": {
|
|
22
22
|
"build": "run clean && tsc --project ./tsconfig.json",
|
|
23
23
|
"clean": "rimraf ./dist",
|
|
24
|
-
"test": "rimraf
|
|
25
|
-
"
|
|
26
|
-
"lint
|
|
24
|
+
"test": "rimraf out && vp test run",
|
|
25
|
+
"test:unit": "yarn test",
|
|
26
|
+
"lint": "vp lint --import-plugin src test features stories",
|
|
27
|
+
"lint:fix": "vp lint --import-plugin --fix src test features stories"
|
|
27
28
|
},
|
|
28
29
|
"dependencies": {
|
|
29
30
|
"d3-shape": "^3.2.0"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
33
|
+
"@allurereport/common-config": "3.22.0",
|
|
32
34
|
"@types/d3-shape": "^3.1.8",
|
|
33
35
|
"@types/node": "^20",
|
|
36
|
+
"@vitest/coverage-istanbul": "5.0.4",
|
|
34
37
|
"@vitest/runner": "^2",
|
|
35
|
-
"@vitest/snapshot": "
|
|
38
|
+
"@vitest/snapshot": "5.0.4",
|
|
36
39
|
"allure-js-commons": "^3",
|
|
37
40
|
"allure-vitest": "^3",
|
|
38
41
|
"rimraf": "^6",
|
|
39
42
|
"typescript": "^5",
|
|
40
|
-
"
|
|
43
|
+
"vite": "@voidzero-dev/vite-plus-core@1.2.0",
|
|
44
|
+
"vite-plus": "1.2.0",
|
|
45
|
+
"vitest": "5.0.4"
|
|
41
46
|
}
|
|
42
47
|
}
|