@allurereport/web-awesome 3.8.2 → 3.10.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 (227) hide show
  1. package/README.md +112 -0
  2. package/allurerc-dev.mjs +10 -0
  3. package/dist/multi/121.app-b18cce138691927e8759.js +1 -0
  4. package/dist/multi/173.app-b18cce138691927e8759.js +1 -0
  5. package/dist/multi/174.app-b18cce138691927e8759.js +1 -0
  6. package/dist/multi/252.app-b18cce138691927e8759.js +1 -0
  7. package/dist/multi/282.app-b18cce138691927e8759.js +1 -0
  8. package/dist/multi/29.app-b18cce138691927e8759.js +1 -0
  9. package/dist/multi/310.app-b18cce138691927e8759.js +1 -0
  10. package/dist/multi/416.app-b18cce138691927e8759.js +1 -0
  11. package/dist/multi/507.app-b18cce138691927e8759.js +1 -0
  12. package/dist/multi/527.app-b18cce138691927e8759.js +1 -0
  13. package/dist/multi/600.app-b18cce138691927e8759.js +1 -0
  14. package/dist/multi/605.app-b18cce138691927e8759.js +1 -0
  15. package/dist/multi/638.app-b18cce138691927e8759.js +1 -0
  16. package/dist/multi/672.app-b18cce138691927e8759.js +1 -0
  17. package/dist/multi/686.app-b18cce138691927e8759.js +1 -0
  18. package/dist/multi/725.app-b18cce138691927e8759.js +1 -0
  19. package/dist/multi/741.app-b18cce138691927e8759.js +1 -0
  20. package/dist/multi/749.app-b18cce138691927e8759.js +1 -0
  21. package/dist/multi/755.app-b18cce138691927e8759.js +1 -0
  22. package/dist/multi/779.app-b18cce138691927e8759.js +1 -0
  23. package/dist/multi/894.app-b18cce138691927e8759.js +1 -0
  24. package/dist/multi/943.app-b18cce138691927e8759.js +1 -0
  25. package/dist/multi/980.app-b18cce138691927e8759.js +1 -0
  26. package/dist/multi/app-b18cce138691927e8759.js +2 -0
  27. package/dist/multi/manifest.json +26 -23
  28. package/dist/multi/styles-212da6c68fa0beb4c6c5.css +1 -0
  29. package/dist/multi/styles-5c882b14b6f3112e40c4.css +1 -0
  30. package/dist/multi/styles-a4f65de86208f79dd2be.css +58 -0
  31. package/dist/single/app-733f473da7b51f98876d.js +2 -0
  32. package/dist/single/manifest.json +1 -1
  33. package/package.json +19 -14
  34. package/src/assets/scss/_common.scss +2 -2
  35. package/src/assets/scss/index.scss +8 -6
  36. package/src/components/BaseLayout/index.tsx +14 -2
  37. package/src/components/BaseLayout/styles.scss +5 -5
  38. package/src/components/Categories/CategoryHeaderItem/styles.scss +2 -2
  39. package/src/components/Categories/CategoryTreeItem/styles.scss +2 -2
  40. package/src/components/Categories/GroupTreeItem/styles.scss +4 -5
  41. package/src/components/Categories/HistoryTreeItem/styles.scss +2 -2
  42. package/src/components/Categories/LabelTreeItem/styles.scss +2 -2
  43. package/src/components/Categories/MessageTreeItem/index.tsx +1 -1
  44. package/src/components/Categories/MessageTreeItem/styles.scss +18 -18
  45. package/src/components/Categories/sticky.ts +1 -1
  46. package/src/components/Footer/FooterVersion.tsx +5 -10
  47. package/src/components/Footer/index.tsx +7 -1
  48. package/src/components/Footer/styles.scss +8 -2
  49. package/src/components/Header/CiInfo/index.tsx +17 -13
  50. package/src/components/Header/CiInfo/styles.scss +1 -1
  51. package/src/components/Header/styles.scss +2 -2
  52. package/src/components/HeaderControls/index.tsx +1 -3
  53. package/src/components/HotkeysProvider/index.tsx +556 -0
  54. package/src/components/KeyboardShortcuts/index.tsx +73 -0
  55. package/src/components/KeyboardShortcuts/shortcutsConfig.ts +91 -0
  56. package/src/components/KeyboardShortcuts/styles.scss +69 -0
  57. package/src/components/MainReport/index.tsx +89 -72
  58. package/src/components/MainReport/styles.scss +20 -5
  59. package/src/components/Metadata/index.tsx +27 -6
  60. package/src/components/Metadata/styles.scss +21 -9
  61. package/src/components/MetadataButton/index.tsx +2 -0
  62. package/src/components/MetadataButton/styles.scss +1 -1
  63. package/src/components/NavTabs/styles.scss +8 -8
  64. package/src/components/ReportBody/styles.scss +3 -4
  65. package/src/components/ReportCategories/styles.scss +1 -1
  66. package/src/components/ReportFilters/styles.scss +1 -1
  67. package/src/components/ReportGlobalAttachments/styles.scss +1 -1
  68. package/src/components/ReportGlobalErrors/styles.scss +1 -1
  69. package/src/components/ReportHeader/index.tsx +25 -13
  70. package/src/components/ReportHeader/styles.scss +2 -2
  71. package/src/components/ReportMetadata/index.tsx +44 -15
  72. package/src/components/ReportMetadata/styles.scss +6 -6
  73. package/src/components/ReportQualityGateResults/styles.scss +2 -2
  74. package/src/components/ReportSearch/index.tsx +1 -5
  75. package/src/components/ReportTabs/styles.scss +9 -9
  76. package/src/components/SectionSwitcher/index.tsx +87 -10
  77. package/src/components/SideBySide/index.tsx +20 -2
  78. package/src/components/SideBySide/styles.scss +9 -1
  79. package/src/components/SplitLayout/index.tsx +11 -2
  80. package/src/components/SplitLayout/styles.scss +23 -4
  81. package/src/components/TestResult/TestStepsEmpty/styles.scss +1 -1
  82. package/src/components/TestResult/TrDescription/styles.scss +1 -1
  83. package/src/components/TestResult/TrDropdown/index.tsx +2 -2
  84. package/src/components/TestResult/TrDropdown/styles.scss +1 -1
  85. package/src/components/TestResult/TrEmpty/styles.scss +1 -1
  86. package/src/components/TestResult/TrEnvironmentItem/styles.scss +4 -4
  87. package/src/components/TestResult/TrError/index.tsx +32 -7
  88. package/src/components/TestResult/TrError/styles.scss +23 -23
  89. package/src/components/TestResult/TrHeader/styles.scss +2 -2
  90. package/src/components/TestResult/TrHistory/styles.scss +6 -6
  91. package/src/components/TestResult/TrInfo/styles.scss +8 -8
  92. package/src/components/TestResult/TrLinks/index.tsx +2 -2
  93. package/src/components/TestResult/TrLinks/styles.scss +2 -2
  94. package/src/components/TestResult/TrMetadata/index.tsx +1 -1
  95. package/src/components/TestResult/TrMetadata/styles.scss +1 -1
  96. package/src/components/TestResult/TrNavigation/index.tsx +1 -1
  97. package/src/components/TestResult/TrNavigation/styles.scss +2 -2
  98. package/src/components/TestResult/TrOverview.tsx +2 -0
  99. package/src/components/TestResult/TrParameters/index.tsx +1 -1
  100. package/src/components/TestResult/TrParameters/styles.scss +1 -1
  101. package/src/components/TestResult/TrPrevStatuses/styles.scss +8 -8
  102. package/src/components/TestResult/TrPwTraces/styles.scss +1 -1
  103. package/src/components/TestResult/TrRetriesView/TrRetriesItem.tsx +27 -1
  104. package/src/components/TestResult/TrRetriesView/styles.scss +20 -10
  105. package/src/components/TestResult/TrSetup/index.tsx +10 -4
  106. package/src/components/TestResult/TrSeverity/styles.scss +7 -7
  107. package/src/components/TestResult/TrStatus/styles.scss +2 -35
  108. package/src/components/TestResult/TrSteps/TrAttachment.tsx +79 -43
  109. package/src/components/TestResult/TrSteps/TrAttachmentInfo.tsx +44 -17
  110. package/src/components/TestResult/TrSteps/TrBodyItems.tsx +5 -2
  111. package/src/components/TestResult/TrSteps/TrErrorStep.tsx +3 -0
  112. package/src/components/TestResult/TrSteps/TrStep.tsx +15 -6
  113. package/src/components/TestResult/TrSteps/TrStepHeader.tsx +8 -5
  114. package/src/components/TestResult/TrSteps/index.tsx +7 -5
  115. package/src/components/TestResult/TrSteps/stepTreeExpansion.ts +27 -9
  116. package/src/components/TestResult/TrSteps/styles.scss +80 -20
  117. package/src/components/TestResult/TrTeardown/index.tsx +10 -4
  118. package/src/components/TestResult/bodyItems.ts +1 -1
  119. package/src/components/TestResult/index.tsx +8 -2
  120. package/src/components/TestResult/styles.scss +10 -1
  121. package/src/components/TestResult/trOverviewFocus.scss +4 -0
  122. package/src/components/Timeline/styles.scss +6 -6
  123. package/src/components/Tree/index.tsx +79 -5
  124. package/src/components/Tree/styles.scss +55 -35
  125. package/src/hooks/useTestResultOverviewFocusScroll.ts +23 -0
  126. package/src/index.html +30 -33
  127. package/src/index.tsx +12 -6
  128. package/src/locales/ar.json +62 -1
  129. package/src/locales/az.json +62 -1
  130. package/src/locales/de.json +62 -1
  131. package/src/locales/en.json +62 -1
  132. package/src/locales/es.json +62 -1
  133. package/src/locales/fr.json +62 -1
  134. package/src/locales/he.json +62 -1
  135. package/src/locales/hy.json +62 -1
  136. package/src/locales/it.json +62 -1
  137. package/src/locales/ja.json +62 -1
  138. package/src/locales/ka.json +62 -1
  139. package/src/locales/kr.json +62 -1
  140. package/src/locales/nl.json +62 -1
  141. package/src/locales/pl.json +62 -1
  142. package/src/locales/pt.json +62 -1
  143. package/src/locales/ru.json +62 -1
  144. package/src/locales/sv.json +62 -1
  145. package/src/locales/tr.json +62 -1
  146. package/src/locales/uk.json +62 -1
  147. package/src/locales/zh-TW.json +62 -1
  148. package/src/locales/zh.json +62 -1
  149. package/src/stores/keyboard.ts +371 -0
  150. package/src/stores/keyboardActions.ts +769 -0
  151. package/src/stores/locale.ts +5 -2
  152. package/src/stores/reportEnvSections.ts +6 -0
  153. package/src/stores/reportRootTabs.ts +95 -0
  154. package/src/stores/search.ts +147 -0
  155. package/src/stores/testResultOverviewNav.ts +119 -0
  156. package/src/stores/testResultTabs.ts +62 -0
  157. package/src/stores/timeline.ts +1 -1
  158. package/src/stores/tree.ts +42 -4
  159. package/src/stores/treeFilters/store.ts +3 -36
  160. package/src/stores/treeSort.ts +7 -1
  161. package/src/styles/_pane-active.scss +8 -0
  162. package/src/styles.scss +1 -1
  163. package/src/utils/atSeparator.ts +4 -0
  164. package/src/utils/flattenTestResultOverview.ts +182 -0
  165. package/src/utils/time.ts +2 -1
  166. package/src/utils/trOverviewFocus.ts +18 -0
  167. package/src/utils/treeFilters.ts +15 -4
  168. package/test/components/EnvironmentPicker.test.tsx +21 -3
  169. package/test/components/Footer.test.tsx +26 -0
  170. package/test/components/Header/CiInfo.test.tsx +56 -0
  171. package/test/components/Header.test.tsx +8 -0
  172. package/test/components/HeaderControls.test.tsx +28 -0
  173. package/test/components/ReportGlobals.test.tsx +9 -1
  174. package/test/components/ReportHeader.test.tsx +77 -0
  175. package/test/components/ReportMetadata.test.tsx +131 -0
  176. package/test/components/TestResult/PwTraceButton.test.tsx +8 -0
  177. package/test/components/TestResult/TrErrorStep.test.tsx +8 -0
  178. package/test/components/TestResult/TrOverview.test.tsx +30 -10
  179. package/test/components/TestResult/TrRetriesItem.test.tsx +163 -0
  180. package/test/components/TestResult/TrSteps.test.tsx +108 -0
  181. package/test/components/TestResult/bodyItems.test.ts +9 -1
  182. package/test/components/TestResult/openPwTraceInNewTab.test.ts +8 -0
  183. package/test/components/TestResult/stepTreeExpansion.test.ts +10 -2
  184. package/test/components/Timeline.test.tsx +15 -7
  185. package/test/stores/keyboard/keyboardActions.test.ts +615 -0
  186. package/test/stores/search.test.ts +143 -0
  187. package/test/stores/treeFilters/actions.test.ts +8 -0
  188. package/test/stores/treeSort.test.ts +58 -0
  189. package/test/utils/flattenTestResultOverview.test.ts +57 -0
  190. package/test/utils/ownerAddress.test.ts +9 -1
  191. package/test/utils/time.test.ts +52 -0
  192. package/test/utils/treeFilters.test.ts +113 -1
  193. package/types.d.ts +39 -0
  194. package/webpack.config.js +12 -7
  195. package/CONTRIBUTING.md +0 -34
  196. package/dist/multi/173.app-f008fb8342025f2b1ace.js +0 -1
  197. package/dist/multi/174.app-f008fb8342025f2b1ace.js +0 -1
  198. package/dist/multi/252.app-f008fb8342025f2b1ace.js +0 -1
  199. package/dist/multi/282.app-f008fb8342025f2b1ace.js +0 -1
  200. package/dist/multi/29.app-f008fb8342025f2b1ace.js +0 -1
  201. package/dist/multi/310.app-f008fb8342025f2b1ace.js +0 -1
  202. package/dist/multi/416.app-f008fb8342025f2b1ace.js +0 -1
  203. package/dist/multi/507.app-f008fb8342025f2b1ace.js +0 -1
  204. package/dist/multi/527.app-f008fb8342025f2b1ace.js +0 -1
  205. package/dist/multi/600.app-f008fb8342025f2b1ace.js +0 -1
  206. package/dist/multi/605.app-f008fb8342025f2b1ace.js +0 -1
  207. package/dist/multi/638.app-f008fb8342025f2b1ace.js +0 -1
  208. package/dist/multi/672.app-f008fb8342025f2b1ace.js +0 -1
  209. package/dist/multi/686.app-f008fb8342025f2b1ace.js +0 -1
  210. package/dist/multi/725.app-f008fb8342025f2b1ace.js +0 -1
  211. package/dist/multi/741.app-f008fb8342025f2b1ace.js +0 -1
  212. package/dist/multi/749.app-f008fb8342025f2b1ace.js +0 -1
  213. package/dist/multi/755.app-f008fb8342025f2b1ace.js +0 -1
  214. package/dist/multi/894.app-f008fb8342025f2b1ace.js +0 -1
  215. package/dist/multi/943.app-f008fb8342025f2b1ace.js +0 -1
  216. package/dist/multi/980.app-f008fb8342025f2b1ace.js +0 -1
  217. package/dist/multi/app-f008fb8342025f2b1ace.js +0 -2
  218. package/dist/multi/styles-9f7a23a0c8b79fa76981.css +0 -58
  219. package/dist/single/app-07332238da9897064301.js +0 -2
  220. package/src/assets/scss/day.scss +0 -53
  221. package/src/assets/scss/fonts.scss +0 -3
  222. package/src/assets/scss/night.scss +0 -63
  223. package/src/assets/scss/palette.scss +0 -393
  224. package/src/assets/scss/theme.scss +0 -330
  225. package/src/assets/scss/vars.scss +0 -11
  226. /package/dist/multi/{app-f008fb8342025f2b1ace.js.LICENSE.txt → app-b18cce138691927e8759.js.LICENSE.txt} +0 -0
  227. /package/dist/single/{app-07332238da9897064301.js.LICENSE.txt → app-733f473da7b51f98876d.js.LICENSE.txt} +0 -0
