@allurereport/web-classic 3.0.1 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/multi/app-d6b3181758d7bcaf59fb.js +2 -0
  2. package/dist/multi/{app-81fc0bb26fd1b73b22f9.js.LICENSE.txt → app-d6b3181758d7bcaf59fb.js.LICENSE.txt} +7 -0
  3. package/dist/multi/manifest.json +22 -22
  4. package/dist/multi/{styles-02faf4bb6ebabe212265.css → styles-0a265e78e1a527b133dd.css} +2 -2
  5. package/dist/single/app-5b0e25f6b516905c3adc.js +2 -0
  6. package/dist/single/{app-997b57d6b8885a4f88c7.js.LICENSE.txt → app-5b0e25f6b516905c3adc.js.LICENSE.txt} +7 -0
  7. package/dist/single/manifest.json +1 -1
  8. package/package.json +6 -7
  9. package/src/components/BaseLayout/styles.scss +0 -3
  10. package/src/components/Overview/index.tsx +7 -3
  11. package/src/components/TestResult/TestResultDescription/index.tsx +60 -10
  12. package/src/components/TestResult/TestResultDescription/styles.scss +4 -0
  13. package/src/components/TestResult/TestResultOverview.tsx +2 -2
  14. package/src/components/ThemeButton/ThemeButton.tsx +6 -17
  15. package/src/index.html +39 -36
  16. package/src/index.tsx +1 -2
  17. package/src/stores/index.ts +0 -1
  18. package/src/stores/locale.ts +2 -1
  19. package/src/translations/constants.ts +24 -18
  20. package/src/utils/time.ts +16 -2
  21. package/src/utils/treeFilters.ts +1 -0
  22. package/types.d.ts +1 -1
  23. package/dist/multi/app-81fc0bb26fd1b73b22f9.js +0 -2
  24. package/dist/single/app-997b57d6b8885a4f88c7.js +0 -2
  25. package/src/stores/theme.ts +0 -30
  26. /package/dist/multi/{10.app-81fc0bb26fd1b73b22f9.js → 10.app-d6b3181758d7bcaf59fb.js} +0 -0
  27. /package/dist/multi/{222.app-81fc0bb26fd1b73b22f9.js → 222.app-d6b3181758d7bcaf59fb.js} +0 -0
  28. /package/dist/multi/{26.app-81fc0bb26fd1b73b22f9.js → 26.app-d6b3181758d7bcaf59fb.js} +0 -0
  29. /package/dist/multi/{302.app-81fc0bb26fd1b73b22f9.js → 302.app-d6b3181758d7bcaf59fb.js} +0 -0
  30. /package/dist/multi/{304.app-81fc0bb26fd1b73b22f9.js → 304.app-d6b3181758d7bcaf59fb.js} +0 -0
  31. /package/dist/multi/{369.app-81fc0bb26fd1b73b22f9.js → 369.app-d6b3181758d7bcaf59fb.js} +0 -0
  32. /package/dist/multi/{389.app-81fc0bb26fd1b73b22f9.js → 389.app-d6b3181758d7bcaf59fb.js} +0 -0
  33. /package/dist/multi/{498.app-81fc0bb26fd1b73b22f9.js → 498.app-d6b3181758d7bcaf59fb.js} +0 -0
  34. /package/dist/multi/{60.app-81fc0bb26fd1b73b22f9.js → 60.app-d6b3181758d7bcaf59fb.js} +0 -0
  35. /package/dist/multi/{643.app-81fc0bb26fd1b73b22f9.js → 643.app-d6b3181758d7bcaf59fb.js} +0 -0
  36. /package/dist/multi/{671.app-81fc0bb26fd1b73b22f9.js → 671.app-d6b3181758d7bcaf59fb.js} +0 -0
  37. /package/dist/multi/{725.app-81fc0bb26fd1b73b22f9.js → 725.app-d6b3181758d7bcaf59fb.js} +0 -0
  38. /package/dist/multi/{770.app-81fc0bb26fd1b73b22f9.js → 770.app-d6b3181758d7bcaf59fb.js} +0 -0
  39. /package/dist/multi/{848.app-81fc0bb26fd1b73b22f9.js → 848.app-d6b3181758d7bcaf59fb.js} +0 -0
  40. /package/dist/multi/{853.app-81fc0bb26fd1b73b22f9.js → 853.app-d6b3181758d7bcaf59fb.js} +0 -0
  41. /package/dist/multi/{872.app-81fc0bb26fd1b73b22f9.js → 872.app-d6b3181758d7bcaf59fb.js} +0 -0
  42. /package/dist/multi/{895.app-81fc0bb26fd1b73b22f9.js → 895.app-d6b3181758d7bcaf59fb.js} +0 -0
  43. /package/dist/multi/{920.app-81fc0bb26fd1b73b22f9.js → 920.app-d6b3181758d7bcaf59fb.js} +0 -0
  44. /package/dist/multi/{979.app-81fc0bb26fd1b73b22f9.js → 979.app-d6b3181758d7bcaf59fb.js} +0 -0
  45. /package/dist/multi/{991.app-81fc0bb26fd1b73b22f9.js → 991.app-d6b3181758d7bcaf59fb.js} +0 -0
