@allurereport/web-awesome 3.0.0-beta.9 → 3.0.1

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 (290) hide show
  1. package/dist/multi/173.app-bae2a0fe5738d77cd976.js +1 -0
  2. package/dist/multi/174.app-bae2a0fe5738d77cd976.js +1 -0
  3. package/dist/multi/252.app-bae2a0fe5738d77cd976.js +1 -0
  4. package/dist/multi/282.app-bae2a0fe5738d77cd976.js +1 -0
  5. package/dist/multi/29.app-bae2a0fe5738d77cd976.js +1 -0
  6. package/dist/multi/416.app-bae2a0fe5738d77cd976.js +1 -0
  7. package/dist/multi/527.app-bae2a0fe5738d77cd976.js +1 -0
  8. package/dist/multi/600.app-bae2a0fe5738d77cd976.js +1 -0
  9. package/dist/multi/605.app-bae2a0fe5738d77cd976.js +1 -0
  10. package/dist/multi/638.app-bae2a0fe5738d77cd976.js +1 -0
  11. package/dist/multi/672.app-bae2a0fe5738d77cd976.js +1 -0
  12. package/dist/multi/686.app-bae2a0fe5738d77cd976.js +1 -0
  13. package/dist/multi/725.app-bae2a0fe5738d77cd976.js +1 -0
  14. package/dist/multi/741.app-bae2a0fe5738d77cd976.js +1 -0
  15. package/dist/multi/755.app-bae2a0fe5738d77cd976.js +1 -0
  16. package/dist/multi/894.app-bae2a0fe5738d77cd976.js +1 -0
  17. package/dist/multi/91.app-bae2a0fe5738d77cd976.js +1 -0
  18. package/dist/multi/943.app-bae2a0fe5738d77cd976.js +1 -0
  19. package/dist/multi/980.app-bae2a0fe5738d77cd976.js +1 -0
  20. package/dist/multi/app-bae2a0fe5738d77cd976.js +2 -0
  21. package/dist/multi/app-bae2a0fe5738d77cd976.js.LICENSE.txt +10 -0
  22. package/dist/multi/manifest.json +25 -24
  23. package/dist/multi/styles-bbf68b2ba63c38b53c38.css +48 -0
  24. package/dist/single/app-996d3b5869f8fc942b66.js +2 -0
  25. package/dist/single/app-996d3b5869f8fc942b66.js.LICENSE.txt +10 -0
  26. package/dist/single/manifest.json +1 -1
  27. package/package.json +31 -19
  28. package/src/assets/scss/day.scss +2 -0
  29. package/src/assets/scss/index.scss +1 -3
  30. package/src/assets/scss/night.scss +2 -0
  31. package/src/assets/scss/palette.scss +391 -391
  32. package/src/assets/scss/theme.scss +292 -79
  33. package/src/components/BaseLayout/index.tsx +10 -32
  34. package/src/components/BaseLayout/styles.scss +14 -4
  35. package/src/components/Charts/index.tsx +245 -0
  36. package/src/components/Charts/styles.scss +27 -0
  37. package/src/components/EnvironmentPicker/index.tsx +60 -0
  38. package/src/components/EnvironmentPicker/styles.scss +9 -0
  39. package/src/components/Footer/FooterLogo.tsx +1 -2
  40. package/src/components/Footer/FooterVersion.tsx +7 -3
  41. package/src/components/Footer/index.tsx +6 -2
  42. package/src/components/Header/CiInfo/index.tsx +67 -0
  43. package/src/components/Header/CiInfo/styles.scss +7 -0
  44. package/src/components/Header/index.tsx +21 -8
  45. package/src/components/Header/styles.scss +9 -1
  46. package/src/components/HeaderControls/index.tsx +20 -0
  47. package/src/components/MainReport/index.tsx +84 -6
  48. package/src/components/MainReport/styles.scss +20 -0
  49. package/src/components/Metadata/index.tsx +6 -4
  50. package/src/components/MetadataButton/index.tsx +14 -6
  51. package/src/components/MetadataButton/styles.scss +3 -0
  52. package/src/components/Modal/index.tsx +15 -167
  53. package/src/components/NavTabs/index.tsx +70 -0
  54. package/src/components/{TestResult/TestResultTabs → NavTabs}/styles.scss +0 -3
  55. package/src/components/Report/index.tsx +7 -0
  56. package/src/components/ReportBody/Filters.tsx +96 -64
  57. package/src/components/ReportBody/HeaderActions.tsx +2 -2
  58. package/src/components/ReportBody/SortBy.tsx +4 -7
  59. package/src/components/ReportBody/index.tsx +30 -24
  60. package/src/components/ReportBody/styles.scss +9 -3
  61. package/src/components/ReportGlobalAttachments/index.tsx +34 -0
  62. package/src/components/ReportGlobalAttachments/styles.scss +11 -0
  63. package/src/components/ReportGlobalErrors/index.tsx +30 -0
  64. package/src/components/ReportGlobalErrors/styles.scss +12 -0
  65. package/src/components/ReportHeader/ReportHeaderLogo.tsx +6 -2
  66. package/src/components/ReportHeader/ReportHeaderPie.tsx +1 -2
  67. package/src/components/ReportHeader/index.tsx +38 -12
  68. package/src/components/ReportHeader/styles.scss +9 -1
  69. package/src/components/ReportMetadata/MetadataSummary.tsx +57 -65
  70. package/src/components/ReportMetadata/MetadataWithIcon.tsx +11 -13
  71. package/src/components/ReportMetadata/index.tsx +50 -3
  72. package/src/components/ReportMetadata/styles.scss +0 -2
  73. package/src/components/ReportQualityGateResults/index.tsx +42 -0
  74. package/src/components/ReportQualityGateResults/styles.scss +44 -0
  75. package/src/components/ReportTabs/index.tsx +37 -0
  76. package/src/components/SectionPicker/index.tsx +55 -0
  77. package/src/components/SectionPicker/styles.scss +5 -0
  78. package/src/components/SectionSwitcher/index.tsx +16 -0
  79. package/src/components/SectionSwitcher/styles.scss +4 -0
  80. package/src/components/SectionTabs/index.tsx +0 -0
  81. package/src/components/SideBySide/index.tsx +52 -0
  82. package/src/components/SideBySide/styles.scss +64 -0
  83. package/src/components/SplitLayout/index.tsx +71 -0
  84. package/src/components/SplitLayout/styles.scss +84 -0
  85. package/src/components/TestResult/TestStepsEmpty/index.tsx +3 -9
  86. package/src/components/TestResult/TrAttachmentsView/index.tsx +29 -0
  87. package/src/components/TestResult/{TestResultDescription → TrDescription}/index.tsx +5 -5
  88. package/src/components/TestResult/{TestResultDropdown → TrDropdown}/index.tsx +7 -5
  89. package/src/components/TestResult/{TestResultEmpty → TrEmpty}/index.tsx +7 -13
  90. package/src/components/TestResult/TrEnvironmentItem/index.tsx +82 -0
  91. package/src/components/TestResult/TrEnvironmentItem/styles.scss +60 -0
  92. package/src/components/TestResult/TrEnvironmentsView/index.tsx +64 -0
  93. package/src/components/TestResult/TrEnvironmentsView/styles.scss +11 -0
  94. package/src/components/TestResult/TrError/TrDiff.tsx +121 -0
  95. package/src/components/TestResult/TrError/index.tsx +111 -0
  96. package/src/components/TestResult/TrError/styles.scss +223 -0
  97. package/src/components/TestResult/TrHeader/TrBreadcrumbs.tsx +44 -0
  98. package/src/components/TestResult/TrHeader/index.tsx +15 -0
  99. package/src/components/TestResult/{TestResultHeader → TrHeader}/styles.scss +7 -2
  100. package/src/components/TestResult/TrHistory/TrHistoryItem.tsx +94 -0
  101. package/src/components/TestResult/TrHistory/index.tsx +26 -0
  102. package/src/components/TestResult/{TestResultHistory → TrHistory}/styles.scss +2 -1
  103. package/src/components/TestResult/{TestResultInfo/TestResultInfoStatuses.tsx → TrInfo/TrInfoStatuses.tsx} +6 -4
  104. package/src/components/TestResult/TrInfo/index.tsx +99 -0
  105. package/src/components/TestResult/{TestResultInfo → TrInfo}/styles.scss +18 -0
  106. package/src/components/TestResult/{TestResultLinks → TrLinks}/index.tsx +8 -8
  107. package/src/components/TestResult/{TestResultMetadata → TrMetadata}/index.tsx +6 -6
  108. package/src/components/TestResult/{TestResultNavigation → TrNavigation}/index.tsx +7 -9
  109. package/src/components/TestResult/TrOverview.tsx +46 -0
  110. package/src/components/TestResult/{TestResultParameters → TrParameters}/index.tsx +4 -4
  111. package/src/components/TestResult/TrPrevStatuses/index.tsx +63 -0
  112. package/src/components/TestResult/TrPwTraces/PwTrace.tsx +34 -0
  113. package/src/components/TestResult/TrPwTraces/PwTraceButton.tsx +32 -0
  114. package/src/components/TestResult/TrPwTraces/index.tsx +32 -0
  115. package/src/components/TestResult/TrPwTraces/styles.scss +20 -0
  116. package/src/components/TestResult/TrRetriesView/TrRetriesItem.tsx +70 -0
  117. package/src/components/TestResult/TrRetriesView/index.tsx +29 -0
  118. package/src/components/TestResult/{TestResultSetup → TrSetup}/index.tsx +13 -13
  119. package/src/components/TestResult/{TestResultSeverity → TrSeverity}/index.tsx +2 -2
  120. package/src/components/TestResult/{TestResultStatus → TrStatus}/index.tsx +5 -5
  121. package/src/components/TestResult/TrSteps/TrAttachment.tsx +118 -0
  122. package/src/components/TestResult/{TestResultSteps/testResultAttachmentInfo.tsx → TrSteps/TrAttachmentInfo.tsx} +11 -11
  123. package/src/components/TestResult/TrSteps/TrStep.tsx +98 -0
  124. package/src/components/TestResult/TrSteps/TrStepInfo.tsx +90 -0
  125. package/src/components/TestResult/{TestResultSteps → TrSteps}/index.tsx +12 -12
  126. package/src/components/TestResult/{TestResultSteps → TrSteps}/styles.scss +49 -10
  127. package/src/components/TestResult/{TestResultSteps → TrSteps}/wrongAttachment.tsx +1 -1
  128. package/src/components/TestResult/TrTabs/index.tsx +42 -0
  129. package/src/components/TestResult/{TestResultTeardown → TrTeardown}/index.tsx +13 -13
  130. package/src/components/TestResult/index.tsx +54 -38
  131. package/src/components/TestResult/styles.scss +12 -0
  132. package/src/components/Timeline/index.tsx +100 -0
  133. package/src/components/Timeline/styles.scss +45 -0
  134. package/src/components/ToggleLayout/index.tsx +17 -0
  135. package/src/components/Tree/index.tsx +117 -11
  136. package/src/components/Tree/styles.scss +23 -5
  137. package/src/index.html +22 -6
  138. package/src/index.tsx +90 -20
  139. package/src/locales/az.json +378 -0
  140. package/src/locales/de.json +378 -0
  141. package/src/locales/en.json +378 -0
  142. package/src/locales/es.json +378 -0
  143. package/src/locales/fr.json +378 -0
  144. package/src/locales/he.json +378 -0
  145. package/src/locales/hy.json +378 -0
  146. package/src/locales/it.json +378 -0
  147. package/src/locales/ja.json +378 -0
  148. package/src/locales/ka.json +378 -0
  149. package/src/locales/kr.json +378 -0
  150. package/src/locales/nl.json +378 -0
  151. package/src/locales/pl.json +386 -0
  152. package/src/locales/pt.json +378 -0
  153. package/src/locales/ru.json +386 -0
  154. package/src/locales/sv.json +378 -0
  155. package/src/locales/tr.json +378 -0
  156. package/src/locales/ua.json +329 -0
  157. package/src/locales/zh.json +378 -0
  158. package/src/stores/chart.ts +41 -6
  159. package/src/stores/env.ts +88 -0
  160. package/src/stores/envInfo.ts +2 -2
  161. package/src/stores/globals.ts +28 -0
  162. package/src/stores/layout.ts +36 -0
  163. package/src/stores/locale.ts +77 -29
  164. package/src/stores/modal.ts +22 -0
  165. package/src/stores/qualityGate.ts +28 -0
  166. package/src/stores/router.ts +108 -0
  167. package/src/stores/sections.ts +63 -0
  168. package/src/stores/stats.ts +52 -7
  169. package/src/stores/testResults.ts +13 -9
  170. package/src/stores/theme.ts +15 -18
  171. package/src/stores/timeline.ts +39 -0
  172. package/src/stores/tree.ts +65 -110
  173. package/src/stores/treeFilters/actions.ts +67 -0
  174. package/src/stores/treeFilters/constants.ts +7 -0
  175. package/src/stores/treeFilters/index.ts +3 -0
  176. package/src/stores/treeFilters/store.ts +73 -0
  177. package/src/stores/treeFilters/types.ts +12 -0
  178. package/src/stores/variables.ts +40 -0
  179. package/src/styles.scss +66 -0
  180. package/src/utils/persist.ts +23 -0
  181. package/src/utils/time.ts +1 -0
  182. package/src/utils/tree.ts +30 -0
  183. package/src/utils/treeFilters.ts +42 -24
  184. package/test/components/Header/CiInfo.test.tsx +177 -0
  185. package/test/components/Header.test.tsx +122 -0
  186. package/test/stores/treeFilters.test.ts +302 -0
  187. package/test/utils/treeFilters.test.ts +189 -44
  188. package/tsconfig.json +7 -2
  189. package/tsconfig.node.json +8 -0
  190. package/types.d.ts +45 -24
  191. package/vitest.config.ts +15 -2
  192. package/vitest.setup.ts +1 -0
  193. package/webpack.config.js +35 -5
  194. package/dist/multi/141.app-f32e4213.js +0 -1
  195. package/dist/multi/222.app-f32e4213.js +0 -1
  196. package/dist/multi/335.app-f32e4213.js +0 -1
  197. package/dist/multi/34.app-f32e4213.js +0 -1
  198. package/dist/multi/349.app-f32e4213.js +0 -1
  199. package/dist/multi/378.app-f32e4213.js +0 -1
  200. package/dist/multi/406.app-f32e4213.js +0 -1
  201. package/dist/multi/476.app-f32e4213.js +0 -1
  202. package/dist/multi/53.app-f32e4213.js +0 -1
  203. package/dist/multi/584.app-f32e4213.js +0 -1
  204. package/dist/multi/690.app-f32e4213.js +0 -1
  205. package/dist/multi/747.app-f32e4213.js +0 -1
  206. package/dist/multi/767.app-f32e4213.js +0 -1
  207. package/dist/multi/816.app-f32e4213.js +0 -1
  208. package/dist/multi/83.app-f32e4213.js +0 -1
  209. package/dist/multi/873.app-f32e4213.js +0 -1
  210. package/dist/multi/920.app-f32e4213.js +0 -1
  211. package/dist/multi/991.app-f32e4213.js +0 -1
  212. package/dist/multi/app-f32e4213.js +0 -2
  213. package/dist/multi/app-f32e4213.js.LICENSE.txt +0 -16
  214. package/dist/multi/styles-f32e4213.css +0 -284
  215. package/dist/single/app-7fa8e43f.js +0 -2
  216. package/dist/single/app-7fa8e43f.js.LICENSE.txt +0 -16
  217. package/src/assets/scss/code.scss +0 -71
  218. package/src/assets/scss/typography.scss +0 -218
  219. package/src/components/ArrowButton/index.tsx +0 -36
  220. package/src/components/ArrowButton/styles.scss +0 -35
  221. package/src/components/LanguagePicker/index.tsx +0 -40
  222. package/src/components/Modal/styles.scss +0 -126
  223. package/src/components/ReportLogo/index.tsx +0 -16
  224. package/src/components/ReportLogo/styles.scss +0 -20
  225. package/src/components/ReportLogoFull/index.tsx +0 -20
  226. package/src/components/ReportLogoFull/styles.scss +0 -7
  227. package/src/components/Tabs/index.tsx +0 -62
  228. package/src/components/TestResult/TestResultAttachmentsView/index.tsx +0 -27
  229. package/src/components/TestResult/TestResultError/index.tsx +0 -59
  230. package/src/components/TestResult/TestResultError/styles.scss +0 -51
  231. package/src/components/TestResult/TestResultHeader/index.tsx +0 -55
  232. package/src/components/TestResult/TestResultHistory/TestResultHistoryItem.tsx +0 -67
  233. package/src/components/TestResult/TestResultHistory/index.tsx +0 -26
  234. package/src/components/TestResult/TestResultInfo/index.tsx +0 -79
  235. package/src/components/TestResult/TestResultOverview.tsx +0 -43
  236. package/src/components/TestResult/TestResultPrevStatuses/index.tsx +0 -49
  237. package/src/components/TestResult/TestResultRetriesView/TestResultRetriesItem.tsx +0 -52
  238. package/src/components/TestResult/TestResultRetriesView/index.tsx +0 -24
  239. package/src/components/TestResult/TestResultSteps/HtmlAttachmentPreview.tsx +0 -12
  240. package/src/components/TestResult/TestResultSteps/attachment.tsx +0 -68
  241. package/src/components/TestResult/TestResultSteps/attachmentCode.tsx +0 -20
  242. package/src/components/TestResult/TestResultSteps/attachmentImage.tsx +0 -32
  243. package/src/components/TestResult/TestResultSteps/attachmentVideo.tsx +0 -15
  244. package/src/components/TestResult/TestResultSteps/testResultAttachment.tsx +0 -77
  245. package/src/components/TestResult/TestResultSteps/testResultStep.tsx +0 -85
  246. package/src/components/TestResult/TestResultSteps/testResultStepInfo.tsx +0 -30
  247. package/src/components/TestResult/TestResultTabs/index.tsx +0 -59
  248. package/src/components/ThemeButton/ThemeButton.tsx +0 -20
  249. package/src/components/Tree/Tree.tsx +0 -75
  250. package/src/components/Tree/TreeHeader.tsx +0 -82
  251. package/src/components/Tree/TreeItem.tsx +0 -35
  252. package/src/components/Tree/TreeItemIcon.tsx +0 -32
  253. package/src/i18n/constants.ts +0 -124
  254. package/src/i18n/locales/am.json +0 -120
  255. package/src/i18n/locales/az.json +0 -120
  256. package/src/i18n/locales/de.json +0 -120
  257. package/src/i18n/locales/en.json +0 -121
  258. package/src/i18n/locales/es.json +0 -120
  259. package/src/i18n/locales/fr.json +0 -120
  260. package/src/i18n/locales/he.json +0 -120
  261. package/src/i18n/locales/it.json +0 -120
  262. package/src/i18n/locales/ja.json +0 -120
  263. package/src/i18n/locales/ka.json +0 -120
  264. package/src/i18n/locales/kr.json +0 -120
  265. package/src/i18n/locales/nl.json +0 -120
  266. package/src/i18n/locales/pl.json +0 -118
  267. package/src/i18n/locales/pt.json +0 -120
  268. package/src/i18n/locales/ru.json +0 -118
  269. package/src/i18n/locales/sv.json +0 -120
  270. package/src/i18n/locales/tr.json +0 -120
  271. package/src/i18n/locales/zh.json +0 -120
  272. package/src/utils/attachments.ts +0 -156
  273. package/src/utils/capitalize.ts +0 -6
  274. /package/dist/multi/{JetBrainsMono_vf-b9a9c326..woff → JetBrainsMono_vf.woff} +0 -0
  275. /package/dist/multi/{JetBrainsMono_vf-9e9649b6..woff2 → JetBrainsMono_vf.woff2} +0 -0
  276. /package/dist/multi/{pt-root-ui_vf-22fe60ca..woff → pt-root-ui_vf.woff} +0 -0
  277. /package/dist/multi/{pt-root-ui_vf-9d251e8b..woff2 → pt-root-ui_vf.woff2} +0 -0
  278. /package/src/components/{Tabs → ReportTabs}/styles.scss +0 -0
  279. /package/src/components/TestResult/{TestResultAttachmentsView → TrAttachmentsView}/styles.scss +0 -0
  280. /package/src/components/TestResult/{TestResultDescription → TrDescription}/styles.scss +0 -0
  281. /package/src/components/TestResult/{TestResultDropdown → TrDropdown}/styles.scss +0 -0
  282. /package/src/components/TestResult/{TestResultEmpty → TrEmpty}/styles.scss +0 -0
  283. /package/src/components/TestResult/{TestResultLinks → TrLinks}/styles.scss +0 -0
  284. /package/src/components/TestResult/{TestResultMetadata → TrMetadata}/styles.scss +0 -0
  285. /package/src/components/TestResult/{TestResultNavigation → TrNavigation}/styles.scss +0 -0
  286. /package/src/components/TestResult/{TestResultParameters → TrParameters}/styles.scss +0 -0
  287. /package/src/components/TestResult/{TestResultPrevStatuses → TrPrevStatuses}/styles.scss +0 -0
  288. /package/src/components/TestResult/{TestResultRetriesView → TrRetriesView}/styles.scss +0 -0
  289. /package/src/components/TestResult/{TestResultSeverity → TrSeverity}/styles.scss +0 -0
  290. /package/src/components/TestResult/{TestResultStatus → TrStatus}/styles.scss +0 -0