@@ -4,7 +4,7 @@
4
4
  padding-right: 24px;
5
5
 
6
6
  &:not(:first-child) {
7
- border-top: 1px solid var(--on-border-muted);
7
+ border-top: 1px solid var(--color-border-subtle);
8
8
  }
9
9
  }
10
10
 
@@ -14,14 +14,14 @@
14
14
 
15
15
  .test-result-step {
16
16
  &:not(:first-child) {
17
- border-top: 1px solid var(--on-border-muted);
17
+ border-top: 1px solid var(--color-border-subtle);
18
18
  }
19
19
  }
20
20
 
21
21
  .test-result-step-content {
22
22
  padding-left: 24px;
23
23
  margin-bottom: 12px;
24
- border-top: 1px solid var(--on-border-muted);
24
+ border-top: 1px solid var(--color-border-subtle);
25
25
  min-width: 0;
26
26
  }
27
27
 
@@ -30,7 +30,20 @@
30
30
  }
31
31
 
32
32
  .test-result-attachment-content {
33
+ border-top: 1px solid var(--color-border-subtle);
34
+ }
35
+
36
+ button.test-result-attachment-content {
37
+ appearance: none;
38
+ background: transparent;
39
+ border: 0;
33
40
  border-top: 1px solid var(--on-border-muted);
41
+ color: inherit;
42
+ cursor: pointer;
43
+ display: block;
44
+ padding: 0;
45
+ text-align: inherit;
46
+ width: 100%;
34
47
  }
