@allurereport/web-awesome 3.0.0-beta.10

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 (196) hide show
  1. package/.babelrc.js +46 -0
  2. package/.eslintrc.cjs +18 -0
  3. package/CONTRIBUTING.md +34 -0
  4. package/README.md +27 -0
  5. package/dist/multi/141.app-d01d0c66.js +1 -0
  6. package/dist/multi/222.app-d01d0c66.js +1 -0
  7. package/dist/multi/335.app-d01d0c66.js +1 -0
  8. package/dist/multi/34.app-d01d0c66.js +1 -0
  9. package/dist/multi/349.app-d01d0c66.js +1 -0
  10. package/dist/multi/378.app-d01d0c66.js +1 -0
  11. package/dist/multi/406.app-d01d0c66.js +1 -0
  12. package/dist/multi/476.app-d01d0c66.js +1 -0
  13. package/dist/multi/53.app-d01d0c66.js +1 -0
  14. package/dist/multi/584.app-d01d0c66.js +1 -0
  15. package/dist/multi/690.app-d01d0c66.js +1 -0
  16. package/dist/multi/747.app-d01d0c66.js +1 -0
  17. package/dist/multi/767.app-d01d0c66.js +1 -0
  18. package/dist/multi/816.app-d01d0c66.js +1 -0
  19. package/dist/multi/83.app-d01d0c66.js +1 -0
  20. package/dist/multi/873.app-d01d0c66.js +1 -0
  21. package/dist/multi/920.app-d01d0c66.js +1 -0
  22. package/dist/multi/991.app-d01d0c66.js +1 -0
  23. package/dist/multi/JetBrainsMono_vf-9e9649b6..woff2 +0 -0
  24. package/dist/multi/JetBrainsMono_vf-b9a9c326..woff +0 -0
  25. package/dist/multi/app-d01d0c66.js +2 -0
  26. package/dist/multi/app-d01d0c66.js.LICENSE.txt +16 -0
  27. package/dist/multi/manifest.json +26 -0
  28. package/dist/multi/pt-root-ui_vf-22fe60ca..woff +0 -0
  29. package/dist/multi/pt-root-ui_vf-9d251e8b..woff2 +0 -0
  30. package/dist/multi/styles-d01d0c66.css +39 -0
  31. package/dist/single/app-6596cb08.js +2 -0
  32. package/dist/single/app-6596cb08.js.LICENSE.txt +16 -0
  33. package/dist/single/manifest.json +3 -0
  34. package/package.json +107 -0
  35. package/postcss.config.js +5 -0
  36. package/src/assets/scss/_common.scss +143 -0
  37. package/src/assets/scss/day.scss +51 -0
  38. package/src/assets/scss/fonts.scss +3 -0
  39. package/src/assets/scss/index.scss +7 -0
  40. package/src/assets/scss/night.scss +61 -0
  41. package/src/assets/scss/palette.scss +393 -0
  42. package/src/assets/scss/theme.scss +119 -0
  43. package/src/assets/scss/vars.scss +9 -0
  44. package/src/assets/svg/line-alerts-alert-circle.svg +12 -0
  45. package/src/assets/svg/line-general-eye.svg +7 -0
  46. package/src/assets/svg/line-icon-bomb-2.svg +12 -0
  47. package/src/components/ArrowButton/index.tsx +36 -0
  48. package/src/components/ArrowButton/styles.scss +35 -0
  49. package/src/components/BaseLayout/index.tsx +43 -0
  50. package/src/components/BaseLayout/styles.scss +60 -0
  51. package/src/components/Footer/FooterLogo.tsx +16 -0
  52. package/src/components/Footer/FooterVersion.tsx +37 -0
  53. package/src/components/Footer/index.tsx +13 -0
  54. package/src/components/Footer/styles.scss +14 -0
  55. package/src/components/Header/index.tsx +28 -0
  56. package/src/components/Header/styles.scss +33 -0
  57. package/src/components/LanguagePicker/index.tsx +40 -0
  58. package/src/components/MainReport/index.tsx +21 -0
  59. package/src/components/MainReport/styles.scss +11 -0
  60. package/src/components/Metadata/index.tsx +121 -0
  61. package/src/components/Metadata/styles.scss +146 -0
  62. package/src/components/MetadataButton/index.tsx +32 -0
  63. package/src/components/MetadataButton/styles.scss +53 -0
  64. package/src/components/Modal/index.tsx +22 -0
  65. package/src/components/ReportBody/Filters.tsx +90 -0
  66. package/src/components/ReportBody/HeaderActions.tsx +21 -0
  67. package/src/components/ReportBody/SortBy.tsx +132 -0
  68. package/src/components/ReportBody/context.tsx +106 -0
  69. package/src/components/ReportBody/index.tsx +72 -0
  70. package/src/components/ReportBody/styles.scss +69 -0
  71. package/src/components/ReportHeader/ReportHeaderLabelList.tsx +12 -0
  72. package/src/components/ReportHeader/ReportHeaderLogo.tsx +10 -0
  73. package/src/components/ReportHeader/ReportHeaderPie.tsx +14 -0
  74. package/src/components/ReportHeader/index.tsx +33 -0
  75. package/src/components/ReportHeader/styles.scss +51 -0
  76. package/src/components/ReportLogo/index.tsx +16 -0
  77. package/src/components/ReportLogo/styles.scss +20 -0
  78. package/src/components/ReportLogoFull/index.tsx +20 -0
  79. package/src/components/ReportLogoFull/styles.scss +7 -0
  80. package/src/components/ReportMetadata/MetadataItem.tsx +45 -0
  81. package/src/components/ReportMetadata/MetadataSummary.tsx +81 -0
  82. package/src/components/ReportMetadata/MetadataTestType.tsx +16 -0
  83. package/src/components/ReportMetadata/MetadataWithIcon.tsx +21 -0
  84. package/src/components/ReportMetadata/index.tsx +46 -0
  85. package/src/components/ReportMetadata/styles.scss +99 -0
  86. package/src/components/SideBySide/index.tsx +52 -0
  87. package/src/components/SideBySide/styles.scss +65 -0
  88. package/src/components/SplitLayout/index.tsx +77 -0
  89. package/src/components/SplitLayout/styles.scss +85 -0
  90. package/src/components/Tabs/index.tsx +62 -0
  91. package/src/components/Tabs/styles.scss +56 -0
  92. package/src/components/TestResult/TestResultAttachmentsView/index.tsx +27 -0
  93. package/src/components/TestResult/TestResultAttachmentsView/styles.scss +12 -0
  94. package/src/components/TestResult/TestResultDescription/index.tsx +27 -0
  95. package/src/components/TestResult/TestResultDescription/styles.scss +12 -0
  96. package/src/components/TestResult/TestResultDropdown/index.tsx +26 -0
  97. package/src/components/TestResult/TestResultDropdown/styles.scss +34 -0
  98. package/src/components/TestResult/TestResultEmpty/index.tsx +34 -0
  99. package/src/components/TestResult/TestResultEmpty/styles.scss +25 -0
  100. package/src/components/TestResult/TestResultHeader/TestResultBreadcrumbs.tsx +44 -0
  101. package/src/components/TestResult/TestResultHeader/index.tsx +21 -0
  102. package/src/components/TestResult/TestResultHeader/styles.scss +48 -0
  103. package/src/components/TestResult/TestResultHistory/TestResultHistoryItem.tsx +66 -0
  104. package/src/components/TestResult/TestResultHistory/index.tsx +26 -0
  105. package/src/components/TestResult/TestResultHistory/styles.scss +63 -0
  106. package/src/components/TestResult/TestResultInfo/TestResultInfoStatuses.tsx +30 -0
  107. package/src/components/TestResult/TestResultInfo/index.tsx +81 -0
  108. package/src/components/TestResult/TestResultInfo/styles.scss +68 -0
  109. package/src/components/TestResult/TestResultLinks/index.tsx +56 -0
  110. package/src/components/TestResult/TestResultLinks/styles.scss +30 -0
  111. package/src/components/TestResult/TestResultMetadata/index.tsx +27 -0
  112. package/src/components/TestResult/TestResultMetadata/styles.scss +8 -0
  113. package/src/components/TestResult/TestResultNavigation/index.tsx +80 -0
  114. package/src/components/TestResult/TestResultNavigation/styles.scss +48 -0
  115. package/src/components/TestResult/TestResultOverview.tsx +43 -0
  116. package/src/components/TestResult/TestResultParameters/index.tsx +30 -0
  117. package/src/components/TestResult/TestResultParameters/styles.scss +8 -0
  118. package/src/components/TestResult/TestResultPrevStatuses/index.tsx +49 -0
  119. package/src/components/TestResult/TestResultPrevStatuses/styles.scss +57 -0
  120. package/src/components/TestResult/TestResultRetriesView/TestResultRetriesItem.tsx +51 -0
  121. package/src/components/TestResult/TestResultRetriesView/index.tsx +24 -0
  122. package/src/components/TestResult/TestResultRetriesView/styles.scss +69 -0
  123. package/src/components/TestResult/TestResultSetup/index.tsx +58 -0
  124. package/src/components/TestResult/TestResultSeverity/index.tsx +27 -0
  125. package/src/components/TestResult/TestResultSeverity/styles.scss +29 -0
  126. package/src/components/TestResult/TestResultStatus/index.tsx +25 -0
  127. package/src/components/TestResult/TestResultStatus/styles.scss +36 -0
  128. package/src/components/TestResult/TestResultSteps/index.tsx +58 -0
  129. package/src/components/TestResult/TestResultSteps/styles.scss +225 -0
  130. package/src/components/TestResult/TestResultSteps/testResultAttachment.tsx +76 -0
  131. package/src/components/TestResult/TestResultSteps/testResultAttachmentInfo.tsx +83 -0
  132. package/src/components/TestResult/TestResultSteps/testResultStep.tsx +84 -0
  133. package/src/components/TestResult/TestResultSteps/testResultStepInfo.tsx +30 -0
  134. package/src/components/TestResult/TestResultSteps/wrongAttachment.tsx +8 -0
  135. package/src/components/TestResult/TestResultTabs/index.tsx +68 -0
  136. package/src/components/TestResult/TestResultTabs/styles.scss +76 -0
  137. package/src/components/TestResult/TestResultTeardown/index.tsx +59 -0
  138. package/src/components/TestResult/TestStepsEmpty/index.tsx +23 -0
  139. package/src/components/TestResult/TestStepsEmpty/styles.scss +25 -0
  140. package/src/components/TestResult/TrError/TrDiff.tsx +124 -0
  141. package/src/components/TestResult/TrError/index.tsx +78 -0
  142. package/src/components/TestResult/TrError/styles.scss +133 -0
  143. package/src/components/TestResult/index.tsx +62 -0
  144. package/src/components/TestResult/styles.scss +11 -0
  145. package/src/components/ThemeButton/ThemeButton.tsx +20 -0
  146. package/src/components/ToggleLayout/index.tsx +17 -0
  147. package/src/components/Tree/index.tsx +75 -0
  148. package/src/components/Tree/styles.scss +189 -0
  149. package/src/i18n/constants.ts +124 -0
  150. package/src/i18n/locales/am.json +133 -0
  151. package/src/i18n/locales/az.json +133 -0
  152. package/src/i18n/locales/de.json +133 -0
  153. package/src/i18n/locales/en.json +134 -0
  154. package/src/i18n/locales/es.json +133 -0
  155. package/src/i18n/locales/fr.json +133 -0
  156. package/src/i18n/locales/he.json +133 -0
  157. package/src/i18n/locales/it.json +133 -0
  158. package/src/i18n/locales/ja.json +133 -0
  159. package/src/i18n/locales/ka.json +133 -0
  160. package/src/i18n/locales/kr.json +133 -0
  161. package/src/i18n/locales/nl.json +133 -0
  162. package/src/i18n/locales/pl.json +131 -0
  163. package/src/i18n/locales/pt.json +133 -0
  164. package/src/i18n/locales/ru.json +131 -0
  165. package/src/i18n/locales/sv.json +133 -0
  166. package/src/i18n/locales/tr.json +133 -0
  167. package/src/i18n/locales/zh.json +133 -0
  168. package/src/index.html +40 -0
  169. package/src/index.tsx +96 -0
  170. package/src/stores/chart.ts +32 -0
  171. package/src/stores/envInfo.ts +34 -0
  172. package/src/stores/index.ts +4 -0
  173. package/src/stores/layout.ts +36 -0
  174. package/src/stores/locale.ts +75 -0
  175. package/src/stores/modal.ts +22 -0
  176. package/src/stores/router.ts +48 -0
  177. package/src/stores/stats.ts +36 -0
  178. package/src/stores/testResults.ts +66 -0
  179. package/src/stores/theme.ts +32 -0
  180. package/src/stores/tree.ts +157 -0
  181. package/src/stores/types.ts +5 -0
  182. package/src/styles.scss +45 -0
  183. package/src/types/globals.d.ts +13 -0
  184. package/src/types/window.d.ts +8 -0
  185. package/src/utils/capitalize.ts +6 -0
  186. package/src/utils/copyToClipboard.ts +16 -0
  187. package/src/utils/isMac.ts +8 -0
  188. package/src/utils/loadFromLocalStorage.ts +8 -0
  189. package/src/utils/statuses.ts +55 -0
  190. package/src/utils/time.ts +17 -0
  191. package/src/utils/treeFilters.ts +147 -0
  192. package/test/utils/treeFilters.test.ts +448 -0
  193. package/tsconfig.json +27 -0
  194. package/types.d.ts +99 -0
  195. package/vitest.config.ts +18 -0
  196. package/webpack.config.js +112 -0