@@ -1,15 +1,14 @@
1
- import { getReportOptions } from "@allurereport/web-commons";
1
+ import { formatDuration } from "@allurereport/core-api";
2
+ import { DEFAULT_LOCALE, LANG_LOCALE, type LangLocale, getReportOptions } from "@allurereport/web-commons";
2
3
  import { computed, signal } from "@preact/signals";
3
4
  import i18next, { type TOptions } from "i18next";
4
- import { DEFAULT_LOCALE, LANG_LOCALE, type LangLocale } from "@/i18n/constants";
5
- import type { AllureAwesomeReportOptions } from "../../types.js";
6
-
7
- const { reportLanguage } = getReportOptions<AllureAwesomeReportOptions>() ?? {};
5
+ import type { AwesomeReportOptions } from "types";
8
6
 
9
7
  const namespaces = [
10
8
  "empty",
11
9
  "execution",
12
10
  "filters",
11
+ "filters.description",
13
12
  "search",
14
13
  "severity",
15
14
  "sort-by",
@@ -22,31 +21,36 @@ const namespaces = [
22
21
  "welcome",
23
22
  "controls",
24
23
  "errors",
25
- ];
24
+ "split",
25
+ "modal",
26
+ "environments",
27
+ "charts",
28
+ "sections",
29
+ "timeline",
30
+ "transitions",
31
+ ] as const;
26
32
 