35
48
 
36
49
  .test-result-attachment-content-wrapper {
@@ -51,7 +64,7 @@
51
64
  min-height: 32px;
52
65
 
53
66
  &:hover {
54
- background: var(--bg-control-flat-medium);
67
+ background: var(--color-row-bg-hover);
55
68
  }
56
69
  }
57
70
 
@@ -81,7 +94,7 @@
81
94
  }
82
95
 
83
96
  .test-result-step-number {
84
- color: var(--on-text-hint);
97
+ color: var(--color-text-muted);
85
98
  min-width: 16px;
86
99
  text-align: center;
87
100
  box-sizing: content-box;
@@ -90,7 +103,7 @@
90
103
  .item-time {
91
104
  flex: none;
92
105
  margin-left: auto;
93
- color: var(--on-text-hint);
106
+ color: var(--color-text-muted);
94
107
  line-height: 20px;
95
108
  min-width: 56px;
96
109
  text-align: right;
@@ -99,7 +112,7 @@
99
112
  .item-info {
100
113
  display: flex;
101
114
  gap: 8px;
102
- color: var(--on-text-secondary);
115
+ color: var(--color-text-secondary);
103
116
  align-items: center;
104
117
  flex: 0 0 auto;
105
118
  }
@@ -108,7 +121,7 @@
108
121
  display: flex;
109
122
  align-items: center;
110
123
  gap: 4px;
111
- color: var(--on-icon-secondary);
124
+ color: var(--color-icon-secondary);
112
125
  min-width: 56px;
113
126
  justify-content: flex-end;
114
127
  }
@@ -120,7 +133,7 @@
120
133
  }
