@allurereport/web-awesome 3.0.0-beta.3 → 3.0.0-beta.5

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 (89) hide show
  1. package/.eslintrc.cjs +1 -1
  2. package/CONTRIBUTING.md +34 -0
  3. package/dist/multi/{141.app-b6362ca0.js → 141.app-71d7f77e.js} +1 -1
  4. package/dist/multi/222.app-71d7f77e.js +1 -0
  5. package/dist/multi/335.app-71d7f77e.js +1 -0
  6. package/dist/multi/{34.app-b6362ca0.js → 34.app-71d7f77e.js} +1 -1
  7. package/dist/multi/349.app-71d7f77e.js +1 -0
  8. package/dist/multi/378.app-71d7f77e.js +1 -0
  9. package/dist/multi/{406.app-b6362ca0.js → 406.app-71d7f77e.js} +1 -1
  10. package/dist/multi/476.app-71d7f77e.js +1 -0
  11. package/dist/multi/{53.app-b6362ca0.js → 53.app-71d7f77e.js} +1 -1
  12. package/dist/multi/{584.app-b6362ca0.js → 584.app-71d7f77e.js} +1 -1
  13. package/dist/multi/690.app-71d7f77e.js +1 -0
  14. package/dist/multi/{747.app-b6362ca0.js → 747.app-71d7f77e.js} +1 -1
  15. package/dist/multi/{767.app-b6362ca0.js → 767.app-71d7f77e.js} +1 -1
  16. package/dist/multi/{816.app-b6362ca0.js → 816.app-71d7f77e.js} +1 -1
  17. package/dist/multi/83.app-71d7f77e.js +1 -0
  18. package/dist/multi/{873.app-b6362ca0.js → 873.app-71d7f77e.js} +1 -1
  19. package/dist/multi/{920.app-b6362ca0.js → 920.app-71d7f77e.js} +1 -1
  20. package/dist/multi/{991.app-b6362ca0.js → 991.app-71d7f77e.js} +1 -1
  21. package/dist/multi/app-71d7f77e.js +2 -0
  22. package/dist/multi/manifest.json +20 -20
  23. package/dist/multi/{styles-b6362ca0.css → styles-71d7f77e.css} +6 -6
  24. package/dist/single/app-7aa8b012.js +2 -0
  25. package/dist/single/manifest.json +1 -1
  26. package/package.json +11 -4
  27. package/src/assets/scss/_common.scss +9 -0
  28. package/src/components/app/ArrowButton/index.tsx +3 -2
  29. package/src/components/app/BaseLayout/index.tsx +5 -5
  30. package/src/components/app/ReportBody/Filters.tsx +12 -10
  31. package/src/components/app/ReportBody/HeaderActions.tsx +3 -3
  32. package/src/components/app/ReportBody/SortBy.tsx +10 -10
  33. package/src/components/app/ReportBody/context.tsx +0 -1
  34. package/src/components/app/ReportHeader/index.tsx +1 -1
  35. package/src/components/app/Tabs/index.tsx +2 -3
  36. package/src/components/app/TestResult/TestResultDescription/index.tsx +3 -3
  37. package/src/components/app/TestResult/TestResultNavigation/index.tsx +34 -37
  38. package/src/components/app/TestResult/TestResultNavigation/styles.scss +1 -1
  39. package/src/components/app/TestResult/TestResultSteps/attachment.tsx +4 -6
  40. package/src/components/app/Tree/Tree.tsx +54 -101
  41. package/src/components/app/Tree/TreeHeader.tsx +13 -12
  42. package/src/components/app/Tree/TreeItem.tsx +3 -1
  43. package/src/components/app/Tree/index.tsx +31 -7
  44. package/src/components/app/Tree/styles.scss +9 -3
  45. package/src/components/commons/Menu/index.tsx +44 -19
  46. package/src/components/commons/SearchBox/index.tsx +8 -5
  47. package/src/components/commons/SuccessRatePieChart/styles.scss +0 -1
  48. package/src/components/commons/Toggle/index.tsx +3 -2
  49. package/src/components/commons/Tooltip/index.tsx +3 -3
  50. package/src/i18n/constants.ts +21 -2
  51. package/src/i18n/locales/am.json +3 -1
  52. package/src/i18n/locales/az.json +3 -1
  53. package/src/i18n/locales/de.json +3 -1
  54. package/src/i18n/locales/en.json +4 -2
  55. package/src/i18n/locales/es.json +3 -0
  56. package/src/i18n/locales/fr.json +3 -1
  57. package/src/i18n/locales/he.json +3 -1
  58. package/src/i18n/locales/it.json +3 -1
  59. package/src/i18n/locales/ja.json +3 -1
  60. package/src/i18n/locales/ka.json +3 -1
  61. package/src/i18n/locales/kr.json +3 -1
  62. package/src/i18n/locales/nl.json +3 -1
  63. package/src/i18n/locales/pl.json +3 -1
  64. package/src/i18n/locales/pt.json +3 -1
  65. package/src/i18n/locales/ru.json +3 -1
  66. package/src/i18n/locales/sv.json +3 -1
  67. package/src/i18n/locales/tr.json +3 -1
  68. package/src/i18n/locales/zh.json +4 -2
  69. package/src/index.html +1 -0
  70. package/src/stores/chart.ts +2 -2
  71. package/src/stores/testResults.ts +26 -4
  72. package/src/stores/tree.ts +98 -4
  73. package/src/types/globals.d.ts +6 -1
  74. package/src/utils/capitalize.ts +5 -3
  75. package/src/utils/treeFilters.ts +73 -120
  76. package/test/utils/treeFilters.test.ts +424 -0
  77. package/types.d.ts +25 -4
  78. package/vitest.config.ts +12 -0
  79. package/dist/multi/222.app-b6362ca0.js +0 -1
  80. package/dist/multi/335.app-b6362ca0.js +0 -1
  81. package/dist/multi/349.app-b6362ca0.js +0 -1
  82. package/dist/multi/378.app-b6362ca0.js +0 -1
  83. package/dist/multi/476.app-b6362ca0.js +0 -1
  84. package/dist/multi/690.app-b6362ca0.js +0 -1
  85. package/dist/multi/83.app-b6362ca0.js +0 -1
  86. package/dist/multi/app-b6362ca0.js +0 -2
  87. package/dist/single/app-57ae0a60.js +0 -2
  88. /package/dist/multi/{app-b6362ca0.js.LICENSE.txt → app-71d7f77e.js.LICENSE.txt} +0 -0
  89. /package/dist/single/{app-57ae0a60.js.LICENSE.txt → app-7aa8b012.js.LICENSE.txt} +0 -0