27
33
  export const currentLocale = signal<LangLocale>("en" as LangLocale);
34
+ export const currentLocaleIso = computed(() => LANG_LOCALE[currentLocale.value]?.iso ?? LANG_LOCALE.en.iso);
35
+ export const currentLocaleIsRTL = computed(() => ["ar", "he", "fa"].includes(currentLocale.value));
28
36
 
29
- export const currentLocaleIso = computed(() => {
30
- const locale = currentLocale.value;
31
-
32
- return LANG_LOCALE[locale].iso;
33
- });
34
-
35
- export const currentLocaleIsRTL = computed(() => {
36
- return ["ar", "he", "fa"].includes(currentLocale.value as string);
37
- });
38
-
39
- export const getLocale = () => {
37
+ export const getLocale = async () => {
38
+ const { reportLanguage } = getReportOptions<AwesomeReportOptions>() ?? {};
40
39
  const locale = localStorage.getItem("currentLocale") || reportLanguage || DEFAULT_LOCALE;
41
- setLocale(locale as LangLocale);
40
+
41
+ await setLocale(locale as LangLocale);
42
42
  };
43
43
 
44
- i18next
44
+ export const waitForI18next = i18next
45
45
  .use({
46
46
  type: "backend",
47
- async read(language: LangLocale, namespace: string, callback: (errorValue: unknown, translations: null) => void) {
48
- await import(`@/i18n/locales/${language}.json`)
49
- .then((resources) => {
47
+ read: async (
48
+ language: LangLocale,
49
+ namespace: string,
50
+ callback: (errorValue: unknown, translations: null) => void,
51
+ ) => {
52
+ await import(`@/locales/${language}.json`)
53
+ .then((resources: Record<string, null>) => {
50
54
  callback(null, resources[namespace]);
51
55
  })
52
56
  .catch((error) => {
@@ -58,13 +62,57 @@ i18next
58
62
  lng: currentLocale.value,
59
63
  fallbackLng: "en",
60
64
  ns: namespaces,
61
- interpolation: {
62
- escapeValue: false,
63
- },
65
+ interpolation: { escapeValue: false },
66
+ })
67
+ .then(() => {
68
+ i18next.services.formatter.add("capitalize", (value) => {
69
+ return value.charAt(0).toLocaleUpperCase() + value.slice(1);
70
+ });
71
+ i18next.services.formatter.add("timestamp_date", (value: number, lng, options) => {
72
+ const formatter = new Intl.DateTimeFormat(lng, {
73
+ ...options,
74
+ month: "numeric",
75
+ day: "numeric",
76
+ year: "numeric",
77
+ });
78
+ return formatter.format(value);
79
+ });
80
+ i18next.services.formatter.add("timestamp_long", (value: number, lng, options) => {
81
+ const formatter = new Intl.DateTimeFormat(lng, {
82
+ ...options,
83
+ month: "numeric",
84
+ day: "numeric",
85
+ year: "numeric",
86
+ hour: "numeric",
87
+ minute: "numeric",
88
+ second: "numeric",
89
+ hour12: false,
90
+ });
91
+ return formatter.format(value).replace(",", ` ${i18next.t("ui:at")}`);
92
+ });
93
+ i18next.services.formatter.add("timestamp_long_no_seconds", (value: number, lng, options) => {
94
+ const formatter = new Intl.DateTimeFormat(lng, {
95
+ ...options,
96
+ month: "numeric",
97
+ day: "numeric",
98
+ year: "numeric",
99
+ hour: "numeric",
100
+ minute: "numeric",
101
+ hour12: false,
102
+ });
103
+ return formatter.format(value).replace(",", ` ${i18next.t("ui:at")}`);
104
+ });
105
+ i18next.services.formatter.add("format_duration", (value: number) => {
106
+ return formatDuration(value);
107
+ });
64
108
  });
65
109
 
66
- export const useI18n = (namespace?: string) => {
67
- const t = computed(() => (key: string, options?: TOptions) => i18next.t(key, { ns: namespace, ...options }));
110
+ export const useI18n = (namespace: (typeof namespaces)[number]) => {
111
+ const t = computed(
112
+ () =>
113
+ (key: string, options: TOptions = {}) =>
114
+ i18next.t(key, { ns: namespace, ...options }),
115
+ );
68
116
 
69
117
  return {
70
118
  t: t.value,
@@ -73,7 +121,7 @@ export const useI18n = (namespace?: string) => {
73
121
  };
74
122
 
75
123
  export const setLocale = async (locale: LangLocale) => {
76
- await i18next.changeLanguage(locale);
77
- localStorage.setItem("currentLocale", locale);
124
+ await i18next.changeLanguage(locale as string);
125
+ localStorage.setItem("currentLocale", locale as string);
78
126
  currentLocale.value = locale;
79
127
  };
@@ -0,0 +1,22 @@
1
+ import type { ModalDataProps } from "@allurereport/web-components";
2
+ import { signal } from "@preact/signals";
3
+
4
+ export const isModalOpen = signal(false);
5
+
6
+ export const modalData = signal<ModalDataProps>({
7
+ data: null,
8
+ preview: false,
9
+ component: null,
10
+ isModalOpen: isModalOpen.value,
11
+ closeModal: null,
12
+ title: "",
13
+ });
14
+
15
+ export const openModal = (props: ModalDataProps) => {
16
+ modalData.value = { ...props };
17
+ isModalOpen.value = true;
18
+ };
19
+
20
+ export const closeModal = () => {
21
+ isModalOpen.value = false;
22
+ };
@@ -0,0 +1,28 @@
1
+ import { QualityGateValidationResult } from "@allurereport/plugin-api";
2
+ import { fetchReportJsonData } from "@allurereport/web-commons";
3
+ import { signal } from "@preact/signals";
4
+ import { type StoreSignalState } from "./types";
5
+
6
+ export const qualityGateStore = signal<StoreSignalState<QualityGateValidationResult[]>>({
7
+ loading: true,
8
+ error: undefined,
9
+ data: undefined,
10
+ });
11
+
12
+ export const fetchQualityGateResults = async () => {
13
+ try {
14
+ const data = await fetchReportJsonData<QualityGateValidationResult[]>("widgets/quality-gate.json");
15
+
16
+ qualityGateStore.value = {
17
+ data,
18
+ error: undefined,
19
+ loading: false,
20
+ };
21
+ } catch (err) {
22
+ qualityGateStore.value = {
23
+ ...qualityGateStore.value,
24
+ error: err.message,
25
+ loading: false,
26
+ };
27
+ }
28
+ };
@@ -0,0 +1,108 @@
1
+ import { computed, signal } from "@preact/signals";
2
+
3
+ type NavigateToObject = {
4
+ category?: string;
5
+ params?: {
6
+ testResultId?: string | null;
7
+ subTab?: string | null;
8
+ };
9
+ };
10
+
11
+ type Route = {
12
+ category?: string;
13
+ params?: {
14
+ testResultId?: string | null;
15
+ subTab?: string | null;
16
+ };
17
+ };
18
+
19
+ export const parseHash = (): Route => {
20
+ const hash = globalThis.location.hash.replace(/^#/, "").trim();
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 {};
59
+ };
60
+
61
+ export const route = signal<Route>(parseHash());
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
+ }
73
+ };
74
+
75
+ export const navigateTo = (path: NavigateToObject | string) => {
76
+ let newHash = "";
77
+
78
+ if (typeof path === "string") {
79
+ newHash = path.startsWith("#") ? path.slice(1) : path;
80
+ } else {
81
+ const { category, params = {} } = path;
82
+ const parts: string[] = [];
83
+
84
+ if (category) {
85
+ parts.push(category);
86
+ }
87
+
88
+ if (params.testResultId) {
89
+ parts.push(params.testResultId);
90
+ }
91
+
92
+ if (params.subTab) {
93
+ parts.push(params.subTab);
94
+ }
95
+
96
+ newHash = parts.join("/");
97
+ }
98
+
99
+ history.pushState(null, "", `#${newHash}`);
100
+ handleHashChange();
101
+ };
102
+
103
+ export const openInNewTab = (path: string) => {
104
+ window.open(`#${path}`, "_blank");
105
+ };
106
+
107
+ export const activeTab = computed(() => route.value.category || "");
108
+ export const activeSubTab = computed(() => route.value.params?.subTab || "overview");
@@ -0,0 +1,63 @@
1
+ import { getReportOptions } from "@allurereport/web-commons";
2
+ import { effect, signal } from "@preact/signals";
3
+ import { navigateTo, parseHash, route } from "@/stores/router";
4
+ import type { AwesomeReportOptions } from "../../types.js";
5
+
6
+ const DEFAULT_SECTION = "default";
7
+ type Section = string;
8
+
9
+ export const currentSection = signal<Section>("");
10
+ export const availableSections = signal<Section[]>([]);
11
+
12
+ const updateSectionState = (section: Section): void => {
13
+ currentSection.value = section;
14
+ document.documentElement.setAttribute("data-section", section);
15
+ globalThis.localStorage.setItem("chosenSection", section);
16
+ };
17
+
18
+ export const setSection = (chosenSection: Section): void => {
19
+ const isDefaultSection = chosenSection === DEFAULT_SECTION;
20
+ const isValidSection = availableSections.value?.includes(chosenSection);
21
+ const isSectionChanged = currentSection.value !== chosenSection;
22
+
23
+ updateSectionState(chosenSection);
24
+
25
+ if (isDefaultSection) {
26
+ navigateTo({ category: "" });
27
+ return;
28
+ }
29
+
30
+ if (isSectionChanged && isValidSection) {
31
+ navigateTo({ category: chosenSection });
32
+ }
33
+ };
34
+
35
+ export const getSection = () => {
36
+ const { category } = parseHash();
37
+ availableSections.value = getReportOptions<AwesomeReportOptions>()?.sections ?? [];
38
+ const defaultSectionFromReportOptions = getReportOptions<AwesomeReportOptions>()?.defaultSection ?? "";
39
+ const sectionFromUrl = parseHash().category;
40
+ const sectionFromLS =
41
+ globalThis.localStorage.getItem("chosenSection") === ""
42
+ ? ""
43
+ : globalThis.localStorage.getItem("chosenSection") || defaultSectionFromReportOptions;
44
+ currentSection.value = sectionFromUrl || sectionFromLS;
45
+
46
+ if (category) {
47
+ setSection(category);
48
+ return;
49
+ }
50
+
51
+ if (sectionFromLS) {
52
+ setSection(sectionFromLS);
53
+ return;
54
+ }
55
+
56
+ setSection("");
57
+ };
58
+
59
+ effect(() => {
60
+ const category = route.value.category;
61
+
62
+ setSection(category || "");
63
+ });
@@ -2,8 +2,9 @@ import type { Statistic } from "@allurereport/core-api";
2
2
  import { fetchReportJsonData } from "@allurereport/web-commons";
3
3
  import { signal } from "@preact/signals";
4
4
  import type { StoreSignalState } from "@/stores/types";
5
+ import type { AwesomeTree } from "../../types";
5
6
 
6
- export const statsStore = signal<StoreSignalState<Statistic>>({
7
+ export const reportStatsStore = signal<StoreSignalState<Statistic>>({
7
8
  loading: true,
8
9
  error: undefined,
9
10
  data: {
@@ -11,26 +12,70 @@ export const statsStore = signal<StoreSignalState<Statistic>>({
11
12
  },
12
13
  });
13
14
 
14
- export const fetchStats = async () => {
15
- statsStore.value = {
16
- ...statsStore.value,
15
+ export const statsByEnvStore = signal<StoreSignalState<Record<string, Statistic>>>({
16
+ loading: true,
17
+ error: undefined,
18
+ data: {},
19
+ });
20
+
21
+ export const fetchReportStats = async () => {
22
+ reportStatsStore.value = {
23
+ ...reportStatsStore.value,
17
24
  loading: true,
18
25
  error: undefined,
19
26
  };
20
27
 
21
28
  try {
22
- const res = await fetchReportJsonData<Statistic>("widgets/allure_statistic.json");
29
+ const res = await fetchReportJsonData<Statistic>("widgets/statistic.json", { bustCache: true });
23
30
 
24
- statsStore.value = {
31
+ reportStatsStore.value = {
25
32
  data: res,
26
33
  error: undefined,
27
34
  loading: false,
28
35
  };
29
36
  } catch (err) {
30
- statsStore.value = {
37
+ reportStatsStore.value = {
31
38
  data: { total: 0 },
32
39
  error: err.message,
33
40
  loading: false,
34
41
  };
35
42
  }
36
43
  };
44
+
45
+ export const fetchEnvStats = async (envs: string[]) => {
46
+ const envsToFetch = envs.filter((env) => !statsByEnvStore.value.data?.[env]);
47
+
48
+ // all envs have already been fetched
49
+ if (envsToFetch.length === 0) {
50
+ return;
51
+ }
52
+
53
+ statsByEnvStore.value = {
54
+ ...statsByEnvStore.value,
55
+ loading: true,
56
+ error: undefined,
57
+ };
58
+
59
+ try {
60
+ const data = await Promise.all(
61
+ envsToFetch.map((env) => fetchReportJsonData<AwesomeTree>(`widgets/${env}/statistic.json`, { bustCache: true })),
62
+ );
63
+
64
+ statsByEnvStore.value = {
65
+ data: envs.reduce((acc, env, index) => {
66
+ return {
67
+ ...acc,
68
+ [env]: data[index],
69
+ };
70
+ }, {}),
71
+ loading: false,
72
+ error: undefined,
73
+ };
74
+ } catch (err) {
75
+ statsByEnvStore.value = {
76
+ ...statsByEnvStore.value,
77
+ error: err.message,
78
+ loading: false,
79
+ };
80
+ }
81
+ };
@@ -1,27 +1,29 @@
1
1
  import { fetchReportJsonData } from "@allurereport/web-commons";
2
2
  import { signal } from "@preact/signals";
3
- import { type AllureAwesomeTestResult } from "../../types";
3
+ import { type AwesomeTestResult } from "../../types";
4
4
  import { type StoreSignalState } from "./types";
5
5
 
6
- export type TestResultsStoreState = Record<string, AllureAwesomeTestResult>;
6
+ export type TrStoreState = Record<string, AwesomeTestResult>;
7
7
 
8
- export type TestResultNavStoreState = string[];
8
+ export type TrNavStoreState = string[];
9
9
 
10
- export const testResultStore = signal<StoreSignalState<TestResultsStoreState>>({
10
+ export const testResultStore = signal<StoreSignalState<TrStoreState>>({
11
11
  loading: true,
12
12
  error: undefined,
13
13
  data: undefined,
14
14
  });
15
15
 
16
- export const testResultNavStore = signal<StoreSignalState<TestResultNavStoreState>>({
16
+ export const testResultNavStore = signal<StoreSignalState<TrNavStoreState>>({
17
17
  loading: true,
18
18
  error: undefined,
19
19
  data: undefined,
20
20
  });
21
21
 
22
- export const fetchTestResultNav = async () => {
22
+ export const fetchTestResultNav = async (env?: string) => {
23
23
  try {
24
- const data = await fetchReportJsonData<string[]>("widgets/nav.json");
24
+ const data = await fetchReportJsonData<string[]>(env ? `widgets/${env}/nav.json` : "widgets/nav.json", {
25
+ bustCache: true,
26
+ });
25
27
 
26
28
  testResultNavStore.value = {
27
29
  data,
@@ -38,7 +40,7 @@ export const fetchTestResultNav = async () => {
38
40
  };
39
41
 
40
42
  export const fetchTestResult = async (testResultId: string) => {
41
- if (!testResultId) {
43
+ if (!testResultId || (testResultStore.value.data && testResultId in testResultStore.value.data)) {
42
44
  return;
43
45
  }
44
46
 
@@ -49,7 +51,9 @@ export const fetchTestResult = async (testResultId: string) => {
49
51
  };
50
52
 
51
53
  try {
52
- const data = await fetchReportJsonData<AllureAwesomeTestResult>(`data/test-results/${testResultId}.json`);
54
+ const data = await fetchReportJsonData<AwesomeTestResult>(`data/test-results/${testResultId}.json`, {
55
+ bustCache: true,
56
+ });
53
57
 
54
58
  testResultStore.value = {
55
59
  data: { ...testResultStore.value.data, [testResultId]: data },
@@ -1,33 +1,30 @@
1
1
  import { getReportOptions } from "@allurereport/web-commons";
2
+ import type { Theme } from "@allurereport/web-components";
2
3
  import { signal } from "@preact/signals";
3
- import type { AllureAwesomeReportOptions } from "../../types.js";
4
+ import type { AwesomeReportOptions } from "../../types.js";
4
5
 
5
- type Theme = "light" | "dark";
6
+ export const themeStore = signal<Theme>("auto");
6
7
 
7
- const { theme } = getReportOptions<AllureAwesomeReportOptions>() ?? {};
8
+ export const setTheme = (mode: "light" | "dark" | "auto") => {
9
+ themeStore.value = mode;
8
10
 
9
- export const themeStore = signal<Theme>("light");
11
+ try {
12
+ window.localStorage.setItem("theme", mode);
13
+ } catch {}
10
14
 
11
- export const setTheme = (newTheme: Theme): void => {
12
- themeStore.value = newTheme;
13
- document.documentElement.setAttribute("data-theme", newTheme);
14
- window.localStorage.setItem("theme", newTheme);
15
+ document.documentElement.setAttribute("data-theme", mode);
15
16
  };
16
17
 
17
18
  export const toggleTheme = () => {
18
- setTheme(themeStore.value === "light" ? "dark" : "light");
19
+ const order = ["light", "dark", "auto"];
20
+ const current = themeStore.value;
21
+ const next = order[(order.indexOf(current) + 1) % order.length] as Theme;
22
+ setTheme(next);
19
23
  };
20
24
 
21
25
  export const getTheme = () => {
26
+ const { theme } = getReportOptions<AwesomeReportOptions>() ?? {};
22
27
  const themeFromLS = (window.localStorage.getItem("theme") as Theme | null) || (theme as Theme);
23
28
 
24
- if (themeFromLS) {
25
- setTheme(themeFromLS);
26
- return;
27
- }
28
-
29
- const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)").matches;
30
- const initialTheme = prefersDarkScheme ? "dark" : "light";
31
-
32
- setTheme(initialTheme);
29
+ setTheme(themeFromLS);
33
30
  };
@@ -0,0 +1,39 @@
1
+ import type { TestResult } from "@allurereport/core-api";
2
+ import { fetchReportJsonData } from "@allurereport/web-commons";
3
+ import { signal } from "@preact/signals";
4
+ import type { StoreSignalState } from "@/stores/types";
5
+
6
+ export type TimlineTr = Pick<
7
+ TestResult,
8
+ "id" | "name" | "status" | "flaky" | "hidden" | "labels" | "environment" | "start" | "stop" | "duration"
9
+ >;
10
+
11
+ export const timelineStore = signal<StoreSignalState<TimlineTr[]>>({
12
+ loading: true,
13
+ error: undefined,
14
+ data: undefined,
15
+ });
16
+
17
+ export const fetchTimelineData = async () => {
18
+ timelineStore.value = {
19
+ ...timelineStore.value,
20
+ loading: true,
21
+ error: undefined,
22
+ };
23
+
24
+ try {
25
+ const res = await fetchReportJsonData<TimlineTr[]>("widgets/timeline.json", { bustCache: true });
26
+
27
+ timelineStore.value = {
28
+ data: res,
29
+ error: undefined,
30
+ loading: false,
31
+ };
32
+ } catch (err) {
33
+ timelineStore.value = {
34
+ data: undefined,
35
+ error: err.message,
36
+ loading: false,
37
+ };
38
+ }
39
+ };