121
134
 
122
135
  .item-info-step-icon {
123
- color: var(--on-icon-secondary);
136
+ color: var(--color-icon-secondary);
124
137
  }
125
138
 
126
139
  .test-result-step-chevron {
@@ -146,7 +159,26 @@
146
159
  }
147
160
 
148
161
  &:hover {
149
- background: var(--bg-control-flat-medium);
162
+ background: var(--color-row-bg-hover);
163
+ }
164
+ }
165
+
166
+ .test-result-attachment-toggle {
167
+ appearance: none;
168
+ border: 0;
169
+ background: transparent;
170
+ color: inherit;
171
+ display: flex;
172
+ align-items: center;
173
+ gap: 4px;
174
+ flex: 1 1 auto;
175
+ min-width: 0;
176
+ padding: 0;
177
+ font: inherit;
178
+ text-align: left;
179
+
180
+ &:not(:disabled) {
181
+ cursor: pointer;
150
182
  }
151
183
  }
152
184
 
@@ -160,7 +192,7 @@
160
192
  }
161
193
 
162
194
  .test-result-attachment-icon {
163
- color: var(--on-icon-secondary);
195
+ color: var(--color-icon-secondary);
164
196
  padding: 2px 4px;
165
197
  height: max-content;
166
198
  }
@@ -210,11 +242,39 @@
210
242
  }
