@allurereport/web-awesome 3.1.0 → 3.3.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.
Files changed (131) hide show
  1. package/dist/multi/173.app-8be6acc0a596a2197dbf.js +1 -0
  2. package/dist/multi/174.app-8be6acc0a596a2197dbf.js +1 -0
  3. package/dist/multi/252.app-8be6acc0a596a2197dbf.js +1 -0
  4. package/dist/multi/282.app-8be6acc0a596a2197dbf.js +1 -0
  5. package/dist/multi/29.app-8be6acc0a596a2197dbf.js +1 -0
  6. package/dist/multi/416.app-8be6acc0a596a2197dbf.js +1 -0
  7. package/dist/multi/527.app-8be6acc0a596a2197dbf.js +1 -0
  8. package/dist/multi/600.app-8be6acc0a596a2197dbf.js +1 -0
  9. package/dist/multi/605.app-8be6acc0a596a2197dbf.js +1 -0
  10. package/dist/multi/638.app-8be6acc0a596a2197dbf.js +1 -0
  11. package/dist/multi/672.app-8be6acc0a596a2197dbf.js +1 -0
  12. package/dist/multi/686.app-8be6acc0a596a2197dbf.js +1 -0
  13. package/dist/multi/725.app-8be6acc0a596a2197dbf.js +1 -0
  14. package/dist/multi/741.app-8be6acc0a596a2197dbf.js +1 -0
  15. package/dist/multi/749.app-8be6acc0a596a2197dbf.js +1 -0
  16. package/dist/multi/755.app-8be6acc0a596a2197dbf.js +1 -0
  17. package/dist/multi/894.app-8be6acc0a596a2197dbf.js +1 -0
  18. package/dist/multi/943.app-8be6acc0a596a2197dbf.js +1 -0
  19. package/dist/multi/980.app-8be6acc0a596a2197dbf.js +1 -0
  20. package/dist/multi/app-8be6acc0a596a2197dbf.js +2 -0
  21. package/dist/multi/manifest.json +21 -21
  22. package/dist/multi/{styles-9e390bad7ce54a807a8e.css → styles-0b84e1ef76554ad2db9a.css} +19 -10
  23. package/dist/single/app-8221eb856e47b4ef50d6.js +2 -0
  24. package/dist/single/manifest.json +1 -1
  25. package/package.json +8 -10
  26. package/src/components/BaseLayout/index.tsx +5 -4
  27. package/src/components/Categories/CategoriesTree/index.tsx +14 -0
  28. package/src/components/Categories/CategoriesTree/styles.scss +14 -0
  29. package/src/components/Categories/CategoryHeaderItem/index.tsx +50 -0
  30. package/src/components/Categories/CategoryHeaderItem/styles.scss +32 -0
  31. package/src/components/Categories/CategoryTreeItem/index.tsx +309 -0
  32. package/src/components/Categories/CategoryTreeItem/styles.scss +47 -0
  33. package/src/components/Categories/GroupTreeItem/index.tsx +76 -0
  34. package/src/components/Categories/GroupTreeItem/styles.scss +47 -0
  35. package/src/components/Categories/HistoryTreeItem/index.tsx +71 -0
  36. package/src/components/Categories/HistoryTreeItem/styles.scss +53 -0
  37. package/src/components/Categories/LabelTreeItem/index.tsx +150 -0
  38. package/src/components/Categories/LabelTreeItem/styles.scss +102 -0
  39. package/src/components/Categories/MessageTreeItem/index.tsx +107 -0
  40. package/src/components/Categories/MessageTreeItem/styles.scss +178 -0
  41. package/src/components/Categories/SeverityTreeItem/index.tsx +50 -0
  42. package/src/components/Categories/SeverityTreeItem/styles.scss +12 -0
  43. package/src/components/Categories/sticky.ts +12 -0
  44. package/src/components/Charts/index.tsx +5 -5
  45. package/src/components/Header/index.tsx +4 -2
  46. package/src/components/MainReport/index.tsx +148 -47
  47. package/src/components/Metadata/index.tsx +75 -1
  48. package/src/components/Metadata/styles.scss +10 -0
  49. package/src/components/ReportBody/styles.scss +1 -1
  50. package/src/components/ReportCategories/index.tsx +26 -0
  51. package/src/components/ReportCategories/styles.scss +55 -0
  52. package/src/components/ReportFilters/CategoriesFilter.tsx +41 -0
  53. package/src/components/ReportFilters/index.tsx +12 -1
  54. package/src/components/ReportQualityGateResults/index.tsx +77 -19
  55. package/src/components/ReportQualityGateResults/styles.scss +13 -0
  56. package/src/components/SplitLayout/index.tsx +4 -2
  57. package/src/components/SplitLayout/styles.scss +1 -0
  58. package/src/components/TestResult/TrDescription/index.tsx +60 -10
  59. package/src/components/TestResult/TrDescription/styles.scss +4 -0
  60. package/src/components/TestResult/TrError/TrDiff.tsx +2 -6
  61. package/src/components/TestResult/TrError/styles.scss +4 -0
  62. package/src/components/TestResult/TrInfo/index.tsx +8 -1
  63. package/src/components/TestResult/TrInfo/styles.scss +4 -0
  64. package/src/components/TestResult/TrLinks/index.tsx +4 -4
  65. package/src/components/TestResult/TrOverview.tsx +3 -2
  66. package/src/components/TestResult/TrSeverity/index.tsx +13 -4
  67. package/src/components/TestResult/TrSeverity/styles.scss +1 -0
  68. package/src/components/TestResult/TrTabs/index.tsx +5 -0
  69. package/src/components/Timeline/index.tsx +2 -5
  70. package/src/index.tsx +6 -2
  71. package/src/locales/az.json +108 -79
  72. package/src/locales/de.json +26 -5
  73. package/src/locales/en.json +26 -5
  74. package/src/locales/es.json +26 -5
  75. package/src/locales/fr.json +26 -5
  76. package/src/locales/he.json +26 -5
  77. package/src/locales/hy.json +26 -5
  78. package/src/locales/it.json +26 -5
  79. package/src/locales/ja.json +26 -5
  80. package/src/locales/ka.json +26 -5
  81. package/src/locales/kr.json +26 -5
  82. package/src/locales/nl.json +26 -5
  83. package/src/locales/pl.json +26 -5
  84. package/src/locales/pt.json +26 -5
  85. package/src/locales/ru.json +26 -5
  86. package/src/locales/sv.json +26 -5
  87. package/src/locales/tr.json +26 -5
  88. package/src/locales/{ua.json → uk.json} +26 -5
  89. package/src/locales/zh.json +26 -5
  90. package/src/stores/categories.ts +44 -0
  91. package/src/stores/locale.ts +69 -37
  92. package/src/stores/qualityGate.ts +2 -2
  93. package/src/stores/router.ts +55 -3
  94. package/src/stores/testResult.ts +14 -3
  95. package/src/stores/timeline.ts +5 -2
  96. package/src/stores/treeFilters/actions.ts +10 -1
  97. package/src/stores/treeFilters/constants.ts +1 -0
  98. package/src/stores/treeFilters/model.ts +2 -0
  99. package/src/stores/treeFilters/store.ts +45 -0
  100. package/src/stores/treeFilters/utils.ts +10 -0
  101. package/src/stores/treeSwitcher.ts +9 -0
  102. package/src/utils/ownerAddress.ts +92 -0
  103. package/src/utils/time.ts +16 -2
  104. package/src/utils/treeFilters.ts +16 -9
  105. package/test/utils/ownerAddress.test.ts +89 -0
  106. package/test/utils/treeFilters.test.ts +39 -0
  107. package/types.d.ts +2 -1
  108. package/dist/multi/173.app-79c65c7bff941abcbc51.js +0 -1
  109. package/dist/multi/174.app-79c65c7bff941abcbc51.js +0 -1
  110. package/dist/multi/252.app-79c65c7bff941abcbc51.js +0 -1
  111. package/dist/multi/282.app-79c65c7bff941abcbc51.js +0 -1
  112. package/dist/multi/29.app-79c65c7bff941abcbc51.js +0 -1
  113. package/dist/multi/416.app-79c65c7bff941abcbc51.js +0 -1
  114. package/dist/multi/527.app-79c65c7bff941abcbc51.js +0 -1
  115. package/dist/multi/600.app-79c65c7bff941abcbc51.js +0 -1
  116. package/dist/multi/605.app-79c65c7bff941abcbc51.js +0 -1
  117. package/dist/multi/638.app-79c65c7bff941abcbc51.js +0 -1
  118. package/dist/multi/672.app-79c65c7bff941abcbc51.js +0 -1
  119. package/dist/multi/686.app-79c65c7bff941abcbc51.js +0 -1
  120. package/dist/multi/725.app-79c65c7bff941abcbc51.js +0 -1
  121. package/dist/multi/741.app-79c65c7bff941abcbc51.js +0 -1
  122. package/dist/multi/755.app-79c65c7bff941abcbc51.js +0 -1
  123. package/dist/multi/894.app-79c65c7bff941abcbc51.js +0 -1
  124. package/dist/multi/91.app-79c65c7bff941abcbc51.js +0 -1
  125. package/dist/multi/943.app-79c65c7bff941abcbc51.js +0 -1
  126. package/dist/multi/980.app-79c65c7bff941abcbc51.js +0 -1
  127. package/dist/multi/app-79c65c7bff941abcbc51.js +0 -2
  128. package/dist/single/app-3ca67f29d0f1166c08ca.js +0 -2
  129. package/src/components/SectionTabs/index.tsx +0 -0
  130. /package/dist/multi/{app-79c65c7bff941abcbc51.js.LICENSE.txt → app-8be6acc0a596a2197dbf.js.LICENSE.txt} +0 -0
  131. /package/dist/single/{app-3ca67f29d0f1166c08ca.js.LICENSE.txt → app-8221eb856e47b4ef50d6.js.LICENSE.txt} +0 -0