@@ -0,0 +1,84 @@
1
+ import type { DefaultTestStepResult } from "@allurereport/core-api";
2
+ import { Code, Text, TreeItemIcon, allureIcons } from "@allurereport/web-components";
3
+ import type { FunctionComponent } from "preact";
4
+ import { useState } from "preact/hooks";
5
+ import { ArrowButton } from "@/components/ArrowButton";
6
+ import { MetadataList } from "@/components/Metadata";
7
+ import { type MetadataItem } from "@/components/ReportMetadata";
8
+ import * as styles from "@/components/TestResult/TestResultSteps/styles.scss";
9
+ import { TestResultAttachment } from "@/components/TestResult/TestResultSteps/testResultAttachment";
10
+ import { TestResultStepInfo } from "@/components/TestResult/TestResultSteps/testResultStepInfo";
11
+ import { collapsedTrees, toggleTree } from "@/stores/tree";
12
+
13
+ export const TestResultStepParameters = (props: { parameters: DefaultTestStepResult["parameters"] }) => {
14
+ const { parameters } = props;
15
+
16
+ return (
17
+ <div className={styles["test-result-parameters"]}>
18
+ <MetadataList size={"s"} envInfo={parameters as unknown as MetadataItem[]} columns={1} />
19
+ </div>
20
+ );
21
+ };
22
+ export const TestResultStepsContent = (props: { item: DefaultTestStepResult }) => {
23
+ const { item } = props;
24
+
25
+ return (
26
+ <div className={styles["test-result-step-content"]}>
27
+ {Boolean(item?.parameters?.length) && <TestResultStepParameters parameters={item.parameters} />}
28
+ {Boolean(item?.steps?.length) && (
29
+ <>
30
+ {item.steps?.map((subItem, key) => {
31
+ if (subItem.type === "step") {
32
+ return <TestResultStep stepIndex={key + 1} key={key} item={subItem} />;
33
+ }
34
+
35
+ if (subItem.type === "attachment") {
36
+ return <TestResultAttachment stepIndex={key + 1} key={key} item={subItem} />;
37
+ }
38
+
39
+ return null;
40
+ })}
41
+ </>
42
+ )}
43
+ </div>
44
+ );
45
+ };
46
+
47
+ export const TestResultStep: FunctionComponent<{
48
+ item: DefaultTestStepResult;
49
+ stepIndex?: number;
50
+ className?: string;
51
+ }> = ({ item, stepIndex }) => {
52
+ const isEarlyOpened = collapsedTrees.value.has(item.stepId);
53
+ const [isOpened, setIsOpen] = useState(isEarlyOpened || false);
54
+ const hasContent = Boolean(item?.steps?.length || item?.parameters?.length);
55
+
56
+ const handleClick = () => {
57
+ setIsOpen(!isOpened);
58
+ toggleTree(item.stepId);
59
+ };
60
+
61
+ return (
62
+ <div className={styles["test-result-step"]}>
63
+ <div className={styles["test-result-step-header"]} onClick={handleClick}>
64
+ {!hasContent ? (
65
+ <div className={styles["test-result-strut"]} />
66
+ ) : (
67
+ <ArrowButton
68
+ isOpened={isOpened}
69
+ icon={allureIcons.arrowsChevronDown}
70
+ iconSize={"xs"}
71
+ className={!hasContent ? styles["test-result-visibility-hidden"] : ""}
72
+ />
73
+ )}
74
+ <TreeItemIcon status={item.status} />
75
+ <Code size={"s"} className={styles["test-result-step-number"]}>
76
+ {stepIndex}
77
+ </Code>
78
+ <Text className={styles["test-result-header-text"]}>{item.name}</Text>
79
+ <TestResultStepInfo item={item} />
80
+ </div>
81
+ {hasContent && isOpened && <TestResultStepsContent item={item} />}
82
+ </div>
83
+ );
84
+ };
@@ -0,0 +1,30 @@
1
+ import { type DefaultTestStepResult, formatDuration } from "@allurereport/core-api";
2
+ import { SvgIcon, Text, allureIcons } from "@allurereport/web-components";
3
+ import * as styles from "@/components/TestResult/TestResultSteps/styles.scss";
4
+
5
+ export const TestResultStepInfo = (props: { item: DefaultTestStepResult }) => {
6
+ const { item } = props;
7
+ const formattedDuration = formatDuration(item?.duration as number);
8
+ const stepLength = item.steps?.length;
9
+ const attachmentLength = item.steps?.filter((step) => step.type === "attachment")?.length;
10
+
11
+ return (
12
+ <div className={styles["item-info"]}>
13
+ {Boolean(stepLength) && (
14
+ <div className={styles["item-info-step"]}>
15
+ <SvgIcon id={allureIcons.lineArrowsCornerDownRight} className={styles["item-info-step-icon"]} />
16
+ <Text size={"s"}>{stepLength}</Text>
17
+ </div>
18
+ )}
19
+ {Boolean(attachmentLength) && (
20
+ <div className={styles["item-info-step"]}>
21
+ <SvgIcon id={allureIcons.lineFilesFileAttachment2} className={styles["item-info-step-icon"]} />
22
+ <Text size={"s"}>{attachmentLength}</Text>
23
+ </div>
24
+ )}
25
+ <Text type="ui" size={"s"} className={styles["item-time"]}>
26
+ {formattedDuration}
27
+ </Text>
28
+ </div>
29
+ );
30
+ };
@@ -0,0 +1,8 @@
1
+ import * as styles from "@/components/TestResult/TestResultSteps/styles.scss";
2
+ import { useI18n } from "@/stores";
3
+
4
+ export const EmptyComponent = () => {
5
+ const { t } = useI18n("errors");
6
+
7
+ return <div className={styles["wrong-attachment-sign"]}>{t("missedAttachment")}</div>;
8
+ };
@@ -0,0 +1,68 @@
1
+ import { Text } from "@allurereport/web-components";
2
+ import { type ComponentChildren, createContext } from "preact";
3
+ import { useContext, useEffect, useState } from "preact/hooks";
4
+ import { activeTab, navigateTo, route } from "@/stores/router";
5
+ import * as styles from "./styles.scss";
6
+
7
+ type TestResultTabsContextT = {
8
+ currentTab: string | undefined;
9
+ setCurrentTab: (id: string) => void;
10
+ };
11
+
12
+ const TestResultTabsContext = createContext<TestResultTabsContextT | null>(null);
13
+
14
+ export const useTestResultTabsContext = () => {
15
+ const context = useContext(TestResultTabsContext);
16
+
17
+ if (!context) {
18
+ throw new Error("TestResultTabs components must be used within a TestResultTabs component");
19
+ }
20
+
21
+ return context;
22
+ };
23
+
24
+ export const TestResultTabsProvider = (props: { initialTab?: string; children: ComponentChildren }) => {
25
+ const { children, initialTab } = props;
26
+ const [currentTab, setCurrentTab] = useState<string | undefined>(initialTab);
27
+
28
+ return (
29
+ <TestResultTabsContext.Provider value={{ currentTab, setCurrentTab }}>{children}</TestResultTabsContext.Provider>
30
+ );
31
+ };
32
+
33
+ export const TestResultTabs = (props: { children: ComponentChildren; initialTab?: string }) => {
34
+ return <TestResultTabsProvider {...props} />;
35
+ };
36
+
37
+ export const TestResultTabsList = (props: { children: ComponentChildren }) => {
38
+ return <div className={styles.tabsList}>{props.children}</div>;
39
+ };
40
+
41
+ export const TestResultTab = (props: { id: string; children: ComponentChildren; disabled?: boolean }) => {
42
+ const { currentTab, setCurrentTab } = useTestResultTabsContext();
43
+ const { id, children } = props;
44
+ const isActiveFromUrl = activeTab.value === id;
45
+ const isCurrentTab = isActiveFromUrl ? isActiveFromUrl : currentTab === id;
46
+
47
+ useEffect(() => {
48
+ if (isActiveFromUrl) {
49
+ setCurrentTab(id);
50
+ }
51
+ }, [activeTab.value]);
52
+
53
+ const handleTabClick = () => {
54
+ if (isCurrentTab) {
55
+ return;
56
+ }
57
+ setCurrentTab(id);
58
+ navigateTo({ ...route.value, params: { ...route.value.params, tabName: id !== "overview" ? id : "" } });
59
+ };
60
+
61
+ return (
62
+ <button className={styles.tab} onClick={handleTabClick} aria-current={isCurrentTab ? true : undefined}>
63
+ <Text type="paragraph" size="m">
64
+ {children}
65
+ </Text>
66
+ </button>
67
+ );
68
+ };
@@ -0,0 +1,76 @@
1
+ .test-result-tabs {
2
+ display: flex;
3
+ }
4
+
5
+ .tabsList {
6
+ display: flex;
7
+ overflow-x: auto;
8
+ flex-grow: 0;
9
+ max-width: max-content;
10
+ gap: 8px;
11
+ }
12
+
13
+ .tab {
14
+ color: var(--on-text-primary);
15
+ cursor: pointer;
16
+ user-select: none;
17
+ flex-shrink: 0;
18
+ transform: scale(1);
19
+ outline: none;
20
+ background-color: var(--bg-base-primary);
21
+ padding: 8px;
22
+ border: none;
23
+ border-radius: 4px;
24
+ transition:
25
+ transform var(--interaction-transition-duration) ease-out,
26
+ outline var(--interaction-transition-duration) ease-out,
27
+ background-color var(--color-change-transition-duration),
28
+ border-color var(--color-change-transition-duration);
29
+ margin: 0 0 8px;
30
+
31
+ &:after {
32
+ content: "";
33
+ position: absolute;
34
+ bottom: -8px;
35
+ width: 100%;
36
+ left: 0;
37
+ border-bottom: 2px solid transparent;
38
+ }
39
+
40
+ &[disabled] {
41
+ opacity: 0.5;
42
+ }
43
+ &[aria-current] {
44
+ background-color: var(--bg-base-primary);
45
+ cursor: default;
46
+
47
+ &:after {
48
+ border-bottom: 2px solid var(--on-support-aldebaran);
49
+ }
50
+
51
+ span {
52
+ font-weight: bold;
53
+ }
54
+ }
55
+
56
+ &:hover:not([aria-current]) {
57
+ background-color: var(--bg-control-flat-medium);
58
+ }
59
+
60
+ &:active:not([aria-current]) {
61
+ background-color: var(--bg-control-flat-heavy);
62
+ transform: scale(0.94);
63
+ }
64
+
65
+ &:focus {
66
+ outline: 1px solid transparent;
67
+ }
68
+
69
+ &:focus-visible {
70
+ outline: 0 solid var(--ad-other-focus);
71
+
72
+ &:not([aria-current]) {
73
+ background-color: var(--bg-control-flat-medium);
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,59 @@
1
+ import { allureIcons } from "@allurereport/web-components";
2
+ import type { FunctionalComponent } from "preact";
3
+ import { useState } from "preact/hooks";
4
+ import type { AwesomeTestResult } from "types";
5
+ import { TestResultDropdown } from "@/components/TestResult/TestResultDropdown";
6
+ import * as styles from "@/components/TestResult/TestResultSteps/styles.scss";
7
+ import { TestResultAttachment } from "@/components/TestResult/TestResultSteps/testResultAttachment";
8
+ import { TestResultStep } from "@/components/TestResult/TestResultSteps/testResultStep";
9
+ import { useI18n } from "@/stores/locale";
10
+ import { collapsedTrees, toggleTree } from "@/stores/tree";
11
+
12
+ const typeMap = {
13
+ before: TestResultStep,
14
+ after: TestResultStep,
15
+ step: TestResultStep,
16
+ attachment: TestResultAttachment,
17
+ };
18
+
19
+ export type TestResultTeardownProps = {
20
+ teardown: AwesomeTestResult["teardown"];
21
+ id: string;
22
+ };
23
+
24
+ export const TestResultTeardown: FunctionalComponent<TestResultTeardownProps> = ({ teardown, id }) => {
25
+ const teardownId = `${id}-teardown`;
26
+ const isEarlyCollapsed = !collapsedTrees.value.has(teardownId);
27
+ const [isOpened, setIsOpen] = useState<boolean>(isEarlyCollapsed);
28
+
29
+ const handleClick = () => {
30
+ setIsOpen(!isOpened);
31
+ toggleTree(teardownId);
32
+ };
33
+
34
+ const { t } = useI18n("execution");
35
+
36
+ return (
37
+ <div className={styles["test-result-steps"]}>
38
+ <TestResultDropdown
39
+ icon={allureIcons.lineHelpersFlag}
40
+ isOpened={isOpened}
41
+ setIsOpen={handleClick}
42
+ counter={teardown?.length}
43
+ title={t("teardown")}
44
+ />
45
+ {isOpened && (
46
+ <div className={styles["test-result-steps-root"]}>
47
+ {teardown?.map((item, key) => {
48
+ const StepComponent = typeMap[item.type];
49
+ return StepComponent ? (
50
+ // FIXME: use proper type in the StepComponent component
51
+ // @ts-ignore
52
+ <StepComponent item={item} stepIndex={key + 1} key={key} className={styles["test-result-step-root"]} />
53
+ ) : null;
54
+ })}
55
+ </div>
56
+ )}
57
+ </div>
58
+ );
59
+ };
@@ -0,0 +1,23 @@
1
+ import { SvgIcon, Text, allureIcons } from "@allurereport/web-components";
2
+ import { useI18n } from "@/stores";
3
+ import * as styles from "./styles.scss";
4
+
5
+ const TestStepsEmpty = () => {
6
+ const { t } = useI18n("empty");
7
+ return (
8
+ <div className={styles["test-steps-empty"]}>
9
+ <div className={styles["test-steps-empty-wrapper"]}>
10
+ <SvgIcon
11
+ size={"m"}
12
+ width={"32px"}
13
+ height={"32px"}
14
+ id={allureIcons.lineDevCodeSquare}
15
+ className={styles["test-steps-empty-icon"]}
16
+ />
17
+ <Text className={styles["test-steps-empty-text"]}>{t("no-test-steps-results")}</Text>
18
+ </div>
19
+ </div>
20
+ );
21
+ };
22
+
23
+ export default TestStepsEmpty;
@@ -0,0 +1,25 @@
1
+ .test-steps-empty {
2
+ display: flex;
3
+ justify-content: center;
4
+ flex-wrap: wrap;
5
+ min-height: 320px;
6
+ align-items: center;
7
+ }
8
+
9
+ .test-steps-empty-wrapper {
10
+ display: flex;
11
+ flex-direction: column;
12
+ align-items: center;
13
+ }
14
+
15
+ .test-steps-empty-icon {
16
+ width: 32px;
17
+ height: 32px;
18
+ margin-bottom: 16px;
19
+ flex: 1 1 auto;
20
+ }
21
+
22
+ .test-steps-empty-text {
23
+ color: var(--on-text-secondary);
24
+ flex: 1 1 auto;
25
+ }
@@ -0,0 +1,124 @@
1
+ import { Button, Code, CodeViewer } from "@allurereport/web-components";
2
+ import type { BaseOptions, Change } from "diff";
3
+ import { diffChars, diffLines, diffWords } from "diff";
4
+ import { useState } from "preact/hooks";
5
+ import { ac } from "vitest/dist/chunks/reporters.D7Jzd9GS";
6
+ import * as styles from "@/components/TestResult/TrError/styles.scss";
7
+ import { useI18n } from "@/stores";
8
+
9
+ const diffFunctions = {
10
+ chars: diffChars,
11
+ words: diffWords,
12
+ lines: diffLines,
13
+ } as const;
14
+
15
+ type DiffType = keyof typeof diffFunctions;
16
+ type ViewMode = "unified" | "side-by-side";
17
+
18
+ export const TrDiff = ({ expected, actual }: { expected: string; actual: string }) => {
19
+ const stringifiedExpected = JSON.stringify(expected);
20
+ const stringifiedActual = JSON.stringify(actual);
21
+ const [diffType, setDiffType] = useState<DiffType>("lines");
22
+ const [viewMode, setViewMode] = useState<ViewMode>("unified");
23
+ const [diff, setDiff] = useState<Change[]>(() => diffLines(stringifiedExpected, stringifiedActual));
24
+ const { t } = useI18n("controls");
25
+
26
+ const DiffCode = () => {
27
+ return (
28
+ <>
29
+ {diff.map((part, index) => (
30
+ <div key={index} className={part.added ? styles["diff-green"] : part.removed ? styles["diff-red"] : ""}>
31
+ {part.value}
32
+ </div>
33
+ ))}
34
+ </>
35
+ );
36
+ };
37
+ const changeTypeDiff = (type: DiffType = "chars") => {
38
+ const diffFn = diffFunctions[type];
39
+ const result = (diffFn as (oldStr: string, newStr: string, options?: BaseOptions) => Change[])(
40
+ stringifiedExpected,
41
+ stringifiedActual,
42
+ {},
43
+ );
44
+
45
+ setDiffType(type);
46
+ setDiff(result);
47
+ };
48
+
49
+ const SideBySideView = () => {
50
+ return (
51
+ <div className={styles["side-by-side"]}>
52
+ <div className={styles.side}>
53
+ <Code type={"ui"} size={"s"} className={styles["side-title"]}>
54
+ {t("expected")}
55
+ </Code>
56
+ <CodeViewer code={expected} className={styles["diff-screen"]} />
57
+ </div>
58
+ <div className={styles.side}>
59
+ <div className={styles.expected}>
60
+ <Code size={"s"} className={styles["side-title"]}>
61
+ {t("actual")}
62
+ </Code>
63
+ </div>
64
+ <CodeViewer className={styles["diff-screen"]}>
65
+ <DiffCode />
66
+ </CodeViewer>
67
+ </div>
68
+ </div>
69
+ );
70
+ };
71
+
72
+ const UnifiedView = () => {
73
+ return (
74
+ <>
75
+ <div className={styles.unified}>
76
+ <CodeViewer className={styles["diff-screen"]}>
77
+ <div className={styles["diff-grey"]}>{expected}</div>
78
+ <DiffCode />
79
+ </CodeViewer>
80
+ </div>
81
+ </>
82
+ );
83
+ };
84
+
85
+ return (
86
+ <div className={styles.diff} data-testId={"test-result-diff"}>
87
+ <div className={styles["diff-controls"]}>
88
+ <div className={styles["diff-buttons"]}>
89
+ <Code size={"s"} className={styles["diff-buttons-title"]}>
90
+ {t("viewMode")}:
91
+ </Code>
92
+ <div className={styles["diff-view"]}>
93
+ {["unified", "side-by-side"].map((mode: ViewMode) => (
94
+ <Button
95
+ key={mode}
96
+ size={"s"}
97
+ style={viewMode === mode ? "primary" : "outline"}
98
+ text={t(mode)}
99
+ onClick={() => setViewMode(mode)}
100
+ />
101
+ ))}
102
+ </div>
103
+ </div>
104
+ <div className={styles["diff-buttons"]}>
105
+ <Code size={"s"} className={styles["diff-buttons-title"]}>
106
+ {t("compareBy")}:
107
+ </Code>
108
+ {["chars", "words", "lines"].map((type: DiffType) => {
109
+ return (
110
+ <Button
111
+ key={type}
112
+ size={"s"}
113
+ style={diffType === type ? "primary" : "outline"}
114
+ text={t(type)}
115
+ onClick={() => changeTypeDiff(type)}
116
+ />
117
+ );
118
+ })}
119
+ </div>
120
+ </div>
121
+ {viewMode === "side-by-side" ? <SideBySideView /> : <UnifiedView />}
122
+ </div>
123
+ );
124
+ };
@@ -0,0 +1,78 @@
1
+ import type { TestError } from "@allurereport/core-api";
2
+ import { Button, Code, IconButton, Text, TooltipWrapper, allureIcons } from "@allurereport/web-components";
3
+ import AnsiToHtml from "ansi-to-html";
4
+ import { type FunctionalComponent } from "preact";
5
+ import { useState } from "preact/hooks";
6
+ import { TrDiff } from "@/components/TestResult/TrError/TrDiff";
7
+ import { useI18n } from "@/stores/locale";
8
+ import { openModal } from "@/stores/modal";
9
+ import { copyToClipboard } from "@/utils/copyToClipboard";
10
+ import * as styles from "./styles.scss";
11
+
12
+ const TrErrorTrace = ({ trace }: { trace: string }) => {
13
+ const ansiTrace = new AnsiToHtml().toHtml(trace);
14
+ return (
15
+ <div data-testid="test-result-error-trace" className={styles["test-result-error-trace"]}>
16
+ <Code size={"s"} type={"ui"}>
17
+ {/* eslint-disable-next-line react/no-danger */}
18
+ <pre dangerouslySetInnerHTML={{ __html: ansiTrace }}>{ansiTrace}</pre>
19
+ </Code>
20
+ </div>
21
+ );
22
+ };
23
+
24
+ export const TrError: FunctionalComponent<TestError> = ({ message, trace, actual, expected }) => {
25
+ const [isOpen, setIsOpen] = useState(false);
26
+ const { t } = useI18n("ui");
27
+ const { t: tooltip } = useI18n("controls");
28
+ const { t: empty } = useI18n("empty");
29
+
30
+ const openDiff = () =>
31
+ openModal({
32
+ title: tooltip("comparison"),
33
+ data: { actual, expected },
34
+ component: <TrDiff actual={actual} expected={expected} />,
35
+ });
36
+
37
+ return (
38
+ <div data-testid="test-result-error" className={styles["test-result-error"]}>
39
+ {message ? (
40
+ <>
41
+ <div data-testid="test-result-error-header" className={styles["test-result-error-header"]}>
42
+ <Text tag={"p"} size={"m"} bold className={styles["test-result-error-text"]}>
43
+ {t("error")}
44
+ </Text>
45
+ <TooltipWrapper tooltipText={tooltip("clipboard")} tooltipTextAfterClick={tooltip("clipboardSuccess")}>
46
+ <IconButton
47
+ style={"ghost"}
48
+ size={"s"}
49
+ icon={allureIcons.lineGeneralCopy3}
50
+ onClick={() => {
51
+ copyToClipboard(message);
52
+ }}
53
+ />
54
+ </TooltipWrapper>
55
+ </div>
56
+ <div className={styles["test-result-error-message"]} onClick={() => setIsOpen(!isOpen)}>
57
+ <Code data-testid="test-result-error-message" size={"s"}>
58
+ <pre>{message}</pre>
59
+ </Code>
60
+ </div>
61
+ </>
62
+ ) : (
63
+ empty("no-message-provided")
64
+ )}
65
+
66
+ {Boolean(actual && expected) && (
67
+ <Button
68
+ style={"flat"}
69
+ data-testId={"test-result-diff-button"}
70
+ size={"s"}
71
+ text={tooltip("showDiff")}
72
+ onClick={openDiff}
73
+ />
74
+ )}
75
+ {isOpen && Boolean(trace.length) && <TrErrorTrace trace={trace} />}
76
+ </div>
77
+ );
78
+ };