211
243
 
212
244
  .item-button {
213
- color: var(--bg-control-flat);
245
+ flex: none;
246
+ color: var(--color-control-bg-ghost);
214
247
  }
215
248
 
216
- .item-button-syntax-off {
217
- opacity: 0.5;
249
+ .item-buttons {
250
+ :global(button),
251
+ :global(a) {
252
+ --allure-btn-icon-color: var(--color-icon-primary);
253
+ --allure-btn-trailing-icon-color: var(--color-icon-primary);
254
+ color: var(--color-icon-primary);
255
+ }
256
+
257
+ :global(button) :global(svg),
258
+ :global(a) :global(svg) {
259
+ opacity: 1;
260
+ }
261
+
262
+ :global(button) :global(path),
263
+ :global(a) :global(path) {
264
+ stroke-opacity: 1;
265
+ fill-opacity: 1;
266
+ }
267
+
268
+ .item-button-active {
269
+ --allure-btn-bg-color: var(--color-control-bg-ghost-hover);
270
+ background-color: var(--color-control-bg-ghost-hover);
271
+ border-radius: 4px;
272
+ }
273
+
274
+ .item-button-syntax-off {
275
+ --allure-btn-bg-color: var(--color-control-bg-ghost);
276
+ opacity: 0.5;
277
+ }
218
278
  }
219
279
 
220
280
  .wrong-attachment-sign {
@@ -224,7 +284,7 @@
224
284
  }
225
285
 
226
286
  .test-result-attachment-missed {
227
- color: var(--on-text-secondary);
287
+ color: var(--color-text-secondary);
228
288
  line-height: 20px;
229
289
  margin-right: auto;
230
290
  padding-top: 2px;
@@ -255,23 +315,23 @@
255
315
 
256
316
  .item-status-icon {
257
317
  &.status-passed {
258
- color: var(--bg-support-castor);
318
+ color: var(--color-status-passed-chart);
259
319
  }
260
320
 
261
321
  &.status-failed {
262
- color: var(--bg-support-capella);
322
+ color: var(--color-status-failed-chart);
263
323
  }
264
324
 
265
325
  &.status-broken {
266
- color: var(--bg-support-atlas);
326
+ color: var(--color-status-broken-chart);
267
327
  }
268
328
 
269
329
  &.status-skipped {
270
- color: var(--bg-support-rau);
330
+ color: var(--color-status-skipped-chart);
271
331
  }
272
332
 
273
333
  &.status-unknown {
274
- color: var(--bg-support-skat);
334
+ color: var(--color-status-unknown-chart);
275
335
  }
276
336
  }
277
337
 
@@ -8,6 +8,7 @@ import { TrDropdown } from "@/components/TestResult/TrDropdown";
8
8
  import { TrStep } from "@/components/TestResult/TrSteps/TrStep";
9
9
  import { useI18n } from "@/stores/locale";
10
10
  import { collapsedTrees, toggleTree } from "@/stores/tree";
11
+ import { trOverviewFocusAttrs, trOverviewHeaderFocusClass } from "@/utils/trOverviewFocus";
11
12
 
12
13
  import * as styles from "@/components/TestResult/TrSteps/styles.scss";
13
14
 
@@ -17,13 +18,16 @@ export type TrTeardownProps = {
17
18
  };
18
19
 
19
20
  export const TrTeardown: FunctionalComponent<TrTeardownProps> = ({ teardown, id }) => {
20
- const teardownId = `${id}-teardown`;
21
- const isEarlyCollapsed = !collapsedTrees.value.has(teardownId);
21
+ const teardownId = id ? `${id}-teardown` : null;
22
+ const isEarlyCollapsed = teardownId ? !collapsedTrees.value.has(teardownId) : true;
22
23
  const [isOpened, setIsOpen] = useState<boolean>(isEarlyCollapsed);
23
24
 
24
25
  const handleClick = () => {
25
26
  setIsOpen(!isOpened);
26
- toggleTree(teardownId);
27
+
28
+ if (teardownId) {
29
+ toggleTree(teardownId);
30
+ }
27
31
  };
28
32
 
29
33
  const { t } = useI18n("execution");
@@ -31,6 +35,8 @@ export const TrTeardown: FunctionalComponent<TrTeardownProps> = ({ teardown, id
31
35
  return (
32
36
  <div className={styles["test-result-steps"]}>
33
37
  <TrDropdown
38
+ className={trOverviewHeaderFocusClass(teardownId)}
39
+ {...trOverviewFocusAttrs(teardownId)}
34
40
  icon={allureIcons.lineHelpersFlag}
35
41
  isOpened={isOpened}
36
42
  setIsOpen={handleClick}
@@ -41,7 +47,7 @@ export const TrTeardown: FunctionalComponent<TrTeardownProps> = ({ teardown, id
41
47
  <div className={styles["test-result-steps-root"]}>
42
48
  {teardown?.map((fixture, key) => (
43
49
  <div className={styles["test-result-step-root"]} key={fixture.id}>
44
- <TrStep item={fixtureResultToTrStepItem(fixture)} stepIndex={key + 1} />
50
+ <TrStep item={fixtureResultToTrStepItem(fixture)} stepIndex={key + 1} isTopLevel={true} />
45
51
  </div>
46
52
  ))}
47
53
  </div>
@@ -55,7 +55,7 @@ export const hasErrorDiff = (error?: TestErrorLike) =>
55
55
  export const hasTestLevelErrorContent = (error?: TestErrorLike) =>
56
56
  Boolean(normalizeErrorText(error?.trace).length) || hasErrorDiff(error);
57
57
 
58
- const isDisplayableTestError = (error?: TestErrorLike) => {
58
+ export const isDisplayableTestError = (error?: TestErrorLike) => {
59
59
  return (
60
60
  Boolean(normalizeErrorText(error?.message).length) ||
61
61
  Boolean(normalizeErrorText(error?.trace).length) ||
@@ -13,6 +13,7 @@ import { TrOverview } from "@/components/TestResult/TrOverview";
13
13
  import { TrRetriesView } from "@/components/TestResult/TrRetriesView";
14
14
  import { TrTabs } from "@/components/TestResult/TrTabs";
15
15
  import { fetchTestEnvGroup } from "@/stores/env";
16
+ import { activePane, focusTestResultPane } from "@/stores/keyboard";
16
17
  import { isSplitMode } from "@/stores/layout";
17
18
  import { trCurrentTab } from "@/stores/testResult";
18
19
 
@@ -57,7 +58,8 @@ const TrContent: FunctionalComponent<TrContentProps> = ({ testResult }) => {
57
58
  };
58
59
 
59
60
  const TestResult: FunctionComponent<TrProps> = ({ testResult }) => {
60
- const splitModeClass = isSplitMode.value ? styles["scroll-inside"] : "";
61
+ const split = isSplitMode.value;
62
+ const trPaneActive = split && activePane.value === "testResult";
61
63
 
62
64
  useEffect(() => {
63
65
  const testCaseId = testResult?.testCase?.id;
@@ -69,7 +71,11 @@ const TestResult: FunctionComponent<TrProps> = ({ testResult }) => {
69
71
 
70
72
  return (
71
73
  <>
72
- <div className={clsx(styles.content, splitModeClass)}>
74
+ <div
75
+ className={clsx(styles.content, split && styles["scroll-inside"], trPaneActive && styles["pane-active"])}
76
+ data-tr-scroll-container
77
+ onMouseDown={() => focusTestResultPane()}
78
+ >
73
79
  {testResult ? <TrContent testResult={testResult} /> : <TrEmpty />}
74
80
  </div>
75
81
  </>
@@ -1,6 +1,9 @@
1
+ @use "../../styles/pane-active" as paneActive;
2
+
1
3
  .content {
4
+ position: relative;
2
5
  box-shadow: var(--shadow-small);
3
- background: var(--bg-base-primary);
6
+ background: var(--color-bg-primary);
4
7
  border-radius: 12px;
5
8
  width: 100%;
6
9
  }
@@ -10,4 +13,10 @@
10
13
  height: 100%;
11
14
  border-radius: 0;
12
15
  scrollbar-width: thin;
16
+ @include paneActive.split-pane-indicator;
17
+
18
+ &.pane-active {
19
+ @include paneActive.split-pane-indicator-active;
20
+ }
13
21
  }
22
+
@@ -0,0 +1,4 @@
1
+ // Keyboard focus: no visual indicator — step focus is internal only.
2
+ .tr-overview-focused {
3
+ outline: none;
4
+ }
@@ -5,11 +5,11 @@
5
5
  overflow-y: auto;
6
6
 
7
7
  --timeline-font-family: var(--font-family);
8
- --timeline-grid: var(--on-border-control);
9
- --timeline-border-primary: var(--on-border-primary);
10
- --timeline-axis-text: var(--on-text-secondary);
11
- --timeline-bg: var(--bg-base-primary);
12
- --timeline-selection-bg: var(--bg-control-flat-medium);
8
+ --timeline-grid: var(--color-border-control);
9
+ --timeline-border-primary: var(--color-border-default);
10
+ --timeline-axis-text: var(--color-text-secondary);
11
+ --timeline-bg: var(--color-bg-primary);
12
+ --timeline-selection-bg: var(--color-control-bg-ghost-hover);
13
13
  }
14
14
 
15
15
  .overview-grid {
@@ -41,5 +41,5 @@
41
41
  align-items: center;
42
42
  width: 100%;
43
43
  min-height: 320px;
44
- color: var(--on-text-hint);
44
+ color: var(--color-text-muted);
45
45
  }
@@ -1,20 +1,34 @@
1
+ import { scrollFocusIntoView, scrollTreePaneToTop } from "@allurereport/web-commons";
1
2
  import { Button, Loadable, PageLoader, Text, Tree, TreeStatusBar } from "@allurereport/web-components";
2
- import { useMemo } from "preact/hooks";
3
+ import clsx from "clsx";
4
+ import { useLayoutEffect, useMemo } from "preact/hooks";
3
5
 
4
6
  import { MetadataButton } from "@/components/MetadataButton";
5
7
  import { reportStatsStore, statsByEnvStore } from "@/stores";
6
8
  import { collapsedEnvironments, currentEnvironment, environmentNameById, environmentsStore } from "@/stores/env";
9
+ import { flatTree, getFlatTreeNode, setTreeFocusId, treeFocusId, treeScrollPaneToTopPending } from "@/stores/keyboard";
7
10
  import { useI18n } from "@/stores/locale";
8
11
  import { navigateToTestResult } from "@/stores/router";
9
12
  import { currentTrId } from "@/stores/testResult";
10
- import { collapsedTrees, filteredTree, noTests, noTestsFound, toggleTree, treeStore } from "@/stores/tree";
13
+ import {
14
+ collapsedTrees,
15
+ filteredTree,
16
+ isTreeOpened,
17
+ noTests,
18
+ noTestsFound,
19
+ toggleTree,
20
+ treeStore,
21
+ } from "@/stores/tree";
11
22
  import { clearTreeFilters, treeStatus } from "@/stores/treeFilters/store";
12
23
  import { createTreeLocalizer } from "@/utils/tree";
13
24
 
14
25
  import * as styles from "./styles.scss";
15
26
 
16
- const treeNavigateTo = (id: string) => {
17
- navigateToTestResult({ testResultId: id });
27
+ const treeNavigateTo = (testResultId: string) => {
28
+ const flatNode = flatTree.value.find((node) => node.testResultId === testResultId || node.id === testResultId);
29
+
30
+ setTreeFocusId(flatNode?.id ?? testResultId);
31
+ navigateToTestResult({ testResultId });
18
32
  };
19
33
 
20
34
  export const TreeList = () => {
@@ -22,9 +36,56 @@ export const TreeList = () => {
22
36
  const { t: tEnvironments } = useI18n("environments");
23
37
  const { t: tooltip } = useI18n("transitions");
24
38
  const trId = currentTrId.value;
39
+ const focusedId = treeFocusId.value;
25
40
 
26
41
  const currentTreeStatus = treeStatus.value;
27
42
 
43
+ useLayoutEffect(() => {
44
+ if (!focusedId) {
45
+ return;
46
+ }
47
+
48
+ const node = document.querySelector(`[data-tree-node-id="${focusedId}"]`);
49
+
50
+ if (!node) {
51
+ return;
52
+ }
53
+
54
+ if (treeScrollPaneToTopPending.value) {
55
+ treeScrollPaneToTopPending.value = false;
56
+ scrollTreePaneToTop(node);
57
+ return;
58
+ }
59
+
60
+ const flatNode = getFlatTreeNode(focusedId);
61
+ const kind = flatNode?.kind;
62
+
63
+ // For group/env nodes always pin to top (even when already visible in viewport)
64
+ if (kind === "group" || kind === "env") {
65
+ (node as HTMLElement).scrollIntoView({ block: "start", inline: "nearest" });
66
+ } else {
67
+ scrollFocusIntoView(node, { kind });
68
+ }
69
+ }, [focusedId]);
70
+
71
+ useLayoutEffect(() => {
72
+ if (!trId || focusedId) {
73
+ return;
74
+ }
75
+
76
+ // Use flatTree to find the scoped node id — avoids duplicate id issues in multi-env trees
77
+ const flatNode = flatTree.value.find((n) => n.testResultId === trId || n.id === trId);
78
+ const node = flatNode
79
+ ? (document.querySelector(`[data-tree-node-id="${flatNode.id}"]`) as HTMLElement | null)
80
+ : document.getElementById(trId);
81
+
82
+ if (!node) {
83
+ return;
84
+ }
85
+
86
+ scrollFocusIntoView(node, { kind: "leaf" });
87
+ }, [trId]);
88
+
28
89
  const localizers = useMemo(
29
90
  () => ({
30
91
  tooltip: (key: string, options: Record<string, string>) => tooltip(`description.${key}`, options),
@@ -84,10 +145,12 @@ export const TreeList = () => {
84
145
  statistic={soleStatistic}
85
146
  collapsedTrees={collapsedTrees.value}
86
147
  toggleTree={toggleTree}
148
+ isGroupOpened={isTreeOpened}
87
149
  navigateTo={treeNavigateTo}
88
150
  tree={treeLocalizer(filteredTree.value[soleId])}
89
151
  statusFilter={currentTreeStatus}
90
152
  routeId={trId}
153
+ focusedId={focusedId}
91
154
  root
92
155
  />
93
156
  </div>
@@ -104,10 +167,12 @@ export const TreeList = () => {
104
167
  statistic={statsByEnvStore.value.data[currentEnvironment.value]}
105
168
  collapsedTrees={collapsedTrees.value}
106
169
  toggleTree={toggleTree}
170
+ isGroupOpened={isTreeOpened}
107
171
  navigateTo={treeNavigateTo}
108
172
  tree={treeLocalizer(currentTree)}
109
173
  statusFilter={currentTreeStatus}
110
174
  routeId={trId}
175
+ focusedId={focusedId}
111
176
  root
112
177
  />
113
178
  </div>
@@ -132,9 +197,15 @@ export const TreeList = () => {
132
197
  };
133
198
  const stats = statsByEnvStore.value.data[key];
134
199
 
200
+ const envFocusId = `env:${key}`;
201
+
135
202
  return (
136
203
  <div key={key} className={styles["tree-section"]} data-testid={"tree-section"}>
137
- <div className={styles["tree-env-button"]}>
204
+ <div
205
+ className={clsx(styles["tree-env-button"], focusedId === envFocusId && styles["tree-env-focused"])}
206
+ data-tree-node-id={envFocusId}
207
+ id={envFocusId}
208
+ >
138
209
  <MetadataButton
139
210
  isOpened={isOpened}
140
211
  setIsOpen={toggleEnv}
@@ -157,10 +228,13 @@ export const TreeList = () => {
157
228
  reportStatistic={reportStatsStore.value.data}
158
229
  collapsedTrees={collapsedTrees.value}
159
230
  toggleTree={toggleTree}
231
+ isGroupOpened={isTreeOpened}
160
232
  statusFilter={currentTreeStatus}
161
233
  navigateTo={treeNavigateTo}
162
234
  tree={treeLocalizer(value)}
163
235
  routeId={trId}
236
+ focusedId={focusedId}
237
+ focusIdPrefix={`${key}:`}
164
238
  root
165
239
  />
166
240
  </div>