@@ -1,40 +1,98 @@
1
+ import { DEFAULT_ENVIRONMENT } from "@allurereport/core-api";
2
+ import type { QualityGateValidationResult } from "@allurereport/plugin-api";
1
3
  import { Loadable, SvgIcon, Text, allureIcons } from "@allurereport/web-components";
4
+ import { useState } from "preact/hooks";
5
+ import { MetadataButton } from "@/components/MetadataButton";
2
6
  import { TrError } from "@/components/TestResult/TrError";
3
7
  import { useI18n } from "@/stores";
8
+ import { currentEnvironment } from "@/stores/env";
4
9
  import { qualityGateStore } from "@/stores/qualityGate";
5
10
  import * as styles from "./styles.scss";
6
11
 
12
+ const QualityGateResultsList = ({ results }: { results: QualityGateValidationResult[] }) => (
13
+ <ul className={styles["report-quality-gate-results-list"]} data-testid={"quality-gate-results-section-env-content"}>
14
+ {results.map((result) => (
15
+ <li key={result.rule} data-testid="quality-gate-result">
16
+ <div className={styles["report-quality-gate-result"]}>
17
+ <SvgIcon id={allureIcons.solidXCircle} className={styles["report-quality-gate-result-icon"]} />
18
+ <div className={styles["report-quality-gate-result-content"]}>
19
+ <Text tag="p" size="l" type="ui" bold data-testid="quality-gate-result-rule">
20
+ {result.rule}
21
+ </Text>
22
+ <TrError
23
+ className={styles["report-quality-gate-result-error"]}
24
+ message={result.message}
25
+ data-testid="quality-gate-result-message"
26
+ />
27
+ </div>
28
+ </div>
29
+ </li>
30
+ ))}
31
+ </ul>
32
+ );
33
+
7
34
  export const ReportQualityGateResults = () => {
8
35
  const { t } = useI18n("empty");
36
+ const { t: tEnvironments } = useI18n("environments");
37
+ const [collapsedEnvs, setCollapsedEnvs] = useState<string[]>([]);
9
38
 
10
39
  return (
11
40
  <Loadable
12
41
  source={qualityGateStore}
13
42
  renderData={(results) => {
14
- if (!results.length) {
43
+ if (currentEnvironment.value) {
44
+ const currentEnvResults = results[currentEnvironment.value] ?? [];
45
+
46
+ if (!currentEnvResults.length) {
47
+ return <div className={styles["report-quality-gate-results-empty"]}>{t("no-quality-gate-results")}</div>;
48
+ }
49
+
50
+ return <QualityGateResultsList results={currentEnvResults} />;
51
+ }
52
+
53
+ const entries = Object.entries(results).filter(([, envResults]) => envResults.length > 0);
54
+
55
+ if (!entries.length) {
15
56
  return <div className={styles["report-quality-gate-results-empty"]}>{t("no-quality-gate-results")}</div>;
16
57
  }
17
58
 
59
+ // single default environment
60
+ if (entries.length === 1 && entries[0][0] === DEFAULT_ENVIRONMENT) {
61
+ const currentEnvResults = entries[0][1] ?? [];
62
+
63
+ if (!currentEnvResults.length) {
64
+ return <div className={styles["report-quality-gate-results-empty"]}>{t("no-quality-gate-results")}</div>;
65
+ }
66
+
67
+ return <QualityGateResultsList results={currentEnvResults} />;
68
+ }
69
+
18
70
  return (
19
- <ul className={styles["report-quality-gate-results"]}>
20
- {results.map((result) => (
21
- <li key={result.rule} data-testid="report-quality-gate-result">
22
- <div className={styles["report-quality-gate-result"]}>
23
- <SvgIcon id={allureIcons.solidXCircle} className={styles["report-quality-gate-result-icon"]} />
24
- <div className={styles["report-quality-gate-result-content"]}>
25
- <Text tag="p" size="l" type="ui" bold data-testid="report-quality-gate-result-rule">
26
- {result.rule}
27
- </Text>
28
- <TrError
29
- className={styles["report-quality-gate-result-error"]}
30
- message={result.message}
31
- data-testid="report-quality-gate-result-message"
32
- />
33
- </div>
71
+ <div className={styles["report-quality-gate-results"]}>
72
+ {entries.map(([env, envResults]) => {
73
+ const isOpened = !collapsedEnvs.includes(env);
74
+ const toggleEnv = () => {
75
+ setCollapsedEnvs((prev) => (isOpened ? prev.concat(env) : prev.filter((e) => e !== env)));
76
+ };
77
+
78
+ return (
79
+ <div
80
+ key={env}
81
+ className={styles["report-quality-gate-section"]}
82
+ data-testid={"quality-gate-results-section"}
83
+ >
84
+ <MetadataButton
85
+ isOpened={isOpened}
86
+ setIsOpen={toggleEnv}
87
+ title={`${tEnvironments("environment", { count: 1 })}: "${env}"`}
88
+ counter={envResults.length}
89
+ data-testid={"quality-gate-results-section-env-button"}
90
+ />
91
+ {isOpened && <QualityGateResultsList results={envResults} />}
34
92
  </div>
35
- </li>
36
- ))}
37
- </ul>
93
+ );
94
+ })}
95
+ </div>
38
96
  );
39
97
  }}
40
98
  />
@@ -1,6 +1,11 @@
1
1
  @import "~@allurereport/web-components/mixins.scss";
2
2
 
3
3
  .report-quality-gate-results {
4
+ padding: 12px 0 32px 8px;
5
+ min-height: 320px;
6
+ }
7
+
8
+ .report-quality-gate-results-list {
4
9
  padding: 20px 0;
5
10
 
6
11
  & > li + li {
@@ -42,3 +47,11 @@
42
47
  .report-quality-gate-result-error {
43
48
  margin-top: 8px;
44
49
  }
50
+
51
+ .report-quality-gate-section {
52
+ &:not(:last-child) {
53
+ padding-bottom: 8px;
54
+ margin-bottom: 14px;
55
+ border-bottom: 1px solid var(--on-border-muted);
56
+ }
57
+ }
@@ -6,7 +6,7 @@ import MainReport from "@/components/MainReport";
6
6
  import SideBySide from "@/components/SideBySide";
7
7
  import TestResult from "@/components/TestResult";
8
8
  import { useI18n } from "@/stores";
9
- import { testResultRoute } from "@/stores/router";
9
+ import { rootTabRoute, testResultRoute } from "@/stores/router";
10
10
  import { currentTrId } from "@/stores/testResult";
11
11
  import { testResultStore } from "@/stores/testResults";
12
12
  import { treeStore } from "@/stores/tree";
@@ -30,7 +30,9 @@ const Loader = () => {
30
30
  );
31
31
  };
32
32
 
33
- const isTestResultRoute = computed(() => testResultRoute.value.matches);
33
+ const isTestResultRoute = computed(
34
+ () => testResultRoute.value.matches || Boolean(rootTabRoute.value.params.testResultId),
35
+ );
34
36
 
35
37
  export const SplitLayout = () => {
36
38
  const testResultId = currentTrId.value;
@@ -22,6 +22,7 @@
22
22
  overflow: hidden;
23
23
  overflow-y: scroll;
24
24
  position: relative;
25
+ min-height: 100%;
25
26
  }
26
27
 
27
28
  .test-results {
@@ -1,25 +1,75 @@
1
- import { Text } from "@allurereport/web-components";
1
+ import { proseStyles, resolveCssVarDeclarations, sanitizeIframeHtml, themeStore } from "@allurereport/web-commons";
2
2
  import type { FunctionalComponent } from "preact";
3
- import { useState } from "preact/hooks";
3
+ import { useEffect, useMemo, useState } from "preact/hooks";
4
4
  import type { AwesomeTestResult } from "types";
5
5
  import { MetadataButton } from "@/components/MetadataButton";
6
6
  import * as styles from "./styles.scss";
7
7
 
8
8
  export type TrDescriptionProps = {
9
- description: AwesomeTestResult["description"];
9
+ descriptionHtml: AwesomeTestResult["descriptionHtml"];
10
10
  };
11
11
 
12
- export const TrDescription: FunctionalComponent<TrDescriptionProps> = ({ description }) => {
13
- const [isOpen, setIsOpen] = useState<boolean>(true);
12
+ const MIN_HEIGHT = 120;
13
+
14
+ export const TrDescription: FunctionalComponent<TrDescriptionProps> = ({ descriptionHtml }) => {
15
+ const [isOpen, setIsOpen] = useState(true);
16
+ const [blobUrl, setBlobUrl] = useState("");
17
+ const [height, setHeight] = useState(MIN_HEIGHT);
18
+ const currentTheme = themeStore.value.current;
19
+
20
+ const sanitized = useMemo(() => (descriptionHtml ? sanitizeIframeHtml(descriptionHtml) : ""), [descriptionHtml]);
21
+
22
+ useEffect(() => {
23
+ if (!sanitized) {
24
+ setBlobUrl("");
25
+ return;
26
+ }
27
+
28
+ const iframeThemeVars = resolveCssVarDeclarations(proseStyles);
29
+
30
+ const html = `<!DOCTYPE html>
31
+ <html data-theme="${currentTheme}">
32
+ <head>
33
+ <meta charset="utf-8">
34
+ <style>:root {${iframeThemeVars}}</style>
35
+ <style>${proseStyles}</style>
36
+ </head>
37
+ <body>${sanitized}</body>
38
+ </html>`;
39
+
40
+ const blob = new Blob([html], { type: "text/html" });
41
+ const url = URL.createObjectURL(blob);
42
+ setBlobUrl(url);
43
+
44
+ return () => URL.revokeObjectURL(url);
45
+ }, [currentTheme, sanitized]);
46
+
47
+ const handleLoad = (e: Event) => {
48
+ const iframe = e.currentTarget as HTMLIFrameElement;
49
+ const documentElement = iframe.contentDocument?.documentElement;
50
+ const body = iframe.contentDocument?.body;
51
+ const scrollHeight = Math.max(documentElement?.scrollHeight ?? 0, body?.scrollHeight ?? 0);
52
+ setHeight(Math.max(scrollHeight, MIN_HEIGHT));
53
+ };
14
54
 
15
55
  return (
16
- <div className={styles["test-result-description"]}>
56
+ <div className={styles["test-result-description"]} data-testid="test-result-description">
17
57
  <div className={styles["test-result-description-wrapper"]}>
18
- <MetadataButton title={"Description"} setIsOpen={setIsOpen} isOpened={isOpen} />
58
+ <MetadataButton title="Description" setIsOpen={setIsOpen} isOpened={isOpen} />
19
59
  {isOpen && (
20
- <Text tag={"p"} className={styles["test-result-description-text"]}>
21
- {description}
22
- </Text>
60
+ <div className={styles["test-result-description-text"]}>
61
+ {blobUrl && (
62
+ <iframe
63
+ data-testid="test-result-description-frame"
64
+ src={blobUrl}
65
+ width="100%"
66
+ height={String(height)}
67
+ style={{ border: 0 }}
68
+ sandbox="allow-same-origin"
69
+ onLoad={handleLoad}
70
+ />
71
+ )}
72
+ </div>
23
73
  )}
24
74
  </div>
25
75
  </div>
@@ -9,4 +9,8 @@
9
9
 
10
10
  .test-result-description-text {
11
11
  padding-top: 10px;
12
+
13
+ iframe {
14
+ display: block;
15
+ }
12
16
  }
@@ -1,5 +1,5 @@
1
1
  import { Button, Code, CodeViewer } from "@allurereport/web-components";
2
- import type { BaseOptions, Change } from "diff";
2
+ import type { Change } from "diff";
3
3
  import { diffChars, diffLines, diffWords } from "diff";
4
4
  import { useState } from "preact/hooks";
5
5
  import * as styles from "@/components/TestResult/TrError/styles.scss";
@@ -33,11 +33,7 @@ export const TrDiff = ({ expected, actual }: { expected: string; actual: string
33
33
  };
34
34
  const changeTypeDiff = (type: DiffType = "chars") => {
35
35
  const diffFn = diffFunctions[type];
36
- const result = (diffFn as (oldStr: string, newStr: string, options?: BaseOptions) => Change[])(
37
- expected,
38
- actual,
39
- {},
40
- );
36
+ const result: Change[] = diffFn(expected, actual, {});
41
37
 
42
38
  setDiffType(type);
43
39
  setDiff(result);
@@ -128,6 +128,10 @@
128
128
  &:hover {
129
129
  background: inherit;
130
130
  }
131
+
132
+ pre {
133
+ white-space: pre-wrap;
134
+ }
131
135
  }
132
136
 
133
137
  .diff {
@@ -21,10 +21,12 @@ export type TrInfoProps = {
21
21
  };
22
22
 
23
23
  export const TrInfo: FunctionalComponent<TrInfoProps> = ({ testResult }) => {
24
- const { name, status, muted, flaky, known, duration, labels, history, retries, attachments, stop } = testResult ?? {};
24
+ const { name, status, muted, flaky, known, duration, labels, history, retries, attachments, stop, categories } =
25
+ testResult ?? {};
25
26
  const formattedDuration = formatDuration(duration as number);
26
27
  const fullDate = stop && timestampToDate(stop);
27
28
  const severity = labels?.find((label) => label.name === "severity")?.value ?? "normal";
29
+ const categoryName = categories?.[0]?.name;
28
30
  const { t } = useI18n("ui");
29
31
  const statuses = Object.entries({ flaky, muted, known }).filter(([, value]) => value);
30
32
 
@@ -41,6 +43,11 @@ export const TrInfo: FunctionalComponent<TrInfoProps> = ({ testResult }) => {
41
43
  {Boolean(history?.length) && <TrPrevStatuses history={history} />}
42
44
  <TrSeverity severity={severity} />
43
45
  {Boolean(statuses.length) && <TrInfoStatuses statuses={statuses} />}
46
+ {categoryName && (
47
+ <Text tag={"div"} size={"s"} className={styles["test-result-category"]}>
48
+ {t("category")}: {categoryName}
49
+ </Text>
50
+ )}
44
51
  <TooltipWrapper tooltipText={fullDate}>
45
52
  <Text tag={"div"} size={"s"} bold className={styles["test-result-duration"]}>
46
53
  {formattedDuration}
@@ -41,6 +41,10 @@
41
41
  color: var(--on-text-secondary);
42
42
  }
43
43
 
44
+ .test-result-category {
45
+ color: var(--on-text-secondary);
46
+ }
47
+
44
48
  .test-result-tabs {
45
49
  border-bottom: 1px solid var(--on-border-primary);
46
50
  }
@@ -22,13 +22,13 @@ const linksIconMap: Record<string, string> = {
22
22
  const TrLink: FunctionalComponent<{
23
23
  link: TrLinkProps;
24
24
  }> = ({ link }) => {
25
- const { url, type } = link;
25
+ const { url, name, type } = link;
26
26
 
27
27
  return (
28
- <div className={styles["test-result-link"]}>
28
+ <div className={styles["test-result-link"]} data-testid="test-result-meta-link">
29
29
  <SvgIcon id={linksIconMap[type] ?? allureIcons.lineGeneralLink1} />
30
30
  <Text tag={"a"} href={url} target={"_blank"} size={"m"} className={styles["test-result-link-text"]}>
31
- {url}
31
+ {name || url}
32
32
  </Text>
33
33
  </div>
34
34
  );
@@ -46,7 +46,7 @@ export const TrLinks: FunctionalComponent<TrLinksProps> = ({ links }) => {
46
46
  });
47
47
 
48
48
  return (
49
- <div className={styles["test-result-links"]}>
49
+ <div className={styles["test-result-links"]} data-testid="test-result-meta-links">
50
50
  <div className={styles["test-result-links-wrapper"]}>
51
51
  <MetadataButton isOpened={isOpened} setIsOpen={setIsOpen} counter={links.length} title={t("links")} />
52
52
  {isOpened && <div className={styles["test-result-links-list"]}>{linkMap}</div>}
@@ -17,7 +17,8 @@ export type TrOverviewProps = {
17
17
  };
18
18
 
19
19
  export const TrOverview: FunctionalComponent<TrOverviewProps> = ({ testResult }) => {
20
- const { error, parameters, groupedLabels, links, description, setup, steps, teardown, id, status } = testResult || {};
20
+ const { error, parameters, groupedLabels, links, descriptionHtml, setup, steps, teardown, id, status } =
21
+ testResult || {};
21
22
  const isNoSteps = !setup?.length && !steps.length && !teardown.length;
22
23
  const pwTraces = testResult?.attachments?.filter(
23
24
  (attachment) => attachment.link.contentType === "application/vnd.allure.playwright-trace",
@@ -34,7 +35,7 @@ export const TrOverview: FunctionalComponent<TrOverviewProps> = ({ testResult })
34
35
  {Boolean(parameters?.length) && <TrParameters parameters={parameters} />}
35
36
  {Boolean(groupedLabels && Object.keys(groupedLabels || {})?.length) && <TrMetadata testResult={testResult} />}
36
37
  {Boolean(links?.length) && <TrLinks links={links} />}
37
- {Boolean(description) && <TrDescription description={description} />}
38
+ {Boolean(descriptionHtml) && <TrDescription descriptionHtml={descriptionHtml} />}
38
39
  <div className={styles["test-results"]}>
39
40
  {isNoSteps && <TestStepsEmpty />}
40
41
  {Boolean(setup?.length) && <TrSetup id={id} setup={setup} />}
@@ -10,17 +10,26 @@ const icons: Record<string, string> = {
10
10
  normal: allureIcons.lineGeneralEqual,
11
11
  minor: allureIcons.lineArrowsChevronDown,
12
12
  trivial: allureIcons.lineArrowsChevronDownDouble,
13
+ none: allureIcons.lineGeneralXClose,
13
14
  };
14
15
 
15
- export const TrSeverity = ({ severity = "normal" }: { severity?: string }) => {
16
+ export const TrSeverity = ({
17
+ severity = "normal",
18
+ text = "",
19
+ size = "s",
20
+ }: {
21
+ severity?: string;
22
+ text?: string;
23
+ size?: "s" | "m";
24
+ }) => {
16
25
  const { t } = useI18n("severity");
17
26
  const statusClass = clsx(styles[`severity-${severity}`]);
18
27
 
19
28
  return (
20
29
  <div className={styles["test-result-severity"]}>
21
- <SvgIcon className={statusClass} id={icons[severity]} />
22
- <Text size={"s"} bold className={styles["test-result-severity-text"]}>
23
- {capitalize(t(severity))}
30
+ <SvgIcon className={statusClass} id={icons[severity]} size={size} />
31
+ <Text size={size} bold className={styles["test-result-severity-text"]}>
32
+ {text || capitalize(t(severity))}
24
33
  </Text>
25
34
  </div>
26
35
  );
@@ -2,6 +2,7 @@
2
2
  display: flex;
3
3
  align-items: center;
4
4
  gap: 6px;
5
+ color: var(--on-text-secondary);
5
6
  }
6
7
 
7
8
  .test-result-severity-text {
@@ -15,6 +15,11 @@ export const TrTab = (props: { id: string; children: ComponentChildren }) => {
15
15
  return;
16
16
  }
17
17
 
18
+ if (id === "overview") {
19
+ navigateToTestResultTab({ testResultId: currentTrId.value, tab: "" });
20
+ return;
21
+ }
22
+
18
23
  navigateToTestResultTab({ testResultId: currentTrId.value, tab: id });
19
24
  };
20
25
 
@@ -7,12 +7,9 @@ import type { TimlineTr } from "@/stores/timeline";
7
7
  import { fetchTimelineData, timelineStore } from "@/stores/timeline";
8
8
  import * as styles from "./styles.scss";
9
9
 
10
- const getHosts = (tests: TimlineTr[]) => [
11
- ...new Set(tests.map((test) => test.labels.find((label) => label.name === "host")?.value).filter(Boolean)),
12
- ];
10
+ const getHosts = (tests: TimlineTr[]) => [...new Set(tests.map((test) => test.host))];
13
11
 
14
- const filterTestsByHost = (tests: TimlineTr[], host: string) =>
15
- tests.filter((test) => test.labels.find((label) => label.name === "host")?.value === host);
12
+ const filterTestsByHost = (tests: TimlineTr[], host: string) => tests.filter((test) => test.host === host);
16
13
 
17
14
  const currentTimelineData = computed(() => {
18
15
  const tests = timelineStore.value.data ?? [];
package/src/index.tsx CHANGED
@@ -11,6 +11,7 @@ import { Header } from "@/components/Header";
11
11
  import { ModalComponent } from "@/components/Modal";
12
12
  import { SectionSwitcher } from "@/components/SectionSwitcher";
13
13
  import { fetchEnvStats, fetchReportStats, getLocale, waitForI18next } from "@/stores";
14
+ import { fetchCategoriesData } from "@/stores/categories";
14
15
  import { fetchPieChartData } from "@/stores/chart";
15
16
  import { currentEnvironment, environmentsStore, fetchEnvironments } from "@/stores/env";
16
17
  import { fetchEnvInfo } from "@/stores/envInfo";
@@ -20,7 +21,7 @@ import { fetchTestResult, fetchTestResultNav } from "@/stores/testResults";
20
21
  import { fetchEnvTreesData } from "@/stores/tree";
21
22
  import { isMac } from "@/utils/isMac";
22
23
  import { fetchQualityGateResults } from "./stores/qualityGate";
23
- import { testResultRoute } from "./stores/router";
24
+ import { rootTabRoute, testResultRoute } from "./stores/router";
24
25
  import { currentSection } from "./stores/sections";
25
26
  import { currentTrId } from "./stores/testResult";
26
27
  import { fetchTreeFiltersData } from "./stores/treeFilters/actions";
@@ -36,7 +37,9 @@ const Loader = () => {
36
37
  );
37
38
  };
38
39
 
39
- const isTestResultRoute = computed(() => testResultRoute.value.matches);
40
+ const isTestResultRoute = computed(
41
+ () => testResultRoute.value.matches || Boolean(rootTabRoute.value.params.testResultId),
42
+ );
40
43
 
41
44
  const App = () => {
42
45
  const className = styles[`layout-${currentSection.value !== "default" ? currentSection.value : layoutStore.value}`];
@@ -51,6 +54,7 @@ const App = () => {
51
54
  fetchEnvInfo,
52
55
  fetchGlobals,
53
56
  fetchQualityGateResults,
57
+ fetchCategoriesData,
54
58
  ];
55
59
 
56
60
  if (globalThis) {