@@ -1,3 +1,3 @@
1
1
  {
2
- "main.js": "app-57ae0a60.js"
2
+ "main.js": "app-7aa8b012.js"
3
3
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/web-awesome",
3
- "version": "3.0.0-beta.3",
3
+ "version": "3.0.0-beta.5",
4
4
  "description": "The static files for Allure Awesome Report",
5
5
  "keywords": [
6
6
  "allure",
@@ -22,7 +22,8 @@
22
22
  "build:prod:multi": "webpack --mode production",
23
23
  "build:dev:single": "SINGLE_FILE_MODE=1 webpack --mode development",
24
24
  "build:dev:multi": "webpack --mode development",
25
- "lint": "eslint --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
25
+ "lint": "eslint --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
26
+ "test": "vitest run"
26
27
  },
27
28
  "browserslist": [
28
29
  "last 1 version",
@@ -30,8 +31,8 @@
30
31
  "IE 11"
31
32
  ],
32
33
  "dependencies": {
33
- "@allurereport/core-api": "3.0.0-beta.3",
34
- "@allurereport/web-commons": "3.0.0-beta.3",
34
+ "@allurereport/core-api": "3.0.0-beta.5",
35
+ "@allurereport/web-commons": "3.0.0-beta.5",
35
36
  "@preact/signals": "^1.3.0",
36
37
  "clsx": "^2.1.1",
37
38
  "d3-shape": "^3.2.0",
@@ -57,6 +58,10 @@
57
58
  "@types/prismjs": "^1",
58
59
  "@typescript-eslint/eslint-plugin": "^8.0.0",
59
60
  "@typescript-eslint/parser": "^8.0.0",
61
+ "@vitest/runner": "^2.1.8",
62
+ "@vitest/snapshot": "^2.1.8",
63
+ "allure-vitest": "^3.0.7",
64
+ "autoprefixer": "^10.4.20",
60
65
  "babel-loader": "^9.2.1",
61
66
  "babel-plugin-prismjs": "^2.1.0",
62
67
  "css-loader": "^7.1.2",
@@ -78,6 +83,7 @@
78
83
  "html-webpack-plugin": "^5.6.3",
79
84
  "mini-css-extract-plugin": "^2.9.1",
80
85
  "npm-run-all2": "^7.0.1",
86
+ "postcss": "^8.4.49",
81
87
  "rimraf": "^6.0.1",
82
88
  "sass": "^1.79.1",
83
89
  "sass-loader": "^16.0.1",
@@ -85,6 +91,7 @@
85
91
  "svg-sprite-loader": "^6.0.11",
86
92
  "typescript": "^5.6.3",
87
93
  "typescript-eslint": "^8.6.0",
94
+ "vitest": "^2.1.8",
88
95
  "webpack": "^5.94.0",
89
96
  "webpack-cli": "^5.1.4",
90
97
  "webpack-dev-server": "^5.1.0",
@@ -3,6 +3,7 @@
3
3
  *::after {
4
4
  box-sizing: border-box;
5
5
  }
6
+
6
7
  html,
7
8
  body,
8
9
  div,
@@ -91,6 +92,7 @@ video {
91
92
  font: inherit;
92
93
  vertical-align: baseline;
93
94
  }
95
+
94
96
  /* HTML5 display-role reset for older browsers */
95
97
  article,
96
98
  aside,
@@ -105,17 +107,21 @@ nav,
105
107
  section {
106
108
  display: block;
107
109
  }
110
+
108
111
  body {
109
112
  line-height: 1;
110
113
  }
114
+
111
115
  ol,
112
116
  ul {
113
117
  list-style: none;
114
118
  }
119
+
115
120
  blockquote,
116
121
  q {
117
122
  quotes: none;
118
123
  }
124
+
119
125
  blockquote:before,
120
126
  blockquote:after,
121
127
  q:before,
@@ -123,12 +129,15 @@ q:after {
123
129
  content: "";
124
130
  content: none;
125
131
  }
132
+
126
133
  table {
127
134
  border-collapse: collapse;
128
135
  border-spacing: 0;
129
136
  }
137
+
130
138
  body {
131
139
  color: var(--on-text-primary);
132
140
  background: var(--bg-base-secondary);
133
141
  font-family: var(--font-family);
142
+ -webkit-text-size-adjust: 100%;
134
143
  }
@@ -1,5 +1,5 @@
1
1
  import { clsx } from "clsx";
2
- import { FunctionalComponent } from "preact";
2
+ import type { FunctionalComponent } from "preact";
3
3
  import lineChevronDown from "@/assets/svg/line-arrows-chevron-down.svg";
4
4
  import { SvgIcon } from "@/components/commons/SvgIcon";
5
5
  import * as styles from "./styles.scss";
@@ -18,9 +18,10 @@ export const ArrowButton: FunctionalComponent<ArrowButtonProps> = ({
18
18
  iconSize = "xs",
19
19
  className,
20
20
  icon,
21
+ ...rest
21
22
  }) => {
22
23
  return (
23
- <button className={clsx(styles["arrow-button"], styles[`arrow-button-${buttonSize}`])}>
24
+ <button className={clsx(styles["arrow-button"], styles[`arrow-button-${buttonSize}`])} {...rest}>
24
25
  <SvgIcon
25
26
  id={icon || lineChevronDown.id}
26
27
  size={iconSize}
@@ -1,4 +1,4 @@
1
- import { ensureReportDataReady } from "@allurereport/web-commons";
1
+ import { ensureReportDataReady, getReportOptions } from "@allurereport/web-commons";
2
2
  import { useEffect } from "preact/compat";
3
3
  import { Footer } from "@/components/app/Footer";
4
4
  import MainReport from "@/components/app/MainReport";
@@ -6,11 +6,10 @@ import Modal from "@/components/app/Modal";
6
6
  import TestResult from "@/components/app/TestResult";
7
7
  import { Loadable } from "@/components/commons/Loadable";
8
8
  import { PageLoader } from "@/components/commons/PageLoader";
9
- import { fetchStats, getTheme } from "@/stores";
10
- import { getLocale } from "@/stores";
9
+ import { fetchStats, getLocale, getTheme } from "@/stores";
11
10
  import { fetchPieChartData } from "@/stores/chart";
12
11
  import { fetchEnvInfo } from "@/stores/envInfo";
13
- import { fetchTestResult, testResultStore } from "@/stores/testResults";
12
+ import { fetchTestResult, fetchTestResultNav, testResultStore } from "@/stores/testResults";
14
13
  import { fetchTreeData, treeStore } from "@/stores/tree";
15
14
  import * as styles from "./styles.scss";
16
15
 
@@ -23,12 +22,13 @@ export const BaseLayout = ({ testResultId }) => {
23
22
  useEffect(() => {
24
23
  if (testResultId) {
25
24
  fetchTestResult(testResultId);
25
+ fetchTestResultNav();
26
26
  } else {
27
27
  Promise.all([
28
28
  ensureReportDataReady(),
29
29
  fetchStats(),
30
30
  fetchPieChartData(),
31
- fetchTreeData("suites"),
31
+ fetchTreeData(),
32
32
  fetchEnvInfo(),
33
33
  ]);
34
34
  }
@@ -2,18 +2,16 @@ import notificationBoxIcon from "@/assets/svg/line-alerts-notification-box.svg";
2
2
  import refreshIcon from "@/assets/svg/line-arrows-refresh-ccw-1.svg";
3
3
  import settingsIcon from "@/assets/svg/line-general-settings-1.svg";
4
4
  import zapIcon from "@/assets/svg/line-general-zap.svg";
5
- import { useReportContentContext } from "@/components/app/ReportBody/context";
6
5
  import { Button } from "@/components/commons/Button";
7
6
  import { Menu } from "@/components/commons/Menu";
8
7
  import { Toggle } from "@/components/commons/Toggle";
9
8
  import { useI18n } from "@/stores/locale";
9
+ import { setTreeFilter, treeFiltersStore } from "@/stores/tree";
10
10
  import * as styles from "./styles.scss";
11
11
 
12
12
  export const Filters = () => {
13
13
  const { t } = useI18n("filters");
14
- const { filter, setFilter } = useReportContentContext();
15
-
16
- const { flaky, retry, new: isNew } = filter;
14
+ const { flaky, retry, new: isNew } = treeFiltersStore.value.filter;
17
15
  const hasFilter = flaky || retry || isNew;
18
16
 
19
17
  return (
@@ -26,6 +24,7 @@ export const Filters = () => {
26
24
  size="m"
27
25
  style="outline"
28
26
  isActive={isOpened}
27
+ data-testid="filters-button"
29
28
  onClick={onClick}
30
29
  />
31
30
  </div>
@@ -36,7 +35,7 @@ export const Filters = () => {
36
35
  closeMenuOnClick={false}
37
36
  ariaLabel={t("enable-filter", { filter: t("flaky") })}
38
37
  onClick={() => {
39
- setFilter("flaky", !flaky);
38
+ setTreeFilter("flaky", !flaky);
40
39
  }}
41
40
  leadingIcon={zapIcon.id}
42
41
  rightSlot={
@@ -45,7 +44,8 @@ export const Filters = () => {
45
44
  focusable={false}
46
45
  value={flaky}
47
46
  label={t("enable-filter", { filter: t("flaky") })}
48
- onChange={(value) => setFilter("flaky", value)}
47
+ data-testid="flaky-filter"
48
+ onChange={(value) => setTreeFilter("flaky", value)}
49
49
  />
50
50
  </div>
51
51
  }
@@ -55,7 +55,7 @@ export const Filters = () => {
55
55
  <Menu.Item
56
56
  closeMenuOnClick={false}
57
57
  ariaLabel={t("enable-filter", { filter: t("retry") })}
58
- onClick={() => setFilter("retry", !retry)}
58
+ onClick={() => setTreeFilter("retry", !retry)}
59
59
  leadingIcon={refreshIcon.id}
60
60
  rightSlot={
61
61
  <div className={styles.filterToggle}>
@@ -63,7 +63,8 @@ export const Filters = () => {
63
63
  focusable={false}
64
64
  value={retry}
65
65
  label={t("enable-filter", { filter: t("retry") })}
66
- onChange={(value) => setFilter("retry", value)}
66
+ data-testid="retry-filter"
67
+ onChange={(value) => setTreeFilter("retry", value)}
67
68
  />
68
69
  </div>
69
70
  }
@@ -73,7 +74,7 @@ export const Filters = () => {
73
74
  <Menu.Item
74
75
  closeMenuOnClick={false}
75
76
  ariaLabel={t("enable-filter", { filter: t("new") })}
76
- onClick={() => setFilter("new", !isNew)}
77
+ onClick={() => setTreeFilter("new", !isNew)}
77
78
  leadingIcon={notificationBoxIcon.id}
78
79
  rightSlot={
79
80
  <div className={styles.filterToggle}>
@@ -81,7 +82,8 @@ export const Filters = () => {
81
82
  focusable={false}
82
83
  value={isNew}
83
84
  label={t("enable-filter", { filter: t("new") })}
84
- onChange={(value) => setFilter("new", value)}
85
+ data-testid="new-filter"
86
+ onChange={(value) => setTreeFilter("new", value)}
85
87
  />
86
88
  </div>
87
89
  }
@@ -1,14 +1,14 @@
1
1
  import { useI18n } from "@/stores/locale";
2
+ import { setTreeQuery, treeFiltersStore } from "@/stores/tree";
2
3
  import { SearchBox } from "../../commons/SearchBox";
3
4
  import { Filters } from "./Filters";
4
- import { useReportContentContext } from "./context";
5
5
  import * as styles from "./styles.scss";
6
6
 
7
7
  const Search = () => {
8
- const { setQuery, query } = useReportContentContext();
8
+ const { query } = treeFiltersStore.value;
9
9
  const { t } = useI18n("search");
10
10
 
11
- return <SearchBox placeholder={t("search-placeholder")} value={query} onChange={setQuery} />;
11
+ return <SearchBox placeholder={t("search-placeholder")} value={query} onChange={setTreeQuery} />;
12
12
  };
13
13
 
14
14
  export const HeaderActions = () => {
@@ -1,16 +1,16 @@
1
1
  import clsx from "clsx";
2
- import { ComponentChildren } from "preact";
2
+ import type { ComponentChildren } from "preact";
3
3
  import lineChevronDownIcon from "@/assets/svg/line-arrows-chevron-down.svg";
4
4
  import sortAscIcon from "@/assets/svg/line-arrows-sort-line-asc.svg";
5
5
  import sortDescIcon from "@/assets/svg/line-arrows-sort-line-desc.svg";
6
6
  import switchVerticalIcon from "@/assets/svg/line-arrows-switch-vertical-1.svg";
7
7
  import { useI18n } from "@/stores/locale";
8
+ import { setTreeDirection, setTreeSortBy, treeFiltersStore } from "@/stores/tree";
8
9
  import { DropdownButton } from "../../commons/Button";
9
10
  import { Link } from "../../commons/Link";
10
11
  import { Menu } from "../../commons/Menu";
11
12
  import { SvgIcon } from "../../commons/SvgIcon";
12
13
  import { Text } from "../../commons/Typography";
13
- import { useReportContentContext } from "./context";
14
14
  import * as styles from "./styles.scss";
15
15
 
16
16
  const BtnWrapper = ({ children }: { children: ComponentChildren }) => {
@@ -21,7 +21,7 @@ export const SortBy = () => {
21
21
  const { t: sortByLocale } = useI18n("sort-by");
22
22
  const { t: sortByValuesLocale } = useI18n("sort-by.values");
23
23
  const { t: sortByDirectionsLocale } = useI18n("sort-by.directions");
24
- const { direction, sortBy, setSortBy, setDirection } = useReportContentContext();
24
+ const { sortBy, direction } = treeFiltersStore.value;
25
25
 
26
26
  const displayedSortByValue = sortByValuesLocale(sortBy);
27
27
  const displayedDirection = sortByDirectionsLocale(`${sortBy}-${direction}-short`);
@@ -72,16 +72,16 @@ export const SortBy = () => {
72
72
  )}
73
73
  >
74
74
  <Menu.Section>
75
- <Menu.ItemWithCheckmark onClick={() => setSortBy("order")} isChecked={sortBy === "order"}>
75
+ <Menu.ItemWithCheckmark onClick={() => setTreeSortBy("order")} isChecked={sortBy === "order"}>
76
76
  {sortByValuesLocale("order")}
77
77
  </Menu.ItemWithCheckmark>
78
- <Menu.ItemWithCheckmark onClick={() => setSortBy("duration")} isChecked={sortBy === "duration"}>
78
+ <Menu.ItemWithCheckmark onClick={() => setTreeSortBy("duration")} isChecked={sortBy === "duration"}>
79
79
  {sortByValuesLocale("duration")}
80
80
  </Menu.ItemWithCheckmark>
81
- <Menu.ItemWithCheckmark onClick={() => setSortBy("status")} isChecked={sortBy === "status"}>
81
+ <Menu.ItemWithCheckmark onClick={() => setTreeSortBy("status")} isChecked={sortBy === "status"}>
82
82
  {sortByValuesLocale("status")}
83
83
  </Menu.ItemWithCheckmark>
84
- <Menu.ItemWithCheckmark onClick={() => setSortBy("alphabet")} isChecked={sortBy === "alphabet"}>
84
+ <Menu.ItemWithCheckmark onClick={() => setTreeSortBy("alphabet")} isChecked={sortBy === "alphabet"}>
85
85
  {sortByValuesLocale("alphabet")}
86
86
  </Menu.ItemWithCheckmark>
87
87
  </Menu.Section>
@@ -92,7 +92,7 @@ export const SortBy = () => {
92
92
  <Menu.Item
93
93
  closeMenuOnClick={false}
94
94
  onClick={onClick}
95
- leadingIcon={direction == "asc" ? sortAscIcon.id : sortDescIcon.id}
95
+ leadingIcon={direction === "asc" ? sortAscIcon.id : sortDescIcon.id}
96
96
  rightSlot={
97
97
  <BtnWrapper>
98
98
  <DropdownButton
@@ -111,14 +111,14 @@ export const SortBy = () => {
111
111
  >
112
112
  <Menu.Section>
113
113
  <Menu.ItemWithCheckmark
114
- onClick={() => setDirection("asc")}
114
+ onClick={() => setTreeDirection("asc")}
115
115
  leadingIcon={sortAscIcon.id}
116
116
  isChecked={direction === "asc"}
117
117
  >
118
118
  {sortByDirectionsLocale(`${sortBy}-asc`)}
119
119
  </Menu.ItemWithCheckmark>
120
120
  <Menu.ItemWithCheckmark
121
- onClick={() => setDirection("desc")}
121
+ onClick={() => setTreeDirection("desc")}
122
122
  leadingIcon={sortDescIcon.id}
123
123
  isChecked={direction === "desc"}
124
124
  >
@@ -1,6 +1,5 @@
1
1
  import { type ComponentChildren, createContext } from "preact";
2
2
  import { useCallback, useContext, useReducer } from "preact/hooks";
3
- import { capitalize } from "@/utils/capitalize";
4
3
 
5
4
  export type SortBy = "order" | "duration" | "status" | "alphabet";
6
5
  export type Direction = "asc" | "desc";
@@ -19,7 +19,7 @@ export const ReportHeader = () => {
19
19
  <div className={styles["report-wrapper"]}>
20
20
  <ReportHeaderLogo />
21
21
  <div className={styles["report-wrapper-text"]}>
22
- <Heading size={"s"} tag={"h2"} className={styles["wrapper-header"]}>
22
+ <Heading size={"s"} tag={"h2"} className={styles["wrapper-header"]} data-testid="report-title">
23
23
  {reportName}
24
24
  </Heading>
25
25
  <Text type="paragraph" size="m" className={styles["report-date"]}>
@@ -10,7 +10,7 @@ type TabsContextT = {
10
10
 
11
11
  const TabsContext = createContext<TabsContextT | null>(null);
12
12
 
13
- export function useTabsContext() {
13
+ export const useTabsContext = () => {
14
14
  const context = useContext(TabsContext);
15
15
 
16
16
  if (!context) {
@@ -18,7 +18,7 @@ export function useTabsContext() {
18
18
  }
19
19
 
20
20
  return context;
21
- }
21
+ };
22
22
 
23
23
  export const TabsProvider = (props: { initialTab?: string; children: ComponentChildren }) => {
24
24
  const { children, initialTab } = props;
@@ -39,7 +39,6 @@ export const Tab = (props: { id: string; children: ComponentChildren }) => {
39
39
  const { id, children, ...rest } = props;
40
40
  const { currentTab, setCurrentTab } = useTabsContext();
41
41
  const isCurrentTab = currentTab === id;
42
-
43
42
  const handleTabClick = () => {
44
43
  if (isCurrentTab) {
45
44
  return;
@@ -1,13 +1,13 @@
1
+ import { FunctionalComponent } from "preact";
1
2
  import { useState } from "preact/hooks";
2
3
  import { MetadataButton } from "@/components/app/MetadataButton";
3
4
  import { Text } from "@/components/commons/Typography";
4
- import * as styles from "./styles.scss";
5
- import { FunctionalComponent } from "preact";
6
5
  import { AllureAwesomeTestResult } from "../../../../../types";
6
+ import * as styles from "./styles.scss";
7
7
 
8
8
  export type TestResultDescriptionProps = {
9
9
  description: AllureAwesomeTestResult["description"];
10
- }
10
+ };
11
11
 
12
12
  export const TestResultDescription: FunctionalComponent<TestResultDescriptionProps> = ({ description }) => {
13
13
  const [isOpen, setIsOpen] = useState<boolean>(true);
@@ -1,5 +1,5 @@
1
- import { FunctionalComponent } from "preact";
2
- import { AllureAwesomeTestResult } from "types";
1
+ import type { FunctionalComponent } from "preact";
2
+ import type { AllureAwesomeTestResult } from "types";
3
3
  import LineArrowsChevronDown from "@/assets/svg/line-arrows-chevron-down.svg";
4
4
  import LineGeneralCopy3 from "@/assets/svg/line-general-copy-3.svg";
5
5
  import { IconButton } from "@/components/commons/Button";
@@ -8,7 +8,7 @@ import { TooltipWrapper } from "@/components/commons/Tooltip";
8
8
  import { Code } from "@/components/commons/Typography";
9
9
  import { navigateTo } from "@/index";
10
10
  import { useI18n } from "@/stores";
11
- import { treeStore } from "@/stores/tree";
11
+ import { testResultNavStore } from "@/stores/testResults";
12
12
  import { copyToClipboard } from "@/utils/copyToClipboard";
13
13
  import * as styles from "./styles.scss";
14
14
 
@@ -20,47 +20,44 @@ export const TestResultNavigation: FunctionalComponent<TestResultNavigationProps
20
20
  const { fullName, id: testResultId } = testResult ?? {};
21
21
  const id = testResultId || "";
22
22
  const { t: tooltip } = useI18n("controls");
23
+ const FullName = () => {
24
+ return (
25
+ <div data-testid="test-result-fullname" className={styles["test-result-fullName"]}>
26
+ <TooltipWrapper tooltipText={tooltip("clipboard")} tooltipTextAfterClick={tooltip("clipboardSuccess")}>
27
+ <IconButton
28
+ data-testid="test-result-fullname-copy"
29
+ style={"ghost"}
30
+ size={"s"}
31
+ icon={LineGeneralCopy3.id}
32
+ onClick={() => copyToClipboard(fullName)}
33
+ />
34
+ </TooltipWrapper>
35
+ <Code tag={"div"} size={"s"} className={styles["test-result-fullName-text"]}>
36
+ {fullName && fullName}
37
+ </Code>
38
+ </div>
39
+ );
40
+ };
23
41
 
24
42
  return (
25
43
  <Loadable
26
- source={treeStore}
27
- renderData={(treeData) => {
28
- const leaves = treeData && Object.keys(treeData?.leavesById);
29
- const currentIndex = id && leaves?.findIndex((leave) => leave === id) + 1;
30
- const allTestResults = leaves?.length;
31
-
32
- const FullName = () => {
33
- return (
34
- <div data-testid="test-result-fullname" className={styles["test-result-fullName"]}>
35
- <TooltipWrapper tooltipText={tooltip("clipboard")} tooltipTextAfterClick={tooltip("clipboardSuccess")}>
36
- <IconButton
37
- data-testid="test-result-fullname-copy"
38
- style={"ghost"}
39
- size={"s"}
40
- icon={LineGeneralCopy3.id}
41
- onClick={() => copyToClipboard(fullName)}
42
- />
43
- </TooltipWrapper>
44
- <Code tag={"div"} size={"s"} className={styles["test-result-fullName-text"]}>
45
- {fullName && fullName}
46
- </Code>
47
- </div>
48
- );
49
- };
44
+ source={testResultNavStore}
45
+ renderData={(data) => {
46
+ const currentIndex = data.indexOf(id) + 1;
50
47
 
51
48
  return (
52
49
  <div className={styles["test-result-nav"]}>
53
50
  {fullName && <FullName />}
54
- {allTestResults && (
51
+ {data && (
55
52
  <div className={styles["test-result-navigator"]}>
56
- <TooltipWrapper tooltipText={tooltip("nextTR")}>
53
+ <TooltipWrapper tooltipText={tooltip("prevTR")} isTriggerActive={currentIndex > 1}>
57
54
  <IconButton
58
55
  icon={LineArrowsChevronDown.id}
59
56
  style={"ghost"}
60
- isDisabled={currentIndex === allTestResults}
61
- data-testid="test-result-nav-next"
62
- onClick={() => navigateTo(leaves[currentIndex])}
63
- className={styles["test-result-nav-next"]}
57
+ isDisabled={currentIndex === data.length}
58
+ data-testid="test-result-nav-prev"
59
+ className={styles["test-result-nav-prev"]}
60
+ onClick={() => navigateTo(data[currentIndex])}
64
61
  />
65
62
  </TooltipWrapper>
66
63
  <Code
@@ -68,15 +65,15 @@ export const TestResultNavigation: FunctionalComponent<TestResultNavigationProps
68
65
  size={"s"}
69
66
  className={styles["test-result-navigator-numbers"]}
70
67
  >
71
- {currentIndex}/{allTestResults}
68
+ {currentIndex}/{data.length}
72
69
  </Code>
73
- <TooltipWrapper tooltipText={tooltip("prevTR")} isTriggerActive={currentIndex > 1}>
70
+ <TooltipWrapper tooltipText={tooltip("nextTR")}>
74
71
  <IconButton
75
72
  icon={LineArrowsChevronDown.id}
76
73
  style={"ghost"}
77
74
  isDisabled={currentIndex <= 1}
78
- data-testid="test-result-nav-prev"
79
- onClick={() => navigateTo(leaves[currentIndex - 2])}
75
+ data-testid="test-result-nav-next"
76
+ onClick={() => navigateTo(data[currentIndex - 2])}
80
77
  />
81
78
  </TooltipWrapper>
82
79
  </div>
@@ -40,7 +40,7 @@
40
40
  font-weight: 400;
41
41
  }
42
42
 
43
- .test-result-nav-next {
43
+ .test-result-nav-prev {
44
44
  transform: rotate(-180deg);
45
45
  &:active {
46
46
  transform: scale(var(--allure-btn-pressed-scale)) rotate(-180deg);
@@ -1,16 +1,14 @@
1
1
  import type { AttachmentTestStepResult } from "@allurereport/core-api";
2
2
  import type { FunctionalComponent } from "preact";
3
3
  import { useEffect, useState } from "preact/hooks";
4
+ import { modalData } from "@/components/app/Modal";
5
+ import { HtmlAttachmentPreview } from "@/components/app/TestResult/TestResultSteps/HtmlAttachmentPreview";
4
6
  import { AttachmentCode } from "@/components/app/TestResult/TestResultSteps/attachmentCode";
5
7
  import { AttachmentImage } from "@/components/app/TestResult/TestResultSteps/attachmentImage";
6
8
  import { AttachmentVideo } from "@/components/app/TestResult/TestResultSteps/attachmentVideo";
7
9
  import { EmptyComponent } from "@/components/app/TestResult/TestResultSteps/wrongAttachment";
8
10
  import { Spinner } from "@/components/commons/Spinner";
9
11
  import { type Attachments, attachmentType, fetchAttachment } from "@/utils/attachments";
10
- import {
11
- HtmlAttachmentPreview
12
- } from "@/components/app/TestResult/TestResultSteps/HtmlAttachmentPreview";
13
- import { modalData } from "@/components/app/Modal";
14
12
  import * as styles from "./styles.scss";
15
13
 
16
14
  const componentsByAttachmentType = {
@@ -63,8 +61,8 @@ export const Attachment: FunctionalComponent<AttachmentTestStepResultProps> = ({
63
61
 
64
62
  // temp solution before modal component refactoring
65
63
  if (CurrentPreviewComponent && previewable && modalData.value.preview) {
66
- return <CurrentPreviewComponent attachment={attachment} item={item} />
64
+ return <CurrentPreviewComponent attachment={attachment} item={item} />;
67
65
  }
68
66
 
69
- return CurrentComponent ? <CurrentComponent attachment={attachment} item={item} /> : <EmptyComponent />
67
+ return CurrentComponent ? <CurrentComponent attachment={attachment} item={item} /> : <EmptyComponent />;
70
68
  };