@@ -23,3 +23,10 @@
23
23
  * @license BSD-3-Clause
24
24
  * @version 10.1.6
25
25
  */
26
+
27
+ /**!
28
+ * Sortable 1.15.6
29
+ * @author RubaXa <trash@rubaxa.org>
30
+ * @author owenm <owen23355@gmail.com>
31
+ * @license MIT
32
+ */
@@ -1,3 +1,3 @@
1
1
  {
2
- "main.js": "app-997b57d6b8885a4f88c7.js"
2
+ "main.js": "app-5b0e25f6b516905c3adc.js"
3
3
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allurereport/web-classic",
3
- "version": "3.0.1",
3
+ "version": "3.2.0",
4
4
  "description": "The static files for Allure Classic Report",
5
5
  "keywords": [
6
6
  "allure",
@@ -31,18 +31,17 @@
31
31
  "IE 11"
32
32
  ],
33
33
  "dependencies": {
34
- "@allurereport/charts-api": "3.0.1",
35
- "@allurereport/core-api": "3.0.1",
36
- "@allurereport/web-commons": "3.0.1",
37
- "@allurereport/web-components": "3.0.1",
38
- "@preact/signals": "^1.3.0",
34
+ "@allurereport/charts-api": "3.2.0",
35
+ "@allurereport/core-api": "3.2.0",
36
+ "@allurereport/web-commons": "3.2.0",
37
+ "@allurereport/web-components": "3.2.0",
38
+ "@preact/signals": "^2.6.1",
39
39
  "clsx": "^2.1.1",
40
40
  "d3-shape": "^3.2.0",
41
41
  "i18next": "^24.0.2",
42
42
  "md5": "^2.3.0",
43
43
  "preact": "^10.28.2",
44
44
  "prismjs": "^1.30.0",
45
- "reset.css": "^2.0.2",
46
45
  "split.js": "^1.6.5"
47
46
  },
48
47
  "devDependencies": {
@@ -1,6 +1,5 @@
1
1
  .layout {
2
2
  margin: auto;
3
- //padding: 12px 32px;
4
3
  background: var(--bg-base-primary);
5
4
  color: var(--on-text-primary);
6
5
  font-size: 14px;
@@ -11,10 +10,8 @@
11
10
  }
12
11
 
13
12
  .wrapper {
14
- //max-width: 920px;
15
13
  width: 100%;
16
14
  flex-direction: column;
17
- //margin: auto;
18
15
  }
19
16
 
20
17
  .content {
@@ -3,6 +3,7 @@
3
3
  /* eslint-disable @typescript-eslint/no-unsafe-argument */
4
4
  import { ChartType } from "@allurereport/charts-api";
5
5
  import type { UIChartData } from "@allurereport/web-commons";
6
+ import { themeStore } from "@allurereport/web-commons";
6
7
  import {
7
8
  Grid,
8
9
  GridItem,
@@ -12,14 +13,15 @@ import {
12
13
  ThemeProvider,
13
14
  TreeMapChartWidget,
14
15
  } from "@allurereport/web-components";
16
+ import { computed } from "@preact/signals";
15
17
  import { useEffect } from "preact/hooks";
16
- import { themeStore, useI18n } from "@/stores";
18
+ import { useI18n } from "@/stores";
17
19
  import { chartsStore, fetchChartsData } from "@/stores/charts";
18
20
  import * as styles from "./Overview.module.scss";
19
21
 
20
22
  const getChartWidgetByType = (
21
23
  chartData: UIChartData,
22
- { t, empty }: Record<string, (key: string, options?: any) => string>,
24
+ { empty }: Record<string, (key: string, options?: any) => string>,
23
25
  ) => {
24
26
  switch (chartData.type) {
25
27
  case ChartType.CoverageDiff: {
@@ -65,6 +67,8 @@ const getChartWidgetByType = (
65
67
  }
66
68
  };
67
69
 
70
+ const currentTheme = computed(() => themeStore.value.current);
71
+
68
72
  const Overview = () => {
69
73
  const { t } = useI18n("charts");
70
74
  const { t: empty } = useI18n("empty");
@@ -74,7 +78,7 @@ const Overview = () => {
74
78
  }, []);
75
79
 
76
80
  return (
77
- <ThemeProvider theme={themeStore.value}>
81
+ <ThemeProvider theme={currentTheme.value}>
78
82
  <Loadable
79
83
  source={chartsStore}
80
84
  renderLoader={() => <PageLoader />}
@@ -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 { ClassicTestResult } from "types";
5
5
  import { MetadataButton } from "@/components/MetadataButton";
6
6
  import * as styles from "./styles.scss";
7
7
 
8
8
  export type TestResultDescriptionProps = {
9
- description: ClassicTestResult["description"];
9
+ descriptionHtml: ClassicTestResult["descriptionHtml"];
10
10
  };
11
11
 
12
- export const TestResultDescription: FunctionalComponent<TestResultDescriptionProps> = ({ description }) => {
13
- const [isOpen, setIsOpen] = useState<boolean>(true);
12
+ const MIN_HEIGHT = 120;
13
+
14
+ export const TestResultDescription: FunctionalComponent<TestResultDescriptionProps> = ({ 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 || "Description mock"}
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
  }
@@ -15,7 +15,7 @@ export type TestResultOverviewProps = {
15
15
  };
16
16
 
17
17
  export const TestResultOverview: FunctionalComponent<TestResultOverviewProps> = ({ testResult }) => {
18
- const { error, parameters, groupedLabels, links, description, setup, steps, teardown } = testResult || {};
18
+ const { error, parameters, groupedLabels, links, descriptionHtml, setup, steps, teardown } = testResult || {};
19
19
 
20
20
  return (
21
21
  <>
@@ -29,7 +29,7 @@ export const TestResultOverview: FunctionalComponent<TestResultOverviewProps> =
29
29
  <TestResultMetadata testResult={testResult} />
30
30
  )}
31
31
  {Boolean(links?.length) && <TestResultLinks links={links} />}
32
- {Boolean(description) && <TestResultDescription description={description} />}
32
+ {Boolean(descriptionHtml) && <TestResultDescription descriptionHtml={descriptionHtml} />}
33
33
  <div className={styles["test-results"]}>
34
34
  {Boolean(setup?.length) && <TestResultSetup setup={setup} />}
35
35
  {Boolean(steps?.length) && <TestResultSteps steps={steps} />}
@@ -1,20 +1,9 @@
1
- import { IconButton, allureIcons } from "@allurereport/web-components";
2
- import { useEffect } from "preact/hooks";
3
- import { getTheme, themeStore, toggleTheme } from "@/stores/theme";
1
+ import { themeStore, toggleUserTheme } from "@allurereport/web-commons";
2
+ import { ThemeButton as UIThemeButton } from "@allurereport/web-components";
3
+ import { computed } from "@preact/signals";
4
4
 
5
- export const ThemeButton = () => {
6
- const theme = themeStore.value;
7
-
8
- useEffect(() => {
9
- getTheme();
10
- }, []);
5
+ const selectedTheme = computed(() => themeStore.value.selected);
11
6
 
12
- return (
13
- <IconButton
14
- onClick={toggleTheme}
15
- style="ghost"
16
- icon={theme === "light" ? allureIcons.lineShapesMoon : allureIcons.lineShapesSun}
17
- size="s"
18
- />
19
- );
7
+ export const ThemeButton = () => {
8
+ return <UIThemeButton theme={selectedTheme.value} toggleTheme={toggleUserTheme} />;
20
9
  };
package/src/index.html CHANGED
@@ -1,40 +1,43 @@
1
- <!DOCTYPE html>
1
+ <!doctype html>
2
2
  <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <!-- Inline favicon for single single-file build -->
6
- <link rel="icon" href="data:image/svg+xml,%3Csvg width='32' height='32' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M22.232 4.662a3.6 3.6 0 0 1 5.09.035c2.855 2.894 4.662 6.885 4.662 11.295a3.6 3.6 0 0 1-7.2 0c0-2.406-.981-4.61-2.587-6.24a3.6 3.6 0 0 1 .035-5.09Z' fill='url(%23a)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M12.392 3.6a3.6 3.6 0 0 1 3.6-3.6c4.41 0 8.401 1.807 11.296 4.662a3.6 3.6 0 1 1-5.056 5.126C20.602 8.18 18.398 7.2 15.992 7.2a3.6 3.6 0 0 1-3.6-3.6Z' fill='url(%23b)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 15.992C0 7.157 7.157 0 15.992 0a3.6 3.6 0 0 1 0 7.2A8.789 8.789 0 0 0 7.2 15.992c0 2.406.981 4.61 2.588 6.24a3.6 3.6 0 0 1-5.126 5.056C1.807 24.393 0 20.402 0 15.992Z' fill='url(%23c)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4.661 22.232a3.6 3.6 0 0 1 5.091-.035c1.63 1.606 3.834 2.587 6.24 2.587a3.6 3.6 0 0 1 0 7.2c-4.41 0-8.401-1.807-11.295-4.661a3.6 3.6 0 0 1-.036-5.091Z' fill='url(%23d)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M28.384 12.392a3.6 3.6 0 0 1 3.6 3.6c0 8.835-7.157 15.992-15.992 15.992a3.6 3.6 0 0 1 0-7.2 8.789 8.789 0 0 0 8.792-8.792 3.6 3.6 0 0 1 3.6-3.6Z' fill='url(%23e)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M28.385 12.392a3.6 3.6 0 0 1 3.6 3.6v12.392a3.6 3.6 0 0 1-7.2 0V15.992a3.6 3.6 0 0 1 3.6-3.6Z' fill='url(%23f)'/%3E%3Cg clip-path='url(%23g)'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M22.232 4.662a3.6 3.6 0 0 1 5.091.035c2.855 2.894 4.662 6.885 4.662 11.295a3.6 3.6 0 0 1-7.2 0c0-2.406-.982-4.61-2.588-6.24a3.6 3.6 0 0 1 .035-5.09Z' fill='url(%23h)'/%3E%3C/g%3E%3Cdefs%3E%3ClinearGradient id='a' x1='26.4' y1='9.6' x2='28.8' y2='15' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%237E22CE'/%3E%3Cstop offset='1' stop-color='%238B5CF6'/%3E%3C/linearGradient%3E%3ClinearGradient id='b' x1='26.8' y1='9.4' x2='17.8' y2='3.6' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23EF4444'/%3E%3Cstop offset='1' stop-color='%23DC2626'/%3E%3C/linearGradient%3E%3ClinearGradient id='c' x1='3.6' y1='14' x2='5.4' y2='24.8' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%2322C55E'/%3E%3Cstop offset='1' stop-color='%2315803D'/%3E%3C/linearGradient%3E%3ClinearGradient id='d' x1='4.8' y1='22.2' x2='14.4' y2='29.2' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%2394A3B8'/%3E%3Cstop offset='.958' stop-color='%2364748B'/%3E%3Cstop offset='1' stop-color='%2364748B'/%3E%3C/linearGradient%3E%3ClinearGradient id='e' x1='28.4' y1='22.173' x2='22.188' y2='28.384' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23D97706'/%3E%3Cstop offset='1' stop-color='%23FBBF24'/%3E%3C/linearGradient%3E%3ClinearGradient id='f' x1='29.2' y1='54.4' x2='30.626' y2='54.256' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23FBBF24'/%3E%3Cstop offset='1' stop-color='%23FBBF24'/%3E%3C/linearGradient%3E%3ClinearGradient id='h' x1='26.4' y1='9.6' x2='28.8' y2='15' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%237E22CE'/%3E%3Cstop offset='1' stop-color='%238B5CF6'/%3E%3C/linearGradient%3E%3CclipPath id='g'%3E%3Cpath fill='%23fff' transform='translate(24.8 12)' d='M0 0h7.2v8H0z'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E" />
7
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
- <title>Allure Report</title>
9
- </head>
10
- <body>
11
- <div id="app"></div>
12
- <script>
13
- </script>
14
- <script>
15
- window.allure = window.allure || {};
16
- </script>
17
- <script>
18
- const { origin, pathname } = window.location;
19
- const url = new URL(pathname, origin);
20
- const baseEl = document.createElement("base");
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <!-- Inline favicon for single single-file build -->
6
+ <link
7
+ rel="icon"
8
+ href="data:image/svg+xml,%3Csvg width='32' height='32' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M22.232 4.662a3.6 3.6 0 0 1 5.09.035c2.855 2.894 4.662 6.885 4.662 11.295a3.6 3.6 0 0 1-7.2 0c0-2.406-.981-4.61-2.587-6.24a3.6 3.6 0 0 1 .035-5.09Z' fill='url(%23a)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M12.392 3.6a3.6 3.6 0 0 1 3.6-3.6c4.41 0 8.401 1.807 11.296 4.662a3.6 3.6 0 1 1-5.056 5.126C20.602 8.18 18.398 7.2 15.992 7.2a3.6 3.6 0 0 1-3.6-3.6Z' fill='url(%23b)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 15.992C0 7.157 7.157 0 15.992 0a3.6 3.6 0 0 1 0 7.2A8.789 8.789 0 0 0 7.2 15.992c0 2.406.981 4.61 2.588 6.24a3.6 3.6 0 0 1-5.126 5.056C1.807 24.393 0 20.402 0 15.992Z' fill='url(%23c)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4.661 22.232a3.6 3.6 0 0 1 5.091-.035c1.63 1.606 3.834 2.587 6.24 2.587a3.6 3.6 0 0 1 0 7.2c-4.41 0-8.401-1.807-11.295-4.661a3.6 3.6 0 0 1-.036-5.091Z' fill='url(%23d)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M28.384 12.392a3.6 3.6 0 0 1 3.6 3.6c0 8.835-7.157 15.992-15.992 15.992a3.6 3.6 0 0 1 0-7.2 8.789 8.789 0 0 0 8.792-8.792 3.6 3.6 0 0 1 3.6-3.6Z' fill='url(%23e)'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M28.385 12.392a3.6 3.6 0 0 1 3.6 3.6v12.392a3.6 3.6 0 0 1-7.2 0V15.992a3.6 3.6 0 0 1 3.6-3.6Z' fill='url(%23f)'/%3E%3Cg clip-path='url(%23g)'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M22.232 4.662a3.6 3.6 0 0 1 5.091.035c2.855 2.894 4.662 6.885 4.662 11.295a3.6 3.6 0 0 1-7.2 0c0-2.406-.982-4.61-2.588-6.24a3.6 3.6 0 0 1 .035-5.09Z' fill='url(%23h)'/%3E%3C/g%3E%3Cdefs%3E%3ClinearGradient id='a' x1='26.4' y1='9.6' x2='28.8' y2='15' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%237E22CE'/%3E%3Cstop offset='1' stop-color='%238B5CF6'/%3E%3C/linearGradient%3E%3ClinearGradient id='b' x1='26.8' y1='9.4' x2='17.8' y2='3.6' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23EF4444'/%3E%3Cstop offset='1' stop-color='%23DC2626'/%3E%3C/linearGradient%3E%3ClinearGradient id='c' x1='3.6' y1='14' x2='5.4' y2='24.8' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%2322C55E'/%3E%3Cstop offset='1' stop-color='%2315803D'/%3E%3C/linearGradient%3E%3ClinearGradient id='d' x1='4.8' y1='22.2' x2='14.4' y2='29.2' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%2394A3B8'/%3E%3Cstop offset='.958' stop-color='%2364748B'/%3E%3Cstop offset='1' stop-color='%2364748B'/%3E%3C/linearGradient%3E%3ClinearGradient id='e' x1='28.4' y1='22.173' x2='22.188' y2='28.384' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23D97706'/%3E%3Cstop offset='1' stop-color='%23FBBF24'/%3E%3C/linearGradient%3E%3ClinearGradient id='f' x1='29.2' y1='54.4' x2='30.626' y2='54.256' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23FBBF24'/%3E%3Cstop offset='1' stop-color='%23FBBF24'/%3E%3C/linearGradient%3E%3ClinearGradient id='h' x1='26.4' y1='9.6' x2='28.8' y2='15' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%237E22CE'/%3E%3Cstop offset='1' stop-color='%238B5CF6'/%3E%3C/linearGradient%3E%3CclipPath id='g'%3E%3Cpath fill='%23fff' transform='translate(24.8 12)' d='M0 0h7.2v8H0z'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E"
9
+ />
10
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
11
+ <title>Allure Report</title>
12
+ <script>
13
+ window.allureReportOptions = {
14
+ reportName: "Allure Classic Report (Dev)",
15
+ logo: "/data/logo.jpg",
16
+ theme: "light",
17
+ reportLanguage: "ru",
18
+ createdAt: 1731513697651,
19
+ groupBy: "suite",
20
+ };
21
+ </script>
22
+ </head>
23
+ <body>
24
+ <div id="app"></div>
25
+ <script></script>
26
+ <script>
27
+ window.allure = window.allure || {};
28
+ </script>
29
+ <script>
30
+ const { origin, pathname } = window.location;
31
+ const url = new URL(pathname, origin);
32
+ const baseEl = document.createElement("base");
21
33
 
22
- baseEl.href = url.toString();
34
+ baseEl.href = url.toString();
23
35
 
24
- window.document.head.appendChild(baseEl);
25
- </script>
26
- <script>
27
- window.allureReportOptions = {
28
- reportName: "Allure Classic Report (Dev)",
29
- logo: "/data/logo.jpg",
30
- theme: "light",
31
- reportLanguage: "ru",
32
- createdAt: 1731513697651,
33
- groupBy: "suite",
34
- };
35
- </script>
36
- <script async>
37
- window.allureReportDataReady = true;
38
- </script>
39
- </body>
36
+ window.document.head.appendChild(baseEl);
37
+ </script>
38
+
39
+ <script async>
40
+ window.allureReportDataReady = true;
41
+ </script>
42
+ </body>
40
43
  </html>
package/src/index.tsx CHANGED
@@ -12,7 +12,7 @@ import Packages from "@/components/Packages";
12
12
  import Suites from "@/components/Suites";
13
13
  import { TestResultView } from "@/components/TestResultView";
14
14
  import Timeline from "@/components/Timeline";
15
- import { currentLocale, getLocale, getTheme } from "@/stores";
15
+ import { currentLocale, getLocale } from "@/stores";
16
16
  import { handleHashChange, route } from "@/stores/router";
17
17
 
18
18
  const tabComponents = {
@@ -28,7 +28,6 @@ const tabComponents = {
28
28
 
29
29
  const App = () => {
30
30
  useEffect(() => {
31
- getTheme();
32
31
  getLocale();
33
32
  handleHashChange();
34
33
  }, []);
@@ -1,4 +1,3 @@
1
- export * from "./theme";
2
1
  export type * from "./types";
3
2
  export * from "./stats";
4
3
  export * from "./locale";
@@ -52,7 +52,8 @@ i18next
52
52
  callback: (errorValue: unknown, translations: Record<string, string> | null) => void,
53
53
  ) => {
54
54
  try {
55
- const resources = await import(`@/translations/${language}.json`);
55
+ const loadLocale = language === "en-iso" ? "en" : language;
56
+ const resources = await import(`@/translations/${loadLocale}.json`);
56
57
  callback(null, (resources[namespace] as Record<string, string>) || null);
57
58
  } catch (error) {
58
59
  callback(error, null);
@@ -1,5 +1,6 @@
1
1
  export const AVAILABLE_LOCALES = [
2
2
  "en",
3
+ "en-iso",
3
4
  "ru",
4
5
  "pl",
5
6
  "es",
@@ -31,92 +32,97 @@ export const LANG_LOCALE: Record<
31
32
  iso: string;
32
33
  }
33
34
  > = {
34
- en: {
35
+ "en": {
35
36
  short: "Eng",
36
37
  full: "English",
37
38
  iso: "en-US",
38
39
  },
39
- ru: {
40
+ "en-iso": {
41
+ short: "En ISO",
42
+ full: "English (ISO-8601)",
43
+ iso: "en-CA",
44
+ },
45
+ "ru": {
40
46
  short: "Ру",
41
47
  full: "Русский",
42
48
  iso: "ru-RU",
43
49
  },
44
- pl: {
50
+ "pl": {
45
51
  short: "Pl",
46
52
  full: "Polski",
47
53
  iso: "pl-PL",
48
54
  },
49
- es: {
55
+ "es": {
50
56
  short: "Es",
51
57
  full: "Español",
52
58
  iso: "es-ES",
53
59
  },
54
- pt: {
60
+ "pt": {
55
61
  short: "Pt",
56
62
  full: "Português",
57
63
  iso: "pt-PT",
58
64
  },
59
- de: {
65
+ "de": {
60
66
  short: "De",
61
67
  full: "Deutsch",
62
68
  iso: "de-DE",
63
69
  },
64
- am: {
70
+ "am": {
65
71
  short: "Am",
66
72
  full: "Հայերեն",
67
73
  iso: "hy-AM",
68
74
  },
69
- az: {
75
+ "az": {
70
76
  short: "Az",
71
77
  full: "Azərbaycan",
72
78
  iso: "az-AZ",
73
79
  },
74
- fr: {
80
+ "fr": {
75
81
  short: "Fr",
76
82
  full: "Français",
77
83
  iso: "fr-FR",
78
84
  },
79
- it: {
85
+ "it": {
80
86
  short: "It",
81
87
  full: "Italiano",
82
88
  iso: "it-IT",
83
89
  },
84
- ja: {
90
+ "ja": {
85
91
  short: "Ja",
86
92
  full: "日本語",
87
93
  iso: "ja-JP",
88
94
  },
89
- he: {
95
+ "he": {
90
96
  short: "He",
91
97
  full: "עברית",
92
98
  iso: "he-IL",
93
99
  },
94
- ka: {
100
+ "ka": {
95
101
  short: "Ka",
96
102
  full: "ქართული",
97
103
  iso: "ka-GE",
98
104
  },
99
- kr: {
105
+ "kr": {
100
106
  short: "Kr",
101
107
  full: "한국어",
102
108
  iso: "kr-KR",
103
109
  },
104
- nl: {
110
+ "nl": {
105
111
  short: "Nl",
106
112
  full: "Nederlands",
107
113
  iso: "nl-NL",
108
114
  },
109
- sv: {
115
+ "sv": {
110
116
  short: "Sv",
111
117
  full: "Svenska",
112
118
  iso: "sv-SE",
113
119
  },
114
- tr: {
120
+ "tr": {
115
121
  short: "Tr",
116
122
  full: "Türkçe",
117
123
  iso: "tr-TR",
118
124
  },
119
- zh: {
125
+ "zh": {
120
126
  short: "Zh",
121
127
  full: "中文",
122
128
  iso: "zh-CN",
package/src/utils/time.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { useI18n } from "@/stores/locale";
1
+ import { getLocaleDateTimeOverride } from "@allurereport/web-commons";
2
+ import { currentLocale, currentLocaleIso, useI18n } from "@/stores/locale";
2
3
 
3
4
  const defaultOptions: Intl.DateTimeFormatOptions = {
4
5
  month: "numeric",
@@ -12,6 +13,19 @@ const defaultOptions: Intl.DateTimeFormatOptions = {
12
13
 
13
14
  export const timestampToDate = (timestamp: number, options = defaultOptions) => {
14
15
  const date = new Date(timestamp);
16
+ // eslint-disable-next-line react-hooks/rules-of-hooks
15
17
  const { t } = useI18n("ui");
16
- return new Intl.DateTimeFormat("en-US", options).format(date).replace(",", ` ${t("at")}`);
18
+ const kind = options.second ? "dateTime" : options.hour || options.minute ? "dateTimeNoSeconds" : "date";
19
+ const override = getLocaleDateTimeOverride(currentLocale.value, kind);
20
+ const formatter = new Intl.DateTimeFormat(override?.locale ?? (currentLocaleIso.value as string), {
21
+ ...options,
22
+ ...(override?.options ?? {}),
23
+ });
24
+ const formatted = formatter.format(date);
25
+
26
+ if (override?.includeAtSeparator === false || override?.stripComma) {
27
+ return formatted.replace(",", "");
28
+ }
29
+
30
+ return formatted.replace(",", ` ${t("at")}`);
17
31
  };
@@ -110,6 +110,7 @@ export const createRecursiveTree = (payload: {
110
110
  trees.forEach((rt: ClassicRecursiveTree) => {
111
111
  if (rt.statistic) {
112
112
  const additional: Statistic = rt.statistic;
113
+
113
114
  mergeStatistic(statistic, additional);
114
115
  }
115
116
  });
package/types.d.ts CHANGED
@@ -21,7 +21,7 @@ export type ClassicReportOptions = {
21
21
  logo?: string;
22
22
  theme?: "light" | "dark" | "auto";
23
23
  groupBy?: string[];
24
- reportLanguage?: "en";
24
+ reportLanguage?: string;
25
25
  createdAt: number;
26
26
  reportUuid: string;
27
27
  allureVersion?: string;