@allurereport/web-awesome 3.0.1 → 3.2.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/multi/173.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/174.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/252.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/282.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/29.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/416.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/527.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/600.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/605.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/638.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/672.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/686.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/725.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/741.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/749.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/755.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/894.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/943.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/980.app-d0210ed2e64d38a2ee8e.js +1 -0
- package/dist/multi/app-d0210ed2e64d38a2ee8e.js +2 -0
- package/dist/multi/{app-bae2a0fe5738d77cd976.js.LICENSE.txt → app-d0210ed2e64d38a2ee8e.js.LICENSE.txt} +7 -0
- package/dist/multi/manifest.json +21 -21
- package/dist/multi/styles-13107bbe6906beabc50f.css +49 -0
- package/dist/single/app-01fed10ad5f9083fd39c.js +2 -0
- package/dist/single/{app-996d3b5869f8fc942b66.js.LICENSE.txt → app-01fed10ad5f9083fd39c.js.LICENSE.txt} +7 -0
- package/dist/single/manifest.json +1 -1
- package/package.json +9 -11
- package/src/assets/scss/vars.scss +3 -0
- package/src/components/BaseLayout/index.tsx +25 -21
- package/src/components/BaseLayout/styles.scss +1 -0
- package/src/components/Charts/index.tsx +10 -7
- package/src/components/Footer/FooterVersion.tsx +14 -8
- package/src/components/Header/index.tsx +9 -7
- package/src/components/HeaderControls/index.tsx +5 -2
- package/src/components/MainReport/index.tsx +52 -47
- package/src/components/MainReport/styles.scss +1 -0
- package/src/components/Metadata/index.tsx +98 -7
- package/src/components/Metadata/styles.scss +10 -0
- package/src/components/ReportBody/HeaderActions.tsx +4 -13
- package/src/components/ReportBody/SortBy.tsx +27 -13
- package/src/components/ReportBody/index.tsx +1 -1
- package/src/components/ReportBody/styles.scss +4 -1
- package/src/components/ReportFilters/BaseFilters.tsx +345 -0
- package/src/components/ReportFilters/RetryFlaky.tsx +29 -0
- package/src/components/ReportFilters/TagsFilter.tsx +41 -0
- package/src/components/ReportFilters/TransitionFilter.tsx +49 -0
- package/src/components/ReportFilters/index.tsx +44 -0
- package/src/components/ReportFilters/styles.scss +55 -0
- package/src/components/ReportQualityGateResults/index.tsx +77 -19
- package/src/components/ReportQualityGateResults/styles.scss +13 -0
- package/src/components/ReportSearch/index.tsx +29 -0
- package/src/components/ReportTabs/index.tsx +1 -1
- package/src/components/SectionPicker/index.tsx +1 -1
- package/src/components/SplitLayout/index.tsx +7 -3
- package/src/components/TestResult/TrDescription/index.tsx +60 -10
- package/src/components/TestResult/TrDescription/styles.scss +4 -0
- package/src/components/TestResult/TrEnvironmentItem/index.tsx +2 -2
- package/src/components/TestResult/TrError/TrDiff.tsx +2 -6
- package/src/components/TestResult/TrError/styles.scss +4 -0
- package/src/components/TestResult/TrHeader/TrBreadcrumbs.tsx +2 -2
- package/src/components/TestResult/TrHistory/TrHistoryItem.tsx +38 -7
- package/src/components/TestResult/TrHistory/index.tsx +18 -8
- package/src/components/TestResult/TrHistory/styles.scss +4 -7
- package/src/components/TestResult/TrInfo/styles.scss +1 -0
- package/src/components/TestResult/TrLinks/index.tsx +4 -4
- package/src/components/TestResult/TrNavigation/index.tsx +109 -68
- package/src/components/TestResult/TrNavigation/styles.scss +15 -25
- package/src/components/TestResult/TrOverview.tsx +3 -2
- package/src/components/TestResult/TrPwTraces/PwTraceButton.tsx +1 -8
- package/src/components/TestResult/TrRetriesView/TrRetriesItem.tsx +2 -3
- package/src/components/TestResult/TrRetriesView/index.tsx +4 -3
- package/src/components/TestResult/TrSteps/TrAttachment.tsx +5 -3
- package/src/components/TestResult/TrSteps/TrAttachmentInfo.tsx +10 -3
- package/src/components/TestResult/TrTabs/index.tsx +7 -23
- package/src/components/TestResult/index.tsx +9 -4
- package/src/components/TestResult/styles.scss +1 -0
- package/src/components/Timeline/index.tsx +2 -5
- package/src/components/Tree/index.tsx +14 -9
- package/src/index.html +19 -18
- package/src/index.tsx +20 -27
- package/src/locales/az.json +42 -13
- package/src/locales/de.json +42 -13
- package/src/locales/en.json +42 -13
- package/src/locales/es.json +42 -13
- package/src/locales/fr.json +42 -13
- package/src/locales/he.json +42 -13
- package/src/locales/hy.json +42 -13
- package/src/locales/it.json +42 -13
- package/src/locales/ja.json +42 -13
- package/src/locales/ka.json +42 -13
- package/src/locales/kr.json +42 -13
- package/src/locales/nl.json +42 -13
- package/src/locales/pl.json +42 -13
- package/src/locales/pt.json +42 -13
- package/src/locales/ru.json +42 -13
- package/src/locales/sv.json +42 -13
- package/src/locales/tr.json +42 -13
- package/src/locales/{ua.json → uk.json} +42 -13
- package/src/locales/zh.json +42 -13
- package/src/stores/chart.ts +2 -2
- package/src/stores/env.ts +6 -6
- package/src/stores/envInfo.ts +2 -2
- package/src/stores/globals.ts +1 -1
- package/src/stores/index.ts +0 -1
- package/src/stores/layout.ts +20 -11
- package/src/stores/locale.ts +71 -38
- package/src/stores/qualityGate.ts +4 -4
- package/src/stores/router.ts +25 -91
- package/src/stores/sections.ts +32 -45
- package/src/stores/stats.ts +4 -4
- package/src/stores/testResult.ts +5 -0
- package/src/stores/testResults.ts +7 -5
- package/src/stores/timeline.ts +5 -2
- package/src/stores/tree.ts +20 -13
- package/src/stores/treeFilters/actions.ts +48 -52
- package/src/stores/treeFilters/constants.ts +11 -5
- package/src/stores/treeFilters/model.ts +51 -0
- package/src/stores/treeFilters/store.ts +260 -60
- package/src/stores/treeFilters/utils.ts +132 -0
- package/src/stores/treeSort.ts +71 -0
- package/src/stores/variables.ts +3 -3
- package/src/utils/ownerAddress.ts +92 -0
- package/src/utils/time.ts +16 -2
- package/src/utils/treeFilters.ts +48 -66
- package/test/components/Header.test.tsx +49 -58
- package/test/utils/ownerAddress.test.ts +89 -0
- package/test/utils/treeFilters.test.ts +18 -321
- package/types.d.ts +3 -2
- package/dist/multi/173.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/174.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/252.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/282.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/29.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/416.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/527.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/600.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/605.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/638.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/672.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/686.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/725.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/741.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/755.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/894.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/91.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/943.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/980.app-bae2a0fe5738d77cd976.js +0 -1
- package/dist/multi/app-bae2a0fe5738d77cd976.js +0 -2
- package/dist/multi/styles-bbf68b2ba63c38b53c38.css +0 -48
- package/dist/single/app-996d3b5869f8fc942b66.js +0 -2
- package/src/components/ReportBody/Filters.tsx +0 -122
- package/src/stores/theme.ts +0 -30
- package/src/stores/treeFilters/index.ts +0 -3
- package/src/stores/treeFilters/types.ts +0 -12
- package/test/stores/treeFilters.test.ts +0 -302
package/src/stores/layout.ts
CHANGED
|
@@ -2,7 +2,26 @@ import { getReportOptions } from "@allurereport/web-commons";
|
|
|
2
2
|
import { computed, signal } from "@preact/signals";
|
|
3
3
|
import type { AwesomeReportOptions, Layout } from "types";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const reportOptions = getReportOptions<AwesomeReportOptions>();
|
|
6
|
+
|
|
7
|
+
const DEFAULT_LAYOUT = "base";
|
|
8
|
+
|
|
9
|
+
const getInitialLayout = (): Layout => {
|
|
10
|
+
if (typeof window === "undefined") {
|
|
11
|
+
return DEFAULT_LAYOUT;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const lsLayout = localStorage.getItem("layout") as Layout | null;
|
|
15
|
+
|
|
16
|
+
if (lsLayout !== null) {
|
|
17
|
+
return lsLayout;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return lsLayout ?? reportOptions?.layout ?? DEFAULT_LAYOUT;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const layoutStore = signal<Layout>(getInitialLayout());
|
|
24
|
+
|
|
6
25
|
export const isLayoutLoading = signal(false);
|
|
7
26
|
|
|
8
27
|
export const setLayout = (newLayout: Layout): void => {
|
|
@@ -24,13 +43,3 @@ export const toggleLayout = () => {
|
|
|
24
43
|
};
|
|
25
44
|
|
|
26
45
|
export const isSplitMode = computed(() => layoutStore.value === "split");
|
|
27
|
-
|
|
28
|
-
export const getLayout = () => {
|
|
29
|
-
const { layout } = getReportOptions<AwesomeReportOptions>() ?? {};
|
|
30
|
-
const layoutFromLS = window.localStorage.getItem("layout") || (layout as Layout) || "base";
|
|
31
|
-
|
|
32
|
-
if (layoutFromLS) {
|
|
33
|
-
setLayout(layoutFromLS as Layout);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
};
|
package/src/stores/locale.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { formatDuration } from "@allurereport/core-api";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_LOCALE,
|
|
4
|
+
LANG_LOCALE,
|
|
5
|
+
type LangLocale,
|
|
6
|
+
getLocaleDateTimeOverride,
|
|
7
|
+
getReportOptions,
|
|
8
|
+
} from "@allurereport/web-commons";
|
|
3
9
|
import { computed, signal } from "@preact/signals";
|
|
4
10
|
import i18next, { type TOptions } from "i18next";
|
|
5
11
|
import type { AwesomeReportOptions } from "types";
|
|
@@ -8,7 +14,6 @@ const namespaces = [
|
|
|
8
14
|
"empty",
|
|
9
15
|
"execution",
|
|
10
16
|
"filters",
|
|
11
|
-
"filters.description",
|
|
12
17
|
"search",
|
|
13
18
|
"severity",
|
|
14
19
|
"sort-by",
|
|
@@ -28,6 +33,8 @@ const namespaces = [
|
|
|
28
33
|
"sections",
|
|
29
34
|
"timeline",
|
|
30
35
|
"transitions",
|
|
36
|
+
"trHistory",
|
|
37
|
+
"attachments",
|
|
31
38
|
] as const;
|
|
32
39
|
|
|
33
40
|
export const currentLocale = signal<LangLocale>("en" as LangLocale);
|
|
@@ -49,7 +56,8 @@ export const waitForI18next = i18next
|
|
|
49
56
|
namespace: string,
|
|
50
57
|
callback: (errorValue: unknown, translations: null) => void,
|
|
51
58
|
) => {
|
|
52
|
-
|
|
59
|
+
const loadLocale = language === "en-iso" ? "en" : language;
|
|
60
|
+
await import(`@/locales/${loadLocale}.json`)
|
|
53
61
|
.then((resources: Record<string, null>) => {
|
|
54
62
|
callback(null, resources[namespace]);
|
|
55
63
|
})
|
|
@@ -65,43 +73,68 @@ export const waitForI18next = i18next
|
|
|
65
73
|
interpolation: { escapeValue: false },
|
|
66
74
|
})
|
|
67
75
|
.then(() => {
|
|
68
|
-
i18next.services.formatter.add("capitalize", (value) => {
|
|
76
|
+
i18next.services.formatter.add("capitalize", (value: string) => {
|
|
69
77
|
return value.charAt(0).toLocaleUpperCase() + value.slice(1);
|
|
70
78
|
});
|
|
71
|
-
i18next.services.formatter.add(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
79
|
+
i18next.services.formatter.add(
|
|
80
|
+
"timestamp_date",
|
|
81
|
+
(value: number, lng: string, options?: Intl.DateTimeFormatOptions) => {
|
|
82
|
+
const override = getLocaleDateTimeOverride(lng, "date");
|
|
83
|
+
const formatter = new Intl.DateTimeFormat(override?.locale ?? lng, {
|
|
84
|
+
...options,
|
|
85
|
+
month: "numeric",
|
|
86
|
+
day: "numeric",
|
|
87
|
+
year: "numeric",
|
|
88
|
+
...(override?.options ?? {}),
|
|
89
|
+
});
|
|
90
|
+
const formatted = formatter.format(value);
|
|
91
|
+
return override?.stripComma ? formatted.replace(",", "") : formatted;
|
|
92
|
+
},
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
i18next.services.formatter.add(
|
|
96
|
+
"timestamp_long",
|
|
97
|
+
(value: number, lng: string, options?: Intl.DateTimeFormatOptions) => {
|
|
98
|
+
const override = getLocaleDateTimeOverride(lng, "dateTime");
|
|
99
|
+
const formatter = new Intl.DateTimeFormat(override?.locale ?? lng, {
|
|
100
|
+
...options,
|
|
101
|
+
month: "numeric",
|
|
102
|
+
day: "numeric",
|
|
103
|
+
year: "numeric",
|
|
104
|
+
hour: "numeric",
|
|
105
|
+
minute: "numeric",
|
|
106
|
+
second: "numeric",
|
|
107
|
+
hour12: false,
|
|
108
|
+
...(override?.options ?? {}),
|
|
109
|
+
});
|
|
110
|
+
const formatted = formatter.format(value);
|
|
111
|
+
if (override?.includeAtSeparator === false || override?.stripComma) {
|
|
112
|
+
return formatted.replace(",", "");
|
|
113
|
+
}
|
|
114
|
+
return formatted.replace(",", ` ${i18next.t("ui:at")}`);
|
|
115
|
+
},
|
|
116
|
+
);
|
|
117
|
+
i18next.services.formatter.add(
|
|
118
|
+
"timestamp_long_no_seconds",
|
|
119
|
+
(value: number, lng: string, options?: Intl.DateTimeFormatOptions) => {
|
|
120
|
+
const override = getLocaleDateTimeOverride(lng, "dateTimeNoSeconds");
|
|
121
|
+
const formatter = new Intl.DateTimeFormat(override?.locale ?? lng, {
|
|
122
|
+
...options,
|
|
123
|
+
month: "numeric",
|
|
124
|
+
day: "numeric",
|
|
125
|
+
year: "numeric",
|
|
126
|
+
hour: "numeric",
|
|
127
|
+
minute: "numeric",
|
|
128
|
+
hour12: false,
|
|
129
|
+
...(override?.options ?? {}),
|
|
130
|
+
});
|
|
131
|
+
const formatted = formatter.format(value);
|
|
132
|
+
if (override?.includeAtSeparator === false || override?.stripComma) {
|
|
133
|
+
return formatted.replace(",", "");
|
|
134
|
+
}
|
|
135
|
+
return formatted.replace(",", ` ${i18next.t("ui:at")}`);
|
|
136
|
+
},
|
|
137
|
+
);
|
|
105
138
|
i18next.services.formatter.add("format_duration", (value: number) => {
|
|
106
139
|
return formatDuration(value);
|
|
107
140
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { QualityGateValidationResult } from "@allurereport/plugin-api";
|
|
1
|
+
import type { QualityGateValidationResult } from "@allurereport/plugin-api";
|
|
2
2
|
import { fetchReportJsonData } from "@allurereport/web-commons";
|
|
3
3
|
import { signal } from "@preact/signals";
|
|
4
4
|
import { type StoreSignalState } from "./types";
|
|
5
5
|
|
|
6
|
-
export const qualityGateStore = signal<StoreSignalState<QualityGateValidationResult[]
|
|
6
|
+
export const qualityGateStore = signal<StoreSignalState<Record<string, QualityGateValidationResult[]>>>({
|
|
7
7
|
loading: true,
|
|
8
8
|
error: undefined,
|
|
9
9
|
data: undefined,
|
|
@@ -11,7 +11,7 @@ export const qualityGateStore = signal<StoreSignalState<QualityGateValidationRes
|
|
|
11
11
|
|
|
12
12
|
export const fetchQualityGateResults = async () => {
|
|
13
13
|
try {
|
|
14
|
-
const data = await fetchReportJsonData<QualityGateValidationResult[]
|
|
14
|
+
const data = await fetchReportJsonData<Record<string, QualityGateValidationResult[]>>("widgets/quality-gate.json");
|
|
15
15
|
|
|
16
16
|
qualityGateStore.value = {
|
|
17
17
|
data,
|
|
@@ -20,7 +20,7 @@ export const fetchQualityGateResults = async () => {
|
|
|
20
20
|
};
|
|
21
21
|
} catch (err) {
|
|
22
22
|
qualityGateStore.value = {
|
|
23
|
-
...qualityGateStore.
|
|
23
|
+
...qualityGateStore.peek(),
|
|
24
24
|
error: err.message,
|
|
25
25
|
loading: false,
|
|
26
26
|
};
|
package/src/stores/router.ts
CHANGED
|
@@ -1,108 +1,42 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRoute, navigateTo as routerNavigateTo } from "@allurereport/web-commons";
|
|
2
|
+
import { computed } from "@preact/signals";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
params?: {
|
|
6
|
-
testResultId?: string | null;
|
|
7
|
-
subTab?: string | null;
|
|
8
|
-
};
|
|
4
|
+
export const navigateToTestResult = (params: { testResultId: string; tab?: string }) => {
|
|
5
|
+
routerNavigateTo({ path: "/:testResultId/:tab?", params, keepSearchParams: true });
|
|
9
6
|
};
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
params?: {
|
|
14
|
-
testResultId?: string | null;
|
|
15
|
-
subTab?: string | null;
|
|
16
|
-
};
|
|
8
|
+
export const navigateToTestResultTab = (params: { testResultId: string; tab: string }) => {
|
|
9
|
+
routerNavigateTo({ path: "/:testResultId/:tab?", params, keepSearchParams: true, replace: true });
|
|
17
10
|
};
|
|
18
11
|
|
|
19
|
-
export const
|
|
20
|
-
|
|
21
|
-
const parts = hash.split("/").filter(Boolean);
|
|
22
|
-
const [first, second] = parts;
|
|
23
|
-
|
|
24
|
-
if (parts.length === 0) {
|
|
25
|
-
return {};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (parts.length === 1) {
|
|
29
|
-
if (/^[a-f0-9]{32,}$/.test(first)) {
|
|
30
|
-
return { params: { testResultId: first } };
|
|
31
|
-
}
|
|
32
|
-
return { category: first || "", params: { testResultId: second } };
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (parts.length === 2) {
|
|
36
|
-
if (/^[a-f0-9]{32,}$/.test(first)) {
|
|
37
|
-
return {
|
|
38
|
-
params: {
|
|
39
|
-
testResultId: first,
|
|
40
|
-
subTab: second,
|
|
41
|
-
},
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
category: first,
|
|
47
|
-
params: {
|
|
48
|
-
testResultId: second,
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (parts.length === 3) {
|
|
54
|
-
const [category, testResultId, subTab] = parts;
|
|
55
|
-
return { category, params: { testResultId, subTab } };
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return {};
|
|
12
|
+
export const navigateToRoot = () => {
|
|
13
|
+
routerNavigateTo({ path: "/", keepSearchParams: true });
|
|
59
14
|
};
|
|
60
15
|
|
|
61
|
-
export const
|
|
62
|
-
|
|
63
|
-
export const handleHashChange = () => {
|
|
64
|
-
const newRoute = parseHash();
|
|
65
|
-
|
|
66
|
-
if (
|
|
67
|
-
newRoute.category !== route.value?.category ||
|
|
68
|
-
newRoute.params?.testResultId !== route.value.params?.testResultId ||
|
|
69
|
-
newRoute.params?.subTab !== route.value.params?.subTab
|
|
70
|
-
) {
|
|
71
|
-
route.value = { ...newRoute };
|
|
72
|
-
}
|
|
16
|
+
export const navigateToSection = (params: { section: "timeline" | "charts" }) => {
|
|
17
|
+
routerNavigateTo({ path: "/:section", params, keepSearchParams: true, replace: false });
|
|
73
18
|
};
|
|
74
19
|
|
|
75
|
-
|
|
76
|
-
let newHash = "";
|
|
20
|
+
const sections = ["charts", "timeline"];
|
|
77
21
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
22
|
+
export const testResultRoute = computed(() =>
|
|
23
|
+
createRoute<{ testResultId: string; tab?: string }>("/:testResultId/:tab?", ({ params }) => {
|
|
24
|
+
return params.testResultId && !sections.includes(params.testResultId);
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
83
27
|
|
|
84
|
-
|
|
85
|
-
parts.push(category);
|
|
86
|
-
}
|
|
28
|
+
export const rootRoute = computed(() => createRoute<{}>("/"));
|
|
87
29
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
30
|
+
export const sectionRoute = computed(() =>
|
|
31
|
+
createRoute<{ section: "timeline" | "charts" }>("/:section", ({ params }) => {
|
|
32
|
+
return sections.includes(params.section);
|
|
33
|
+
}),
|
|
34
|
+
);
|
|
91
35
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
newHash = parts.join("/");
|
|
36
|
+
export const openInNewTab = (path: string) => {
|
|
37
|
+
if (typeof window === "undefined") {
|
|
38
|
+
return;
|
|
97
39
|
}
|
|
98
40
|
|
|
99
|
-
history.pushState(null, "", `#${newHash}`);
|
|
100
|
-
handleHashChange();
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
export const openInNewTab = (path: string) => {
|
|
104
41
|
window.open(`#${path}`, "_blank");
|
|
105
42
|
};
|
|
106
|
-
|
|
107
|
-
export const activeTab = computed(() => route.value.category || "");
|
|
108
|
-
export const activeSubTab = computed(() => route.value.params?.subTab || "overview");
|
package/src/stores/sections.ts
CHANGED
|
@@ -1,63 +1,50 @@
|
|
|
1
1
|
import { getReportOptions } from "@allurereport/web-commons";
|
|
2
|
-
import {
|
|
3
|
-
import { navigateTo, parseHash, route } from "@/stores/router";
|
|
2
|
+
import { computed, effect } from "@preact/signals";
|
|
4
3
|
import type { AwesomeReportOptions } from "../../types.js";
|
|
4
|
+
import { navigateToRoot, navigateToSection, sectionRoute } from "./router";
|
|
5
5
|
|
|
6
6
|
const DEFAULT_SECTION = "default";
|
|
7
|
-
type Section = string;
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
export const availableSections = signal<Section[]>([]);
|
|
8
|
+
type Section = "timeline" | "charts" | "default";
|
|
11
9
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
document.documentElement.setAttribute("data-section", section);
|
|
15
|
-
globalThis.localStorage.setItem("chosenSection", section);
|
|
16
|
-
};
|
|
10
|
+
const reportOptions = getReportOptions<AwesomeReportOptions>();
|
|
11
|
+
const defaultSectionFromReportOptions: Section = (reportOptions?.defaultSection as Section) ?? "default";
|
|
17
12
|
|
|
18
|
-
export const
|
|
19
|
-
const isDefaultSection = chosenSection === DEFAULT_SECTION;
|
|
20
|
-
const isValidSection = availableSections.value?.includes(chosenSection);
|
|
21
|
-
const isSectionChanged = currentSection.value !== chosenSection;
|
|
13
|
+
export const availableSections = (reportOptions?.sections ?? []) as Section[];
|
|
22
14
|
|
|
23
|
-
|
|
15
|
+
const onInit = () => {
|
|
16
|
+
const isSectionRoute = sectionRoute.peek().matches;
|
|
17
|
+
const isDefaultSection = defaultSectionFromReportOptions === DEFAULT_SECTION;
|
|
18
|
+
const isValidSection = availableSections.includes(defaultSectionFromReportOptions);
|
|
24
19
|
|
|
25
|
-
if (isDefaultSection) {
|
|
26
|
-
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (isSectionChanged && isValidSection) {
|
|
31
|
-
navigateTo({ category: chosenSection });
|
|
20
|
+
if (!isSectionRoute && !isDefaultSection && isValidSection) {
|
|
21
|
+
navigateToSection({ section: defaultSectionFromReportOptions });
|
|
32
22
|
}
|
|
33
23
|
};
|
|
34
24
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
currentSection.value = sectionFromUrl || sectionFromLS;
|
|
45
|
-
|
|
46
|
-
if (category) {
|
|
47
|
-
setSection(category);
|
|
48
|
-
return;
|
|
25
|
+
onInit();
|
|
26
|
+
|
|
27
|
+
export const currentSection = computed(() => sectionRoute.value.params.section ?? "default");
|
|
28
|
+
|
|
29
|
+
effect(() => {
|
|
30
|
+
const section = currentSection.value;
|
|
31
|
+
|
|
32
|
+
if (section) {
|
|
33
|
+
document.documentElement.setAttribute("data-section", section);
|
|
49
34
|
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export const setSection = (chosenSection: Section | string): void => {
|
|
38
|
+
const isDefaultSection = chosenSection === DEFAULT_SECTION;
|
|
39
|
+
const isValidSection = availableSections.includes(chosenSection as Section);
|
|
40
|
+
const isSectionChanged = currentSection.peek() !== chosenSection;
|
|
50
41
|
|
|
51
|
-
if (
|
|
52
|
-
|
|
42
|
+
if (isDefaultSection) {
|
|
43
|
+
navigateToRoot();
|
|
53
44
|
return;
|
|
54
45
|
}
|
|
55
46
|
|
|
56
|
-
|
|
47
|
+
if (isSectionChanged && isValidSection) {
|
|
48
|
+
navigateToSection({ section: chosenSection as "timeline" | "charts" });
|
|
49
|
+
}
|
|
57
50
|
};
|
|
58
|
-
|
|
59
|
-
effect(() => {
|
|
60
|
-
const category = route.value.category;
|
|
61
|
-
|
|
62
|
-
setSection(category || "");
|
|
63
|
-
});
|
package/src/stores/stats.ts
CHANGED
|
@@ -20,7 +20,7 @@ export const statsByEnvStore = signal<StoreSignalState<Record<string, Statistic>
|
|
|
20
20
|
|
|
21
21
|
export const fetchReportStats = async () => {
|
|
22
22
|
reportStatsStore.value = {
|
|
23
|
-
...reportStatsStore.
|
|
23
|
+
...reportStatsStore.peek(),
|
|
24
24
|
loading: true,
|
|
25
25
|
error: undefined,
|
|
26
26
|
};
|
|
@@ -43,7 +43,7 @@ export const fetchReportStats = async () => {
|
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
export const fetchEnvStats = async (envs: string[]) => {
|
|
46
|
-
const envsToFetch = envs.filter((env) => !statsByEnvStore.
|
|
46
|
+
const envsToFetch = envs.filter((env) => !statsByEnvStore.peek().data?.[env]);
|
|
47
47
|
|
|
48
48
|
// all envs have already been fetched
|
|
49
49
|
if (envsToFetch.length === 0) {
|
|
@@ -51,7 +51,7 @@ export const fetchEnvStats = async (envs: string[]) => {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
statsByEnvStore.value = {
|
|
54
|
-
...statsByEnvStore.
|
|
54
|
+
...statsByEnvStore.peek(),
|
|
55
55
|
loading: true,
|
|
56
56
|
error: undefined,
|
|
57
57
|
};
|
|
@@ -73,7 +73,7 @@ export const fetchEnvStats = async (envs: string[]) => {
|
|
|
73
73
|
};
|
|
74
74
|
} catch (err) {
|
|
75
75
|
statsByEnvStore.value = {
|
|
76
|
-
...statsByEnvStore.
|
|
76
|
+
...statsByEnvStore.peek(),
|
|
77
77
|
error: err.message,
|
|
78
78
|
loading: false,
|
|
79
79
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { computed } from "@preact/signals";
|
|
2
|
+
import { testResultRoute } from "./router";
|
|
3
|
+
|
|
4
|
+
export const trCurrentTab = computed(() => testResultRoute.value.params.tab ?? "overview");
|
|
5
|
+
export const currentTrId = computed(() => testResultRoute.value.params.testResultId);
|
|
@@ -32,7 +32,7 @@ export const fetchTestResultNav = async (env?: string) => {
|
|
|
32
32
|
};
|
|
33
33
|
} catch (err) {
|
|
34
34
|
testResultNavStore.value = {
|
|
35
|
-
...testResultNavStore.
|
|
35
|
+
...testResultNavStore.peek(),
|
|
36
36
|
error: err.message,
|
|
37
37
|
loading: false,
|
|
38
38
|
};
|
|
@@ -40,12 +40,14 @@ export const fetchTestResultNav = async (env?: string) => {
|
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
export const fetchTestResult = async (testResultId: string) => {
|
|
43
|
-
|
|
43
|
+
const trData = testResultStore.peek().data;
|
|
44
|
+
|
|
45
|
+
if (!testResultId || (trData && testResultId in trData)) {
|
|
44
46
|
return;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
testResultStore.value = {
|
|
48
|
-
...testResultStore.
|
|
50
|
+
...testResultStore.peek(),
|
|
49
51
|
loading: true,
|
|
50
52
|
error: undefined,
|
|
51
53
|
};
|
|
@@ -56,13 +58,13 @@ export const fetchTestResult = async (testResultId: string) => {
|
|
|
56
58
|
});
|
|
57
59
|
|
|
58
60
|
testResultStore.value = {
|
|
59
|
-
data: { ...testResultStore.
|
|
61
|
+
data: { ...testResultStore.peek().data, [testResultId]: data },
|
|
60
62
|
error: undefined,
|
|
61
63
|
loading: false,
|
|
62
64
|
};
|
|
63
65
|
} catch (err) {
|
|
64
66
|
testResultStore.value = {
|
|
65
|
-
...testResultStore.
|
|
67
|
+
...testResultStore.peek(),
|
|
66
68
|
error: err.message,
|
|
67
69
|
loading: false,
|
|
68
70
|
};
|
package/src/stores/timeline.ts
CHANGED
|
@@ -5,8 +5,11 @@ import type { StoreSignalState } from "@/stores/types";
|
|
|
5
5
|
|
|
6
6
|
export type TimlineTr = Pick<
|
|
7
7
|
TestResult,
|
|
8
|
-
"id" | "name" | "status" | "flaky" | "hidden" | "
|
|
9
|
-
|
|
8
|
+
"id" | "name" | "status" | "flaky" | "hidden" | "environment" | "start" | "duration"
|
|
9
|
+
> & {
|
|
10
|
+
host: string;
|
|
11
|
+
thread: string;
|
|
12
|
+
};
|
|
10
13
|
|
|
11
14
|
export const timelineStore = signal<StoreSignalState<TimlineTr[]>>({
|
|
12
15
|
loading: true,
|
package/src/stores/tree.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { fetchReportJsonData } from "@allurereport/web-commons";
|
|
1
|
+
import { buildFilterPredicate, fetchReportJsonData } from "@allurereport/web-commons";
|
|
2
2
|
import type { RecursiveTree } from "@allurereport/web-components/global";
|
|
3
3
|
import { computed, effect, signal } from "@preact/signals";
|
|
4
4
|
import type { AwesomeTree, AwesomeTreeGroup } from "types";
|
|
5
5
|
import type { StoreSignalState } from "@/stores/types";
|
|
6
6
|
import { loadFromLocalStorage } from "@/utils/loadFromLocalStorage";
|
|
7
7
|
import { createRecursiveTree, isRecursiveTreeEmpty } from "@/utils/treeFilters";
|
|
8
|
-
import {
|
|
8
|
+
import { treeFilters } from "./treeFilters/store";
|
|
9
|
+
import { sortBy } from "./treeSort";
|
|
9
10
|
|
|
10
11
|
export const treeStore = signal<StoreSignalState<Record<string, AwesomeTree>>>({
|
|
11
12
|
loading: true,
|
|
@@ -36,7 +37,7 @@ export const toggleTree = (id: string) => {
|
|
|
36
37
|
};
|
|
37
38
|
|
|
38
39
|
export const fetchEnvTreesData = async (envs: string[]) => {
|
|
39
|
-
const envsToFetch = envs.filter((env) => !treeStore.
|
|
40
|
+
const envsToFetch = envs.filter((env) => !treeStore.peek().data?.[env]);
|
|
40
41
|
|
|
41
42
|
// all envs have already been fetched
|
|
42
43
|
if (envsToFetch.length === 0) {
|
|
@@ -44,7 +45,7 @@ export const fetchEnvTreesData = async (envs: string[]) => {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
treeStore.value = {
|
|
47
|
-
...treeStore.
|
|
48
|
+
...treeStore.peek(),
|
|
48
49
|
loading: true,
|
|
49
50
|
error: undefined,
|
|
50
51
|
};
|
|
@@ -54,7 +55,7 @@ export const fetchEnvTreesData = async (envs: string[]) => {
|
|
|
54
55
|
envsToFetch.map((env) => fetchReportJsonData<AwesomeTree>(`widgets/${env}/tree.json`, { bustCache: true })),
|
|
55
56
|
);
|
|
56
57
|
|
|
57
|
-
const previous = treeStore.
|
|
58
|
+
const previous = treeStore.peek().data;
|
|
58
59
|
treeStore.value = {
|
|
59
60
|
data: envsToFetch.reduce(
|
|
60
61
|
(acc, env, index) => {
|
|
@@ -70,7 +71,7 @@ export const fetchEnvTreesData = async (envs: string[]) => {
|
|
|
70
71
|
};
|
|
71
72
|
} catch (e) {
|
|
72
73
|
treeStore.value = {
|
|
73
|
-
...treeStore.
|
|
74
|
+
...treeStore.peek(),
|
|
74
75
|
error: e.message,
|
|
75
76
|
loading: false,
|
|
76
77
|
};
|
|
@@ -79,6 +80,16 @@ export const fetchEnvTreesData = async (envs: string[]) => {
|
|
|
79
80
|
|
|
80
81
|
const treeEntries = computed(() => (treeStore.value.data ? Object.entries(treeStore.value.data) : []));
|
|
81
82
|
|
|
83
|
+
const alwaysTruePredicate = () => true;
|
|
84
|
+
|
|
85
|
+
const filterPredicate = computed(() => {
|
|
86
|
+
if (treeFilters.value.length === 0) {
|
|
87
|
+
return alwaysTruePredicate;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return buildFilterPredicate(treeFilters.value);
|
|
91
|
+
});
|
|
92
|
+
|
|
82
93
|
export const filteredTree = computed(() => {
|
|
83
94
|
return treeEntries.value.reduce(
|
|
84
95
|
(acc, [key, value]) => {
|
|
@@ -87,17 +98,13 @@ export const filteredTree = computed(() => {
|
|
|
87
98
|
}
|
|
88
99
|
|
|
89
100
|
const { root, leavesById, groupsById } = value;
|
|
101
|
+
|
|
90
102
|
const tree = createRecursiveTree({
|
|
91
103
|
group: root as AwesomeTreeGroup,
|
|
92
104
|
leavesById,
|
|
93
105
|
groupsById,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
status: treeStatus.value,
|
|
97
|
-
filter: treeFilter.value,
|
|
98
|
-
sortBy: treeSortBy.value,
|
|
99
|
-
direction: treeDirection.value,
|
|
100
|
-
},
|
|
106
|
+
filterPredicate: filterPredicate.value,
|
|
107
|
+
sortBy: sortBy.value,
|
|
101
108
|
});
|
|
102
109
|
|
|
103
110
|
return Object.assign(acc, {
|