@flanksource/clicky-ui 0.3.46 → 0.3.47

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 (379) hide show
  1. package/NOTICE.md +11 -0
  2. package/dist/ai.cjs +13 -8
  3. package/dist/ai.cjs.map +1 -1
  4. package/dist/ai.js +7 -2
  5. package/dist/ai.js.map +1 -1
  6. package/dist/components/ErrorWrapper.cjs +2 -3
  7. package/dist/components/ErrorWrapper.cjs.map +1 -1
  8. package/dist/components/ErrorWrapper.d.ts.map +1 -1
  9. package/dist/components/ErrorWrapper.js +3 -4
  10. package/dist/components/ErrorWrapper.js.map +1 -1
  11. package/dist/data/Clicky.cjs +3 -0
  12. package/dist/data/Clicky.cjs.map +1 -1
  13. package/dist/data/Clicky.js +3 -0
  14. package/dist/data/Clicky.js.map +1 -1
  15. package/dist/data/FilterPill.cjs +15 -2
  16. package/dist/data/FilterPill.cjs.map +1 -1
  17. package/dist/data/FilterPill.d.ts +1 -1
  18. package/dist/data/FilterPill.d.ts.map +1 -1
  19. package/dist/data/FilterPill.js +15 -2
  20. package/dist/data/FilterPill.js.map +1 -1
  21. package/dist/data/LogViewer.cjs +27 -8
  22. package/dist/data/LogViewer.cjs.map +1 -1
  23. package/dist/data/LogViewer.d.ts +11 -3
  24. package/dist/data/LogViewer.d.ts.map +1 -1
  25. package/dist/data/LogViewer.js +27 -8
  26. package/dist/data/LogViewer.js.map +1 -1
  27. package/dist/data/Properties.cjs +2 -15
  28. package/dist/data/Properties.cjs.map +1 -1
  29. package/dist/data/Properties.d.ts +4 -0
  30. package/dist/data/Properties.d.ts.map +1 -1
  31. package/dist/data/Properties.js +2 -15
  32. package/dist/data/Properties.js.map +1 -1
  33. package/dist/data/PropertyValue.cjs +37 -0
  34. package/dist/data/PropertyValue.cjs.map +1 -0
  35. package/dist/data/PropertyValue.d.ts +6 -0
  36. package/dist/data/PropertyValue.d.ts.map +1 -0
  37. package/dist/data/PropertyValue.js +37 -0
  38. package/dist/data/PropertyValue.js.map +1 -0
  39. package/dist/data/Tree.cjs +4 -3
  40. package/dist/data/Tree.cjs.map +1 -1
  41. package/dist/data/Tree.d.ts +3 -1
  42. package/dist/data/Tree.d.ts.map +1 -1
  43. package/dist/data/Tree.js +4 -3
  44. package/dist/data/Tree.js.map +1 -1
  45. package/dist/data/ai/ChatFab.cjs +1 -1
  46. package/dist/data/ai/ChatFab.cjs.map +1 -1
  47. package/dist/data/ai/ChatFab.js +1 -1
  48. package/dist/data/ai/ChatFab.js.map +1 -1
  49. package/dist/data/ai/ChatWindow.cjs +106 -171
  50. package/dist/data/ai/ChatWindow.cjs.map +1 -1
  51. package/dist/data/ai/ChatWindow.d.ts +6 -2
  52. package/dist/data/ai/ChatWindow.d.ts.map +1 -1
  53. package/dist/data/ai/ChatWindow.header.cjs +104 -0
  54. package/dist/data/ai/ChatWindow.header.cjs.map +1 -0
  55. package/dist/data/ai/ChatWindow.header.d.ts +29 -0
  56. package/dist/data/ai/ChatWindow.header.d.ts.map +1 -0
  57. package/dist/data/ai/ChatWindow.header.js +104 -0
  58. package/dist/data/ai/ChatWindow.header.js.map +1 -0
  59. package/dist/data/ai/ChatWindow.js +107 -172
  60. package/dist/data/ai/ChatWindow.js.map +1 -1
  61. package/dist/data/ai/ChatWindow.placement.cjs +95 -0
  62. package/dist/data/ai/ChatWindow.placement.cjs.map +1 -0
  63. package/dist/data/ai/ChatWindow.placement.d.ts +32 -0
  64. package/dist/data/ai/ChatWindow.placement.d.ts.map +1 -0
  65. package/dist/data/ai/ChatWindow.placement.js +95 -0
  66. package/dist/data/ai/ChatWindow.placement.js.map +1 -0
  67. package/dist/data/ai/SessionChatComposer.cjs +3 -1
  68. package/dist/data/ai/SessionChatComposer.cjs.map +1 -1
  69. package/dist/data/ai/SessionChatComposer.d.ts +4 -1
  70. package/dist/data/ai/SessionChatComposer.d.ts.map +1 -1
  71. package/dist/data/ai/SessionChatComposer.js +3 -1
  72. package/dist/data/ai/SessionChatComposer.js.map +1 -1
  73. package/dist/data/ai/SessionInspector.cjs +68 -72
  74. package/dist/data/ai/SessionInspector.cjs.map +1 -1
  75. package/dist/data/ai/SessionInspector.composer-slot.cjs +8 -0
  76. package/dist/data/ai/SessionInspector.composer-slot.cjs.map +1 -0
  77. package/dist/data/ai/SessionInspector.composer-slot.d.ts +9 -0
  78. package/dist/data/ai/SessionInspector.composer-slot.d.ts.map +1 -0
  79. package/dist/data/ai/SessionInspector.composer-slot.js +8 -0
  80. package/dist/data/ai/SessionInspector.composer-slot.js.map +1 -0
  81. package/dist/data/ai/SessionInspector.d.ts +6 -1
  82. package/dist/data/ai/SessionInspector.d.ts.map +1 -1
  83. package/dist/data/ai/SessionInspector.js +69 -73
  84. package/dist/data/ai/SessionInspector.js.map +1 -1
  85. package/dist/data/ai/SessionInspector.legacy.cjs +41 -42
  86. package/dist/data/ai/SessionInspector.legacy.cjs.map +1 -1
  87. package/dist/data/ai/SessionInspector.legacy.d.ts.map +1 -1
  88. package/dist/data/ai/SessionInspector.legacy.js +41 -42
  89. package/dist/data/ai/SessionInspector.legacy.js.map +1 -1
  90. package/dist/data/ai/SessionInspector.remote-view.cjs +14 -9
  91. package/dist/data/ai/SessionInspector.remote-view.cjs.map +1 -1
  92. package/dist/data/ai/SessionInspector.remote-view.d.ts +6 -2
  93. package/dist/data/ai/SessionInspector.remote-view.d.ts.map +1 -1
  94. package/dist/data/ai/SessionInspector.remote-view.js +14 -9
  95. package/dist/data/ai/SessionInspector.remote-view.js.map +1 -1
  96. package/dist/data/ai/SessionInspector.remote.cjs +84 -16
  97. package/dist/data/ai/SessionInspector.remote.cjs.map +1 -1
  98. package/dist/data/ai/SessionInspector.remote.d.ts +42 -7
  99. package/dist/data/ai/SessionInspector.remote.d.ts.map +1 -1
  100. package/dist/data/ai/SessionInspector.remote.js +86 -18
  101. package/dist/data/ai/SessionInspector.remote.js.map +1 -1
  102. package/dist/data/ai/SessionInspector.transcript.cjs +5 -0
  103. package/dist/data/ai/SessionInspector.transcript.cjs.map +1 -1
  104. package/dist/data/ai/SessionInspector.transcript.d.ts.map +1 -1
  105. package/dist/data/ai/SessionInspector.transcript.js +5 -0
  106. package/dist/data/ai/SessionInspector.transcript.js.map +1 -1
  107. package/dist/data/ai/SessionTail.cjs +63 -0
  108. package/dist/data/ai/SessionTail.cjs.map +1 -0
  109. package/dist/data/ai/SessionTail.d.ts +14 -0
  110. package/dist/data/ai/SessionTail.d.ts.map +1 -0
  111. package/dist/data/ai/SessionTail.js +63 -0
  112. package/dist/data/ai/SessionTail.js.map +1 -0
  113. package/dist/data/ai/SessionViewer.cjs +10 -3
  114. package/dist/data/ai/SessionViewer.cjs.map +1 -1
  115. package/dist/data/ai/SessionViewer.d.ts +7 -1
  116. package/dist/data/ai/SessionViewer.d.ts.map +1 -1
  117. package/dist/data/ai/SessionViewer.js +10 -3
  118. package/dist/data/ai/SessionViewer.js.map +1 -1
  119. package/dist/data/ai/SessionViewer.unified.d.ts +14 -0
  120. package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
  121. package/dist/data/ai/index.d.ts +4 -3
  122. package/dist/data/ai/index.d.ts.map +1 -1
  123. package/dist/data/ai/use-session-scroll.cjs +30 -6
  124. package/dist/data/ai/use-session-scroll.cjs.map +1 -1
  125. package/dist/data/ai/use-session-scroll.d.ts +7 -0
  126. package/dist/data/ai/use-session-scroll.d.ts.map +1 -1
  127. package/dist/data/ai/use-session-scroll.js +30 -6
  128. package/dist/data/ai/use-session-scroll.js.map +1 -1
  129. package/dist/data/chat/Chat.cjs +1 -1
  130. package/dist/data/chat/Chat.cjs.map +1 -1
  131. package/dist/data/chat/Chat.js +1 -1
  132. package/dist/data/chat/Chat.js.map +1 -1
  133. package/dist/data/chat/ChatRuntimeToolbar.cjs +4 -4
  134. package/dist/data/chat/ChatRuntimeToolbar.cjs.map +1 -1
  135. package/dist/data/chat/ChatRuntimeToolbar.d.ts.map +1 -1
  136. package/dist/data/chat/ChatRuntimeToolbar.js +4 -4
  137. package/dist/data/chat/ChatRuntimeToolbar.js.map +1 -1
  138. package/dist/data/chat/PromptInput.cjs +4 -2
  139. package/dist/data/chat/PromptInput.cjs.map +1 -1
  140. package/dist/data/chat/PromptInput.d.ts +5 -1
  141. package/dist/data/chat/PromptInput.d.ts.map +1 -1
  142. package/dist/data/chat/PromptInput.js +4 -2
  143. package/dist/data/chat/PromptInput.js.map +1 -1
  144. package/dist/data/diagnostics/ErrorDetails.cjs +13 -2
  145. package/dist/data/diagnostics/ErrorDetails.cjs.map +1 -1
  146. package/dist/data/diagnostics/ErrorDetails.d.ts +3 -1
  147. package/dist/data/diagnostics/ErrorDetails.d.ts.map +1 -1
  148. package/dist/data/diagnostics/ErrorDetails.js +14 -3
  149. package/dist/data/diagnostics/ErrorDetails.js.map +1 -1
  150. package/dist/data/diagnostics/FrameSourceWindow.cjs +3 -2
  151. package/dist/data/diagnostics/FrameSourceWindow.cjs.map +1 -1
  152. package/dist/data/diagnostics/FrameSourceWindow.d.ts.map +1 -1
  153. package/dist/data/diagnostics/FrameSourceWindow.js +3 -2
  154. package/dist/data/diagnostics/FrameSourceWindow.js.map +1 -1
  155. package/dist/data/diagnostics/error-diagnostics.cjs +5 -0
  156. package/dist/data/diagnostics/error-diagnostics.cjs.map +1 -1
  157. package/dist/data/diagnostics/error-diagnostics.d.ts +1 -0
  158. package/dist/data/diagnostics/error-diagnostics.d.ts.map +1 -1
  159. package/dist/data/diagnostics/error-diagnostics.js +6 -1
  160. package/dist/data/diagnostics/error-diagnostics.js.map +1 -1
  161. package/dist/data/har/HarPanel.cjs +3 -1
  162. package/dist/data/har/HarPanel.cjs.map +1 -1
  163. package/dist/data/har/HarPanel.d.ts +4 -1
  164. package/dist/data/har/HarPanel.d.ts.map +1 -1
  165. package/dist/data/har/HarPanel.js +3 -1
  166. package/dist/data/har/HarPanel.js.map +1 -1
  167. package/dist/data/test-runner/Expectation.cjs +57 -0
  168. package/dist/data/test-runner/Expectation.cjs.map +1 -0
  169. package/dist/data/test-runner/Expectation.d.ts +19 -0
  170. package/dist/data/test-runner/Expectation.d.ts.map +1 -0
  171. package/dist/data/test-runner/Expectation.js +57 -0
  172. package/dist/data/test-runner/Expectation.js.map +1 -0
  173. package/dist/data/test-runner/MarkIcons.cjs +38 -0
  174. package/dist/data/test-runner/MarkIcons.cjs.map +1 -0
  175. package/dist/data/test-runner/MarkIcons.d.ts +15 -0
  176. package/dist/data/test-runner/MarkIcons.d.ts.map +1 -0
  177. package/dist/data/test-runner/MarkIcons.js +38 -0
  178. package/dist/data/test-runner/MarkIcons.js.map +1 -0
  179. package/dist/data/test-runner/TestDetailPanel.cjs +74 -42
  180. package/dist/data/test-runner/TestDetailPanel.cjs.map +1 -1
  181. package/dist/data/test-runner/TestDetailPanel.d.ts.map +1 -1
  182. package/dist/data/test-runner/TestDetailPanel.js +76 -44
  183. package/dist/data/test-runner/TestDetailPanel.js.map +1 -1
  184. package/dist/data/test-runner/TestFailureDetail.cjs +23 -27
  185. package/dist/data/test-runner/TestFailureDetail.cjs.map +1 -1
  186. package/dist/data/test-runner/TestFailureDetail.d.ts +2 -2
  187. package/dist/data/test-runner/TestFailureDetail.d.ts.map +1 -1
  188. package/dist/data/test-runner/TestFailureDetail.js +23 -27
  189. package/dist/data/test-runner/TestFailureDetail.js.map +1 -1
  190. package/dist/data/test-runner/TestFilterBar.cjs +87 -93
  191. package/dist/data/test-runner/TestFilterBar.cjs.map +1 -1
  192. package/dist/data/test-runner/TestFilterBar.d.ts +3 -2
  193. package/dist/data/test-runner/TestFilterBar.d.ts.map +1 -1
  194. package/dist/data/test-runner/TestFilterBar.js +89 -95
  195. package/dist/data/test-runner/TestFilterBar.js.map +1 -1
  196. package/dist/data/test-runner/TestRunSummary.cjs +35 -21
  197. package/dist/data/test-runner/TestRunSummary.cjs.map +1 -1
  198. package/dist/data/test-runner/TestRunSummary.d.ts.map +1 -1
  199. package/dist/data/test-runner/TestRunSummary.js +35 -21
  200. package/dist/data/test-runner/TestRunSummary.js.map +1 -1
  201. package/dist/data/test-runner/TestRunner.cjs +52 -30
  202. package/dist/data/test-runner/TestRunner.cjs.map +1 -1
  203. package/dist/data/test-runner/TestRunner.d.ts +3 -2
  204. package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
  205. package/dist/data/test-runner/TestRunner.js +52 -30
  206. package/dist/data/test-runner/TestRunner.js.map +1 -1
  207. package/dist/data/test-runner/TestTree.cjs +5 -2
  208. package/dist/data/test-runner/TestTree.cjs.map +1 -1
  209. package/dist/data/test-runner/TestTree.d.ts +5 -2
  210. package/dist/data/test-runner/TestTree.d.ts.map +1 -1
  211. package/dist/data/test-runner/TestTree.js +5 -2
  212. package/dist/data/test-runner/TestTree.js.map +1 -1
  213. package/dist/data/test-runner/TestTreeNode.cjs +27 -19
  214. package/dist/data/test-runner/TestTreeNode.cjs.map +1 -1
  215. package/dist/data/test-runner/TestTreeNode.d.ts.map +1 -1
  216. package/dist/data/test-runner/TestTreeNode.js +28 -20
  217. package/dist/data/test-runner/TestTreeNode.js.map +1 -1
  218. package/dist/data/test-runner/adapter.cjs +11 -0
  219. package/dist/data/test-runner/adapter.cjs.map +1 -1
  220. package/dist/data/test-runner/adapter.d.ts +18 -7
  221. package/dist/data/test-runner/adapter.d.ts.map +1 -1
  222. package/dist/data/test-runner/adapter.js +11 -0
  223. package/dist/data/test-runner/adapter.js.map +1 -1
  224. package/dist/data/test-runner/copy.cjs +114 -0
  225. package/dist/data/test-runner/copy.cjs.map +1 -0
  226. package/dist/data/test-runner/copy.d.ts +47 -0
  227. package/dist/data/test-runner/copy.d.ts.map +1 -0
  228. package/dist/data/test-runner/copy.js +114 -0
  229. package/dist/data/test-runner/copy.js.map +1 -0
  230. package/dist/data/test-runner/index.d.ts +5 -2
  231. package/dist/data/test-runner/index.d.ts.map +1 -1
  232. package/dist/data/test-runner/marks.cjs +143 -0
  233. package/dist/data/test-runner/marks.cjs.map +1 -0
  234. package/dist/data/test-runner/marks.d.ts +30 -0
  235. package/dist/data/test-runner/marks.d.ts.map +1 -0
  236. package/dist/data/test-runner/marks.js +143 -0
  237. package/dist/data/test-runner/marks.js.map +1 -0
  238. package/dist/data/test-runner/status.cjs +27 -44
  239. package/dist/data/test-runner/status.cjs.map +1 -1
  240. package/dist/data/test-runner/status.d.ts +12 -3
  241. package/dist/data/test-runner/status.d.ts.map +1 -1
  242. package/dist/data/test-runner/status.js +27 -44
  243. package/dist/data/test-runner/status.js.map +1 -1
  244. package/dist/data/verification/adapterViews.cjs +16 -41
  245. package/dist/data/verification/adapterViews.cjs.map +1 -1
  246. package/dist/data/verification/adapterViews.d.ts.map +1 -1
  247. package/dist/data/verification/adapterViews.js +16 -41
  248. package/dist/data/verification/adapterViews.js.map +1 -1
  249. package/dist/data/verification/adapters.cjs +115 -3
  250. package/dist/data/verification/adapters.cjs.map +1 -1
  251. package/dist/data/verification/adapters.d.ts.map +1 -1
  252. package/dist/data/verification/adapters.js +115 -3
  253. package/dist/data/verification/adapters.js.map +1 -1
  254. package/dist/data/verification/verifyReportTests.cjs.map +1 -1
  255. package/dist/data/verification/verifyReportTests.js.map +1 -1
  256. package/dist/data/version-info.cjs +3 -3
  257. package/dist/data/version-info.js +3 -3
  258. package/dist/data.cjs +44 -3
  259. package/dist/data.cjs.map +1 -1
  260. package/dist/data.d.ts +2 -0
  261. package/dist/data.d.ts.map +1 -1
  262. package/dist/data.js +45 -4
  263. package/dist/data.js.map +1 -1
  264. package/dist/icons/components/UiLogoEslint.cjs +10 -0
  265. package/dist/icons/components/UiLogoEslint.cjs.map +1 -0
  266. package/dist/icons/components/UiLogoEslint.d.ts +9 -0
  267. package/dist/icons/components/UiLogoEslint.d.ts.map +1 -0
  268. package/dist/icons/components/UiLogoEslint.js +10 -0
  269. package/dist/icons/components/UiLogoEslint.js.map +1 -0
  270. package/dist/icons/components/UiLogoGo.cjs +10 -0
  271. package/dist/icons/components/UiLogoGo.cjs.map +1 -0
  272. package/dist/icons/components/UiLogoGo.d.ts +9 -0
  273. package/dist/icons/components/UiLogoGo.d.ts.map +1 -0
  274. package/dist/icons/components/UiLogoGo.js +10 -0
  275. package/dist/icons/components/UiLogoGo.js.map +1 -0
  276. package/dist/icons/components/UiLogoJest.cjs +10 -0
  277. package/dist/icons/components/UiLogoJest.cjs.map +1 -0
  278. package/dist/icons/components/UiLogoJest.d.ts +9 -0
  279. package/dist/icons/components/UiLogoJest.d.ts.map +1 -0
  280. package/dist/icons/components/UiLogoJest.js +10 -0
  281. package/dist/icons/components/UiLogoJest.js.map +1 -0
  282. package/dist/icons/components/UiLogoMarkdown.cjs +10 -0
  283. package/dist/icons/components/UiLogoMarkdown.cjs.map +1 -0
  284. package/dist/icons/components/UiLogoMarkdown.d.ts +9 -0
  285. package/dist/icons/components/UiLogoMarkdown.d.ts.map +1 -0
  286. package/dist/icons/components/UiLogoMarkdown.js +10 -0
  287. package/dist/icons/components/UiLogoMarkdown.js.map +1 -0
  288. package/dist/icons/components/UiLogoOxc.cjs +10 -0
  289. package/dist/icons/components/UiLogoOxc.cjs.map +1 -0
  290. package/dist/icons/components/UiLogoOxc.d.ts +9 -0
  291. package/dist/icons/components/UiLogoOxc.d.ts.map +1 -0
  292. package/dist/icons/components/UiLogoOxc.js +10 -0
  293. package/dist/icons/components/UiLogoOxc.js.map +1 -0
  294. package/dist/icons/components/UiLogoPlaywright.cjs +10 -0
  295. package/dist/icons/components/UiLogoPlaywright.cjs.map +1 -0
  296. package/dist/icons/components/UiLogoPlaywright.d.ts +9 -0
  297. package/dist/icons/components/UiLogoPlaywright.d.ts.map +1 -0
  298. package/dist/icons/components/UiLogoPlaywright.js +10 -0
  299. package/dist/icons/components/UiLogoPlaywright.js.map +1 -0
  300. package/dist/icons/components/UiLogoPython.cjs +10 -0
  301. package/dist/icons/components/UiLogoPython.cjs.map +1 -0
  302. package/dist/icons/components/UiLogoPython.d.ts +9 -0
  303. package/dist/icons/components/UiLogoPython.d.ts.map +1 -0
  304. package/dist/icons/components/UiLogoPython.js +10 -0
  305. package/dist/icons/components/UiLogoPython.js.map +1 -0
  306. package/dist/icons/components/UiLogoReact.cjs +10 -0
  307. package/dist/icons/components/UiLogoReact.cjs.map +1 -0
  308. package/dist/icons/components/UiLogoReact.d.ts +9 -0
  309. package/dist/icons/components/UiLogoReact.d.ts.map +1 -0
  310. package/dist/icons/components/UiLogoReact.js +10 -0
  311. package/dist/icons/components/UiLogoReact.js.map +1 -0
  312. package/dist/icons/components/UiLogoRuff.cjs +10 -0
  313. package/dist/icons/components/UiLogoRuff.cjs.map +1 -0
  314. package/dist/icons/components/UiLogoRuff.d.ts +9 -0
  315. package/dist/icons/components/UiLogoRuff.d.ts.map +1 -0
  316. package/dist/icons/components/UiLogoRuff.js +10 -0
  317. package/dist/icons/components/UiLogoRuff.js.map +1 -0
  318. package/dist/icons/components/UiLogoTypescript.cjs +10 -0
  319. package/dist/icons/components/UiLogoTypescript.cjs.map +1 -0
  320. package/dist/icons/components/UiLogoTypescript.d.ts +9 -0
  321. package/dist/icons/components/UiLogoTypescript.d.ts.map +1 -0
  322. package/dist/icons/components/UiLogoTypescript.js +10 -0
  323. package/dist/icons/components/UiLogoTypescript.js.map +1 -0
  324. package/dist/icons/components/UiLogoVitest.cjs +10 -0
  325. package/dist/icons/components/UiLogoVitest.cjs.map +1 -0
  326. package/dist/icons/components/UiLogoVitest.d.ts +9 -0
  327. package/dist/icons/components/UiLogoVitest.d.ts.map +1 -0
  328. package/dist/icons/components/UiLogoVitest.js +10 -0
  329. package/dist/icons/components/UiLogoVitest.js.map +1 -0
  330. package/dist/icons/index.d.ts +11 -0
  331. package/dist/icons/index.d.ts.map +1 -1
  332. package/dist/icons/registry.cjs +22 -0
  333. package/dist/icons/registry.cjs.map +1 -1
  334. package/dist/icons/registry.d.ts.map +1 -1
  335. package/dist/icons/registry.js +22 -0
  336. package/dist/icons/registry.js.map +1 -1
  337. package/dist/icons.cjs +22 -0
  338. package/dist/icons.cjs.map +1 -1
  339. package/dist/icons.js +22 -0
  340. package/dist/icons.js.map +1 -1
  341. package/dist/index.cjs +44 -3
  342. package/dist/index.cjs.map +1 -1
  343. package/dist/index.js +45 -4
  344. package/dist/index.js.map +1 -1
  345. package/dist/overlay/DropdownMenuSubmenu.cjs +4 -4
  346. package/dist/overlay/DropdownMenuSubmenu.cjs.map +1 -1
  347. package/dist/overlay/DropdownMenuSubmenu.js +4 -4
  348. package/dist/overlay/DropdownMenuSubmenu.js.map +1 -1
  349. package/dist/rpc/InlineError.cjs +12 -43
  350. package/dist/rpc/InlineError.cjs.map +1 -1
  351. package/dist/rpc/InlineError.d.ts.map +1 -1
  352. package/dist/rpc/InlineError.js +13 -44
  353. package/dist/rpc/InlineError.js.map +1 -1
  354. package/dist/rpc/OperationScheduleDialog.cjs +63 -10
  355. package/dist/rpc/OperationScheduleDialog.cjs.map +1 -1
  356. package/dist/rpc/OperationScheduleDialog.d.ts +4 -0
  357. package/dist/rpc/OperationScheduleDialog.d.ts.map +1 -1
  358. package/dist/rpc/OperationScheduleDialog.js +63 -10
  359. package/dist/rpc/OperationScheduleDialog.js.map +1 -1
  360. package/dist/rpc/OperationSchedules.cjs +12 -2
  361. package/dist/rpc/OperationSchedules.cjs.map +1 -1
  362. package/dist/rpc/OperationSchedules.d.ts.map +1 -1
  363. package/dist/rpc/OperationSchedules.js +12 -2
  364. package/dist/rpc/OperationSchedules.js.map +1 -1
  365. package/dist/rpc/operation-schedule-model.cjs +2 -0
  366. package/dist/rpc/operation-schedule-model.cjs.map +1 -1
  367. package/dist/rpc/operation-schedule-model.d.ts.map +1 -1
  368. package/dist/rpc/operation-schedule-model.js +2 -0
  369. package/dist/rpc/operation-schedule-model.js.map +1 -1
  370. package/dist/rpc/operation-schedule-types.d.ts +7 -1
  371. package/dist/rpc/operation-schedule-types.d.ts.map +1 -1
  372. package/dist/styles.css +1 -1
  373. package/package.json +1 -1
  374. package/dist/data/test-runner/frameworkIcon.cjs +0 -27
  375. package/dist/data/test-runner/frameworkIcon.cjs.map +0 -1
  376. package/dist/data/test-runner/frameworkIcon.d.ts +0 -3
  377. package/dist/data/test-runner/frameworkIcon.d.ts.map +0 -1
  378. package/dist/data/test-runner/frameworkIcon.js +0 -27
  379. package/dist/data/test-runner/frameworkIcon.js.map +0 -1
@@ -1,11 +1,4 @@
1
1
  import { matchesFilterState } from "./filterState.js";
2
- import { UiHourglass } from "../../icons/components/UiHourglass.js";
3
- import { UiLoader } from "../../icons/components/UiLoader.js";
4
- import { UiPause } from "../../icons/components/UiPause.js";
5
- import { UiError } from "../../icons/components/UiError.js";
6
- import { UiWarningTriangle } from "../../icons/components/UiWarningTriangle.js";
7
- import { UiPass } from "../../icons/components/UiPass.js";
8
- import { UiClass } from "../../icons/components/UiClass.js";
9
2
  const emptyCounts = () => ({
10
3
  total: 0,
11
4
  passed: 0,
@@ -111,44 +104,34 @@ function testStatus(t) {
111
104
  if (t.passed) return "passed";
112
105
  return null;
113
106
  }
114
- function statusIconFor(t) {
115
- if (t.timed_out) return UiHourglass;
116
- if (t.running) return UiLoader;
117
- if (t.pending) return UiPause;
118
- if (t.failed) return UiError;
119
- if (t.warned) return UiWarningTriangle;
120
- if (t.skipped) return UiPause;
121
- if (t.passed) return UiPass;
122
- if (t.children && t.children.length > 0) {
123
- const s = sum(t);
124
- if (hasTimedOutDescendant(t)) return UiHourglass;
125
- if (s.failed > 0) return UiError;
126
- if (s.warned > 0) return UiWarningTriangle;
127
- if (s.running > 0) return UiLoader;
128
- if (s.pending > 0) return UiPause;
129
- return UiPass;
130
- }
131
- return UiClass;
107
+ function outcomeFor(t) {
108
+ var _a;
109
+ const own = testStatus(t);
110
+ if (own) return own;
111
+ if (!((_a = t.children) == null ? void 0 : _a.length)) return null;
112
+ const s = sum(t);
113
+ if (hasTimedOutDescendant(t)) return "timedout";
114
+ if (s.failed > 0) return "failed";
115
+ if (s.warned > 0) return "warned";
116
+ if (s.running > 0) return "running";
117
+ if (s.pending > 0) return "pending";
118
+ if (s.total > 0 && s.skipped === s.total) return "skipped";
119
+ return "passed";
132
120
  }
133
121
  function statusToneFor(t) {
134
- if (t.timed_out) return "warning";
135
- if (t.running) return "info";
136
- if (t.pending) return "neutral";
137
- if (t.failed) return "danger";
138
- if (t.warned) return "warning";
139
- if (t.skipped) return "warning";
140
- if (t.passed) return "success";
141
- if (t.children && t.children.length > 0) {
142
- const s = sum(t);
143
- if (hasTimedOutDescendant(t)) return "warning";
144
- if (s.failed > 0) return "danger";
145
- if (s.warned > 0) return "warning";
146
- if (s.running > 0) return "info";
147
- if (s.pending > 0) return "neutral";
148
- return "success";
149
- }
150
- return "neutral";
151
- }
122
+ const outcome = outcomeFor(t);
123
+ return outcome ? OUTCOME_TONE[outcome] : "neutral";
124
+ }
125
+ const OUTCOME_TONE = {
126
+ failed: "danger",
127
+ errored: "danger",
128
+ timedout: "warning",
129
+ warned: "warning",
130
+ skipped: "warning",
131
+ running: "info",
132
+ pending: "neutral",
133
+ passed: "success"
134
+ };
152
135
  function formatTestDuration(ns) {
153
136
  if (ns <= 0) return "";
154
137
  const ms = ns / 1e6;
@@ -240,7 +223,7 @@ export {
240
223
  hasFailed,
241
224
  hasPending,
242
225
  humanizeName,
243
- statusIconFor,
226
+ outcomeFor,
244
227
  statusToneFor,
245
228
  sum,
246
229
  sumNonTaskTests,
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sources":["../../../src/data/test-runner/status.ts"],"sourcesContent":["// Pure status/roll-up helpers for the test runner — ported from Gavel's\n// utils.ts (Tests-only subset). No JSX here. The two status mappers\n// (statusIconFor / statusToneFor) replace Gavel's raw-Tailwind statusIcon /\n// statusColor with clicky's icon set and semantic Badge tones.\n\nimport type { StaticIconComponent } from \"../Icon\";\nimport type { BadgeTone } from \"../Badge\";\nimport {\n UiClass,\n UiError,\n UiHourglass,\n UiLoader,\n UiPass,\n UiPause,\n UiWarningTriangle,\n} from \"../../icons\";\nimport type { Test, TestSummary } from \"./types\";\nimport { matchesFilterState, type FilterState } from \"./filterState\";\n\n// --- roll-up counts ------------------------------------------------------\n\n/**\n * Tallied verdict breakdown a `Test` subtree rolls up to. `warned` is amber and\n * orthogonal to a real failure — a warned-only leaf counts in total + warned,\n * never in failed.\n */\nexport type StatusCounts = {\n total: number;\n passed: number;\n failed: number;\n warned: number;\n skipped: number;\n pending: number;\n running: number;\n timedout: number;\n};\n\nconst emptyCounts = (): StatusCounts => ({\n total: 0,\n passed: 0,\n failed: 0,\n warned: 0,\n skipped: 0,\n pending: 0,\n running: 0,\n timedout: 0,\n});\n\nconst addCounts = (r: StatusCounts, s: StatusCounts) => {\n r.total += s.total;\n r.passed += s.passed;\n r.failed += s.failed;\n r.warned += s.warned;\n r.skipped += s.skipped;\n r.pending += s.pending;\n r.running += s.running;\n r.timedout += s.timedout;\n};\n\nconst countsFromSummary = (summary: TestSummary): StatusCounts => ({\n total: summary.Total,\n passed: summary.Passed,\n failed: summary.Failed,\n warned: summary.Warned || 0,\n skipped: summary.Skipped,\n pending: summary.Pending || 0,\n running: summary.Running || 0,\n timedout: summary.Timedout || 0,\n});\n\nconst countsFromLeaf = (t: Test): StatusCounts => {\n const isTimedOut = !!t.timed_out;\n const counted =\n isTimedOut || t.passed || t.failed || t.warned || t.skipped || t.pending || t.running;\n return {\n total: counted ? 1 : 0,\n passed: !isTimedOut && t.passed ? 1 : 0,\n failed: !isTimedOut && t.failed ? 1 : 0,\n warned: !isTimedOut && t.warned ? 1 : 0,\n skipped: !isTimedOut && t.skipped ? 1 : 0,\n pending: !isTimedOut && t.pending ? 1 : 0,\n running: !isTimedOut && t.running ? 1 : 0,\n timedout: isTimedOut ? 1 : 0,\n };\n};\n\nexport function sum(t: Test): StatusCounts {\n if (t.summary) return countsFromSummary(t.summary);\n if (!t.children || t.children.length === 0) return countsFromLeaf(t);\n const r = emptyCounts();\n for (const c of t.children) addCounts(r, sum(c));\n return r;\n}\n\n/** Roll up a forest's non-task status counts. Shared by `TestRunner`'s filter\n * bar and `TestRunSummary`'s chips so both read the same tally. */\nexport function aggregateStatusCounts(tests: Test[]): StatusCounts {\n const r = emptyCounts();\n for (const t of tests) addCounts(r, sumNonTaskTests(t));\n return r;\n}\n\n/** Ordered status key → label list, driving both the filter bar's pills and a\n * host's status filter option list, so the seven rows aren't hand-duplicated. */\nexport const STATUS_LABELS: { key: keyof StatusCounts; label: string }[] = [\n { key: \"failed\", label: \"Failed\" },\n { key: \"warned\", label: \"Warned\" },\n { key: \"timedout\", label: \"Timed out\" },\n { key: \"passed\", label: \"Passed\" },\n { key: \"skipped\", label: \"Skipped\" },\n { key: \"running\", label: \"Running\" },\n { key: \"pending\", label: \"Queued\" },\n];\n\n/** Like {@link sum} but excludes `task`-framework pseudo-nodes from the tally. */\nexport function sumNonTaskTests(t: Test): StatusCounts {\n if (t.framework === \"task\") {\n const r = emptyCounts();\n for (const c of t.children || []) addCounts(r, sumNonTaskTests(c));\n return r;\n }\n if (t.summary) return countsFromSummary(t.summary);\n if (!t.children || t.children.length === 0) return countsFromLeaf(t);\n const r = emptyCounts();\n for (const c of t.children) addCounts(r, sumNonTaskTests(c));\n return r;\n}\n\nexport function hasFailed(t: Test): boolean {\n if (t.failed) return true;\n return (t.children || []).some(hasFailed);\n}\n\nexport function hasPending(t: Test): boolean {\n if (t.pending) return true;\n return (t.children || []).some(hasPending);\n}\n\nfunction hasTimedOutDescendant(t: Test): boolean {\n if (t.timed_out) return true;\n return (t.children || []).some(hasTimedOutDescendant);\n}\n\nexport function totalDuration(t: Test): number {\n if (t.duration && t.duration > 0) return t.duration;\n let d = 0;\n for (const c of t.children || []) d += totalDuration(c);\n return d;\n}\n\n// --- status classification ----------------------------------------------\n\nexport type TestStatus =\n | \"passed\"\n | \"failed\"\n | \"warned\"\n | \"skipped\"\n | \"pending\"\n | \"running\"\n | \"timedout\";\n\n/** Resolve a leaf node's single status, or null for a status-less container. */\nexport function testStatus(t: Test): TestStatus | null {\n if (t.timed_out) return \"timedout\";\n if (t.running) return \"running\";\n if (t.pending) return \"pending\";\n if (t.failed) return \"failed\";\n if (t.warned) return \"warned\";\n if (t.skipped) return \"skipped\";\n if (t.passed) return \"passed\";\n return null;\n}\n\n/** Pick the clicky icon for a node, rolling up container state. */\nexport function statusIconFor(t: Test): StaticIconComponent {\n if (t.timed_out) return UiHourglass;\n if (t.running) return UiLoader;\n if (t.pending) return UiPause;\n if (t.failed) return UiError;\n if (t.warned) return UiWarningTriangle;\n if (t.skipped) return UiPause;\n if (t.passed) return UiPass;\n if (t.children && t.children.length > 0) {\n const s = sum(t);\n if (hasTimedOutDescendant(t)) return UiHourglass;\n if (s.failed > 0) return UiError;\n if (s.warned > 0) return UiWarningTriangle;\n if (s.running > 0) return UiLoader;\n if (s.pending > 0) return UiPause;\n return UiPass;\n }\n return UiClass;\n}\n\n/** Map a node's status to a semantic Badge tone, rolling up container state. */\nexport function statusToneFor(t: Test): BadgeTone {\n if (t.timed_out) return \"warning\";\n if (t.running) return \"info\";\n if (t.pending) return \"neutral\";\n if (t.failed) return \"danger\";\n if (t.warned) return \"warning\";\n if (t.skipped) return \"warning\";\n if (t.passed) return \"success\";\n if (t.children && t.children.length > 0) {\n const s = sum(t);\n if (hasTimedOutDescendant(t)) return \"warning\";\n if (s.failed > 0) return \"danger\";\n if (s.warned > 0) return \"warning\";\n if (s.running > 0) return \"info\";\n if (s.pending > 0) return \"neutral\";\n return \"success\";\n }\n return \"neutral\";\n}\n\n// --- formatting ----------------------------------------------------------\n\n/**\n * Format a nanosecond duration as \"123ms\" or \"1.2s\". Empty for non-positive.\n * Named distinctly from clicky's ms/s `formatDuration` (lib/format) since the\n * test-runner wire format is nanoseconds.\n */\nexport function formatTestDuration(ns: number): string {\n if (ns <= 0) return \"\";\n const ms = ns / 1e6;\n if (ms < 1000) return `${ms.toFixed(0)}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\nfunction compactWithUnit(value: number, unit: string): string {\n const rounded =\n Math.abs(value) >= 10 ? Math.round(value).toString() : value.toFixed(1).replace(/\\.0$/, \"\");\n return `${rounded}${unit}`;\n}\n\n/** Compact integer counts: <1000 raw, then \"k\", then \"M\". */\nexport function formatCount(n: number): string {\n const abs = Math.abs(n);\n if (abs < 1000) return String(n);\n if (abs < 1_000_000) return compactWithUnit(n / 1000, \"k\");\n return compactWithUnit(n / 1_000_000, \"M\");\n}\n\n/** Strip Go's `Test` prefix and split CamelCase / subtest names into words. */\nexport function humanizeName(name: string, framework?: string): string {\n if (!name) return \"\";\n if (framework !== \"go test\") return name;\n if (name.endsWith(\"/\")) return name;\n return name\n .split(\"/\")\n .map((p, i) => {\n if (i === 0) {\n return p.replace(/^Test/, \"\").replace(/([a-z0-9])([A-Z])/g, \"$1 $2\");\n }\n return p.replace(/_/g, \" \");\n })\n .join(\" / \");\n}\n\n// --- tree transforms -----------------------------------------------------\n\n/** Unique non-task frameworks present in the forest, sorted. */\nexport function collectFrameworks(tests: Test[]): string[] {\n const set = new Set<string>();\n const walk = (t: Test) => {\n if (t.framework && t.framework !== \"task\") set.add(t.framework);\n (t.children || []).forEach(walk);\n };\n tests.forEach(walk);\n return Array.from(set).sort();\n}\n\nfunction joinChainNames(parent: string | undefined, child: string | undefined): string {\n const p = (parent ?? \"\").trim();\n const c = (child ?? \"\").trim();\n if (!p) return c;\n if (!c) return p;\n return `${p} > ${c}`;\n}\n\nfunction isCollapsibleContainer(t: Test): boolean {\n return !(t.passed || t.failed || t.skipped || t.pending);\n}\n\n// Re-deriving a collapsed/filtered node invalidates any cached summary; drop it\n// so callers re-roll-up from the surviving children.\nfunction withoutSummary(t: Test): Omit<Test, \"summary\"> & { summary?: never } {\n const { summary: _summary, ...rest } = t;\n return rest;\n}\n\nfunction collapseNode(t: Test): Test {\n const children = t.children ?? [];\n if (children.length === 0) return t;\n\n const collapsedChildren = children.map(collapseNode);\n\n const onlyChild = collapsedChildren.length === 1 ? collapsedChildren[0] : undefined;\n if (onlyChild && isCollapsibleContainer(t)) {\n return { ...withoutSummary(onlyChild), name: joinChainNames(t.name, onlyChild.name) };\n }\n\n return { ...t, children: collapsedChildren };\n}\n\n/**\n * Compress any status-less container with exactly one child into that child,\n * joining names with \" > \". Recursive, so chains collapse into a single row.\n */\nexport function collapseSingleChildChains(tests: Test[]): Test[] {\n return tests.map(collapseNode);\n}\n\nfunction matchesLeaf(\n t: Test,\n statusFilter: FilterState<string>,\n frameworkFilter: FilterState<string>,\n): boolean {\n const s = testStatus(t);\n if (s === null) return false;\n return matchesFilterState(s, statusFilter) && matchesFilterState(t.framework, frameworkFilter);\n}\n\nfunction filterNode(\n t: Test,\n statusFilter: FilterState<string>,\n frameworkFilter: FilterState<string>,\n): Test | null {\n if (t.children && t.children.length > 0) {\n const filtered = t.children\n .map((c) => filterNode(c, statusFilter, frameworkFilter))\n .filter(Boolean) as Test[];\n if (filtered.length === 0) return null;\n return { ...withoutSummary(t), children: filtered };\n }\n return matchesLeaf(t, statusFilter, frameworkFilter) ? t : null;\n}\n\n/** Prune leaves not matching the status/framework filters; drop empty branches. */\nexport function filterTests(\n tests: Test[],\n statusFilter: FilterState<string>,\n frameworkFilter: FilterState<string>,\n): Test[] {\n if (statusFilter.size === 0 && frameworkFilter.size === 0) return tests;\n return tests\n .map((t) => filterNode(t, statusFilter, frameworkFilter))\n .filter(Boolean) as Test[];\n}\n"],"names":["r"],"mappings":"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"}
1
+ {"version":3,"file":"status.js","sources":["../../../src/data/test-runner/status.ts"],"sourcesContent":["// Pure status/roll-up helpers for the test runner — ported from Gavel's\n// utils.ts (Tests-only subset). No JSX here. `outcomeFor` resolves the outcome\n// marks.tsx draws; `statusToneFor` maps it to a semantic Badge tone.\n\nimport type { BadgeTone } from \"../Badge\";\nimport type { Test, TestSummary } from \"./types\";\nimport { matchesFilterState, type FilterState } from \"./filterState\";\n\n// --- roll-up counts ------------------------------------------------------\n\n/**\n * Tallied verdict breakdown a `Test` subtree rolls up to. `warned` is amber and\n * orthogonal to a real failure — a warned-only leaf counts in total + warned,\n * never in failed.\n */\nexport type StatusCounts = {\n total: number;\n passed: number;\n failed: number;\n warned: number;\n skipped: number;\n pending: number;\n running: number;\n timedout: number;\n};\n\nconst emptyCounts = (): StatusCounts => ({\n total: 0,\n passed: 0,\n failed: 0,\n warned: 0,\n skipped: 0,\n pending: 0,\n running: 0,\n timedout: 0,\n});\n\nconst addCounts = (r: StatusCounts, s: StatusCounts) => {\n r.total += s.total;\n r.passed += s.passed;\n r.failed += s.failed;\n r.warned += s.warned;\n r.skipped += s.skipped;\n r.pending += s.pending;\n r.running += s.running;\n r.timedout += s.timedout;\n};\n\nconst countsFromSummary = (summary: TestSummary): StatusCounts => ({\n total: summary.Total,\n passed: summary.Passed,\n failed: summary.Failed,\n warned: summary.Warned || 0,\n skipped: summary.Skipped,\n pending: summary.Pending || 0,\n running: summary.Running || 0,\n timedout: summary.Timedout || 0,\n});\n\nconst countsFromLeaf = (t: Test): StatusCounts => {\n const isTimedOut = !!t.timed_out;\n const counted =\n isTimedOut || t.passed || t.failed || t.warned || t.skipped || t.pending || t.running;\n return {\n total: counted ? 1 : 0,\n passed: !isTimedOut && t.passed ? 1 : 0,\n failed: !isTimedOut && t.failed ? 1 : 0,\n warned: !isTimedOut && t.warned ? 1 : 0,\n skipped: !isTimedOut && t.skipped ? 1 : 0,\n pending: !isTimedOut && t.pending ? 1 : 0,\n running: !isTimedOut && t.running ? 1 : 0,\n timedout: isTimedOut ? 1 : 0,\n };\n};\n\nexport function sum(t: Test): StatusCounts {\n if (t.summary) return countsFromSummary(t.summary);\n if (!t.children || t.children.length === 0) return countsFromLeaf(t);\n const r = emptyCounts();\n for (const c of t.children) addCounts(r, sum(c));\n return r;\n}\n\n/** Roll up a forest's non-task status counts. Shared by `TestRunner`'s filter\n * bar and `TestRunSummary`'s chips so both read the same tally. */\nexport function aggregateStatusCounts(tests: Test[]): StatusCounts {\n const r = emptyCounts();\n for (const t of tests) addCounts(r, sumNonTaskTests(t));\n return r;\n}\n\n/** Ordered status key → label list, driving both the filter bar's pills and a\n * host's status filter option list, so the seven rows aren't hand-duplicated. */\nexport const STATUS_LABELS: { key: keyof StatusCounts; label: string }[] = [\n { key: \"failed\", label: \"Failed\" },\n { key: \"warned\", label: \"Warned\" },\n { key: \"timedout\", label: \"Timed out\" },\n { key: \"passed\", label: \"Passed\" },\n { key: \"skipped\", label: \"Skipped\" },\n { key: \"running\", label: \"Running\" },\n { key: \"pending\", label: \"Queued\" },\n];\n\n/** Like {@link sum} but excludes `task`-framework pseudo-nodes from the tally. */\nexport function sumNonTaskTests(t: Test): StatusCounts {\n if (t.framework === \"task\") {\n const r = emptyCounts();\n for (const c of t.children || []) addCounts(r, sumNonTaskTests(c));\n return r;\n }\n if (t.summary) return countsFromSummary(t.summary);\n if (!t.children || t.children.length === 0) return countsFromLeaf(t);\n const r = emptyCounts();\n for (const c of t.children) addCounts(r, sumNonTaskTests(c));\n return r;\n}\n\nexport function hasFailed(t: Test): boolean {\n if (t.failed) return true;\n return (t.children || []).some(hasFailed);\n}\n\nexport function hasPending(t: Test): boolean {\n if (t.pending) return true;\n return (t.children || []).some(hasPending);\n}\n\nfunction hasTimedOutDescendant(t: Test): boolean {\n if (t.timed_out) return true;\n return (t.children || []).some(hasTimedOutDescendant);\n}\n\nexport function totalDuration(t: Test): number {\n if (t.duration && t.duration > 0) return t.duration;\n let d = 0;\n for (const c of t.children || []) d += totalDuration(c);\n return d;\n}\n\n// --- status classification ----------------------------------------------\n\nexport type TestStatus =\n | \"passed\"\n | \"failed\"\n | \"warned\"\n | \"skipped\"\n | \"pending\"\n | \"running\"\n | \"timedout\";\n\n/** Resolve a leaf node's single status, or null for a status-less container. */\nexport function testStatus(t: Test): TestStatus | null {\n if (t.timed_out) return \"timedout\";\n if (t.running) return \"running\";\n if (t.pending) return \"pending\";\n if (t.failed) return \"failed\";\n if (t.warned) return \"warned\";\n if (t.skipped) return \"skipped\";\n if (t.passed) return \"passed\";\n return null;\n}\n\n/**\n * A test or lint result's outcome. `errored` is a result the runner could not\n * produce at all (the engine crashed, the child run never reported) — distinct\n * from a test that ran and failed.\n */\nexport type TestOutcome = TestStatus | \"errored\";\n\n/**\n * Resolve a node's outcome, rolling a container up to its worst child: a\n * timeout anywhere, then failed, warned, running, queued, else passed. Null for\n * a status-less leaf.\n */\nexport function outcomeFor(t: Test): TestOutcome | null {\n const own = testStatus(t);\n if (own) return own;\n if (!t.children?.length) return null;\n const s = sum(t);\n if (hasTimedOutDescendant(t)) return \"timedout\";\n if (s.failed > 0) return \"failed\";\n if (s.warned > 0) return \"warned\";\n if (s.running > 0) return \"running\";\n if (s.pending > 0) return \"pending\";\n if (s.total > 0 && s.skipped === s.total) return \"skipped\";\n return \"passed\";\n}\n\n/** Map a node's status to a semantic Badge tone, rolling up container state. */\nexport function statusToneFor(t: Test): BadgeTone {\n const outcome = outcomeFor(t);\n return outcome ? OUTCOME_TONE[outcome] : \"neutral\";\n}\n\nconst OUTCOME_TONE: Record<TestOutcome, BadgeTone> = {\n failed: \"danger\",\n errored: \"danger\",\n timedout: \"warning\",\n warned: \"warning\",\n skipped: \"warning\",\n running: \"info\",\n pending: \"neutral\",\n passed: \"success\",\n};\n\n// --- formatting ----------------------------------------------------------\n\n/**\n * Format a nanosecond duration as \"123ms\" or \"1.2s\". Empty for non-positive.\n * Named distinctly from clicky's ms/s `formatDuration` (lib/format) since the\n * test-runner wire format is nanoseconds.\n */\nexport function formatTestDuration(ns: number): string {\n if (ns <= 0) return \"\";\n const ms = ns / 1e6;\n if (ms < 1000) return `${ms.toFixed(0)}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\nfunction compactWithUnit(value: number, unit: string): string {\n const rounded =\n Math.abs(value) >= 10 ? Math.round(value).toString() : value.toFixed(1).replace(/\\.0$/, \"\");\n return `${rounded}${unit}`;\n}\n\n/** Compact integer counts: <1000 raw, then \"k\", then \"M\". */\nexport function formatCount(n: number): string {\n const abs = Math.abs(n);\n if (abs < 1000) return String(n);\n if (abs < 1_000_000) return compactWithUnit(n / 1000, \"k\");\n return compactWithUnit(n / 1_000_000, \"M\");\n}\n\n/** Strip Go's `Test` prefix and split CamelCase / subtest names into words. */\nexport function humanizeName(name: string, framework?: string): string {\n if (!name) return \"\";\n if (framework !== \"go test\") return name;\n if (name.endsWith(\"/\")) return name;\n return name\n .split(\"/\")\n .map((p, i) => {\n if (i === 0) {\n return p.replace(/^Test/, \"\").replace(/([a-z0-9])([A-Z])/g, \"$1 $2\");\n }\n return p.replace(/_/g, \" \");\n })\n .join(\" / \");\n}\n\n// --- tree transforms -----------------------------------------------------\n\n/** Unique non-task frameworks present in the forest, sorted. */\nexport function collectFrameworks(tests: Test[]): string[] {\n const set = new Set<string>();\n const walk = (t: Test) => {\n if (t.framework && t.framework !== \"task\") set.add(t.framework);\n (t.children || []).forEach(walk);\n };\n tests.forEach(walk);\n return Array.from(set).sort();\n}\n\nfunction joinChainNames(parent: string | undefined, child: string | undefined): string {\n const p = (parent ?? \"\").trim();\n const c = (child ?? \"\").trim();\n if (!p) return c;\n if (!c) return p;\n return `${p} > ${c}`;\n}\n\nfunction isCollapsibleContainer(t: Test): boolean {\n return !(t.passed || t.failed || t.skipped || t.pending);\n}\n\n// Re-deriving a collapsed/filtered node invalidates any cached summary; drop it\n// so callers re-roll-up from the surviving children.\nfunction withoutSummary(t: Test): Omit<Test, \"summary\"> & { summary?: never } {\n const { summary: _summary, ...rest } = t;\n return rest;\n}\n\nfunction collapseNode(t: Test): Test {\n const children = t.children ?? [];\n if (children.length === 0) return t;\n\n const collapsedChildren = children.map(collapseNode);\n\n const onlyChild = collapsedChildren.length === 1 ? collapsedChildren[0] : undefined;\n if (onlyChild && isCollapsibleContainer(t)) {\n return { ...withoutSummary(onlyChild), name: joinChainNames(t.name, onlyChild.name) };\n }\n\n return { ...t, children: collapsedChildren };\n}\n\n/**\n * Compress any status-less container with exactly one child into that child,\n * joining names with \" > \". Recursive, so chains collapse into a single row.\n */\nexport function collapseSingleChildChains(tests: Test[]): Test[] {\n return tests.map(collapseNode);\n}\n\nfunction matchesLeaf(\n t: Test,\n statusFilter: FilterState<string>,\n frameworkFilter: FilterState<string>,\n): boolean {\n const s = testStatus(t);\n if (s === null) return false;\n return matchesFilterState(s, statusFilter) && matchesFilterState(t.framework, frameworkFilter);\n}\n\nfunction filterNode(\n t: Test,\n statusFilter: FilterState<string>,\n frameworkFilter: FilterState<string>,\n): Test | null {\n if (t.children && t.children.length > 0) {\n const filtered = t.children\n .map((c) => filterNode(c, statusFilter, frameworkFilter))\n .filter(Boolean) as Test[];\n if (filtered.length === 0) return null;\n return { ...withoutSummary(t), children: filtered };\n }\n return matchesLeaf(t, statusFilter, frameworkFilter) ? t : null;\n}\n\n/** Prune leaves not matching the status/framework filters; drop empty branches. */\nexport function filterTests(\n tests: Test[],\n statusFilter: FilterState<string>,\n frameworkFilter: FilterState<string>,\n): Test[] {\n if (statusFilter.size === 0 && frameworkFilter.size === 0) return tests;\n return tests\n .map((t) => filterNode(t, statusFilter, frameworkFilter))\n .filter(Boolean) as Test[];\n}\n"],"names":["r"],"mappings":"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"}
@@ -1,27 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
- const utils = require("../../lib/utils.cjs");
5
- const Icon = require("../Icon.cjs");
6
4
  const JsonView = require("../JsonView.cjs");
7
5
  const TestFailureDetail = require("../test-runner/TestFailureDetail.cjs");
8
- const UiPause = require("../../icons/components/UiPause.cjs");
9
- const UiError = require("../../icons/components/UiError.cjs");
10
- const UiPass = require("../../icons/components/UiPass.cjs");
11
- function checklistItemState(item) {
6
+ const MarkIcons = require("../test-runner/MarkIcons.cjs");
7
+ const Expectation = require("../test-runner/Expectation.cjs");
8
+ function checklistItemOutcome(item) {
12
9
  if (item.failed) return "failed";
13
10
  if (item.passed) return "passed";
14
11
  return "pending";
15
12
  }
16
- const CHECKLIST_ICONS = {
17
- passed: { icon: UiPass.UiPass, tone: "text-emerald-600" },
18
- failed: { icon: UiError.UiError, tone: "text-red-600" },
19
- pending: { icon: UiPause.UiPause, tone: "text-muted-foreground" }
20
- };
21
13
  function ChecklistItemRow({ item }) {
22
- const { icon, tone } = CHECKLIST_ICONS[checklistItemState(item)];
23
14
  return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-1.5 text-xs", children: [
24
- /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon, className: utils.cn("mt-0.5 shrink-0 text-sm", tone) }),
15
+ /* @__PURE__ */ jsxRuntime.jsx(MarkIcons.OutcomeIcon, { outcome: checklistItemOutcome(item), className: "mt-0.5 text-sm" }),
25
16
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0", children: [
26
17
  item.name,
27
18
  item.message ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-[11px] text-muted-foreground", children: item.message }) : null
@@ -45,42 +36,26 @@ function comparisonValue(hasCelGate, value) {
45
36
  if (value !== null && typeof value === "object" && !Array.isArray(value)) return void 0;
46
37
  return value;
47
38
  }
48
- function formatCelValue(value) {
49
- if (typeof value === "string") return value;
50
- try {
51
- return JSON.stringify(value);
52
- } catch {
53
- return String(value);
54
- }
55
- }
56
39
  function CelDetails({ node }) {
57
40
  if (node.passed) return null;
58
41
  const context = node.context;
59
- const vars = Object.entries((context == null ? void 0 : context.cel_vars) ?? {});
42
+ const vars = (context == null ? void 0 : context.cel_vars) ?? {};
60
43
  const expression = readCelTrace(node.detail) || (context == null ? void 0 : context.cel_expression);
61
44
  const hasCelGate = !!expression;
62
45
  const expected = comparisonValue(hasCelGate, context == null ? void 0 : context.expected);
63
46
  const actual = comparisonValue(hasCelGate, context == null ? void 0 : context.actual);
64
47
  const hasComparison = expected !== void 0 || actual !== void 0;
65
- if (!expression && vars.length === 0 && !hasComparison) return null;
66
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 rounded border border-border bg-muted/30 px-2 py-1.5", children: [
67
- expression && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
68
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase text-muted-foreground", children: "expression" }),
69
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "block overflow-x-auto whitespace-pre text-[11px]", children: expression })
70
- ] }),
71
- vars.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("table", { className: "w-full table-fixed text-[11px]", children: /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: vars.map(([name, value]) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "align-top", children: [
72
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "w-1/3 truncate pr-2 font-medium text-muted-foreground", children: name }),
73
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "break-words font-mono", children: formatCelValue(value) })
74
- ] }, name)) }) }),
75
- expected !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[11px]", children: [
76
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "expected " }),
77
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: formatCelValue(expected) })
78
- ] }),
79
- actual !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[11px]", children: [
80
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "actual " }),
81
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: formatCelValue(actual) })
82
- ] })
83
- ] });
48
+ if (!expression && Object.keys(vars).length === 0 && !hasComparison) return null;
49
+ return /* @__PURE__ */ jsxRuntime.jsx(
50
+ Expectation.Expectation,
51
+ {
52
+ check: expression,
53
+ checkLabel: "expression",
54
+ vars,
55
+ expected,
56
+ actual
57
+ }
58
+ );
84
59
  }
85
60
  function FixtureDetail({ node }) {
86
61
  const context = node.context;
@@ -1 +1 @@
1
- {"version":3,"file":"adapterViews.cjs","sources":["../../../src/data/verification/adapterViews.tsx"],"sourcesContent":["// Detail-body components for the verification node adapters. Split from\n// adapters.ts (react/only-export-components: a file mixing component\n// declarations with the plain TestNodeAdapter/registry exports loses Fast\n// Refresh). Ported from gavel's VerificationStepOutput.tsx (the checklist list\n// and the CelDetails block).\n\nimport { cn } from \"../../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"../Icon\";\nimport { UiError, UiPass, UiPause } from \"../../icons\";\nimport { JsonView } from \"../JsonView\";\nimport { TestOutput, type Test, type FixtureContext } from \"../test-runner\";\n\n// ── Checklist: the synthesized \"Acceptance criteria\" node and its items ────\n\ntype ChecklistState = \"passed\" | \"failed\" | \"pending\";\n\nfunction checklistItemState(item: Test): ChecklistState {\n if (item.failed) return \"failed\";\n if (item.passed) return \"passed\";\n return \"pending\";\n}\n\nconst CHECKLIST_ICONS: Record<ChecklistState, { icon: StaticIconComponent; tone: string }> = {\n passed: { icon: UiPass, tone: \"text-emerald-600\" },\n failed: { icon: UiError, tone: \"text-red-600\" },\n pending: { icon: UiPause, tone: \"text-muted-foreground\" },\n};\n\nfunction ChecklistItemRow({ item }: { item: Test }) {\n const { icon, tone } = CHECKLIST_ICONS[checklistItemState(item)];\n return (\n <li className=\"flex items-start gap-1.5 text-xs\">\n <Icon icon={icon} className={cn(\"mt-0.5 shrink-0 text-sm\", tone)} />\n <span className=\"min-w-0\">\n {item.name}\n {item.message ? (\n <span className=\"block text-[11px] text-muted-foreground\">{item.message}</span>\n ) : null}\n </span>\n </li>\n );\n}\n\n/** Renders every checklist item for the \"Acceptance criteria\" parent, or the\n * single item itself when a leaf criterion is selected directly. */\nexport function ChecklistDetail({ node }: { node: Test }) {\n const items = node.children && node.children.length > 0 ? node.children : [node];\n return (\n <div className=\"space-y-2 p-density-4\">\n <ul className=\"space-y-1\">\n {items.map((item, index) => (\n <ChecklistItemRow key={item.task_id ?? index} item={item} />\n ))}\n </ul>\n </div>\n );\n}\n\n// ── Fixture / CEL: the failing-step detail (command + CelDetails) ──────────\n\nfunction readCelTrace(detail: unknown): string | undefined {\n if (detail && typeof detail === \"object\" && !Array.isArray(detail)) {\n const value = (detail as Record<string, unknown>).cel_trace;\n if (typeof value === \"string\" && value.length > 0) return value;\n }\n return undefined;\n}\n\n// A command step with no CEL assertion stores the whole command result object\n// in `actual` — the command/output is already rendered above, so dumping it\n// again as JSON is noise. Anything a CEL expression compared is shown as-is,\n// structured values included. `hasCelGate` mirrors gavel's own gate: a plain\n// `context.cel_expression`, or a trace recorded in `node.detail` when the\n// expression itself wasn't preserved on `context`.\nfunction comparisonValue(hasCelGate: boolean, value: unknown): unknown {\n if (value === undefined) return undefined;\n if (hasCelGate) return value;\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) return undefined;\n return value;\n}\n\nfunction formatCelValue(value: unknown): string {\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\n// CEL detail is rendered only for a failing node: the expression and the\n// values it saw are what explain the verdict.\nexport function CelDetails({ node }: { node: Test }) {\n if (node.passed) return null;\n const context = node.context as FixtureContext | undefined;\n const vars = Object.entries(context?.cel_vars ?? {});\n const expression = readCelTrace(node.detail) || context?.cel_expression;\n const hasCelGate = !!expression;\n const expected = comparisonValue(hasCelGate, context?.expected);\n const actual = comparisonValue(hasCelGate, context?.actual);\n const hasComparison = expected !== undefined || actual !== undefined;\n if (!expression && vars.length === 0 && !hasComparison) return null;\n return (\n <div className=\"space-y-1 rounded border border-border bg-muted/30 px-2 py-1.5\">\n {expression && (\n <div>\n <span className=\"text-[10px] uppercase text-muted-foreground\">expression</span>\n <code className=\"block overflow-x-auto whitespace-pre text-[11px]\">{expression}</code>\n </div>\n )}\n {vars.length > 0 && (\n <table className=\"w-full table-fixed text-[11px]\">\n <tbody>\n {vars.map(([name, value]) => (\n <tr key={name} className=\"align-top\">\n <td className=\"w-1/3 truncate pr-2 font-medium text-muted-foreground\">{name}</td>\n <td className=\"break-words font-mono\">{formatCelValue(value)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )}\n {expected !== undefined && (\n <div className=\"text-[11px]\">\n <span className=\"text-muted-foreground\">expected </span>\n <span className=\"font-mono\">{formatCelValue(expected)}</span>\n </div>\n )}\n {actual !== undefined && (\n <div className=\"text-[11px]\">\n <span className=\"text-muted-foreground\">actual </span>\n <span className=\"font-mono\">{formatCelValue(actual)}</span>\n </div>\n )}\n </div>\n );\n}\n\nexport function FixtureDetail({ node }: { node: Test }) {\n const context = node.context as FixtureContext | undefined;\n const command = context?.command ?? node.command;\n const cwd = context?.cwd ?? node.work_dir;\n return (\n <div className=\"space-y-4 p-density-4\">\n {node.message && (\n <p className=\"whitespace-pre-wrap break-words text-sm\">{node.message}</p>\n )}\n {command && (\n <div className=\"min-w-0 space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Command</div>\n <code className=\"block overflow-x-auto whitespace-pre rounded bg-muted px-2 py-1.5 text-xs\">\n {command}\n </code>\n <div className=\"flex flex-wrap items-center gap-2 text-[10px] text-muted-foreground\">\n {cwd && <span>in {cwd}</span>}\n {typeof context?.exit_code === \"number\" && (\n <span className={context.exit_code === 0 ? undefined : \"text-red-600\"}>\n exit {context.exit_code}\n </span>\n )}\n </div>\n </div>\n )}\n <TestOutput node={node} />\n <CelDetails node={node} />\n {node.detail != null && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Detail</div>\n <JsonView data={node.detail} />\n </div>\n )}\n </div>\n );\n}\n"],"names":["UiPass","UiError","UiPause","jsxs","jsx","Icon","cn","TestOutput","JsonView"],"mappings":"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"}
1
+ {"version":3,"file":"adapterViews.cjs","sources":["../../../src/data/verification/adapterViews.tsx"],"sourcesContent":["// Detail-body components for the verification node adapters. Split from\n// adapters.ts (react/only-export-components: a file mixing component\n// declarations with the plain TestNodeAdapter/registry exports loses Fast\n// Refresh). Ported from gavel's VerificationStepOutput.tsx (the checklist list\n// and the CelDetails block).\n\nimport { JsonView } from \"../JsonView\";\nimport {\n Expectation,\n OutcomeIcon,\n TestOutput,\n type FixtureContext,\n type Test,\n type TestOutcome,\n} from \"../test-runner\";\n\n// ── Checklist: the synthesized \"Acceptance criteria\" node and its items ────\n\nfunction checklistItemOutcome(item: Test): TestOutcome {\n if (item.failed) return \"failed\";\n if (item.passed) return \"passed\";\n return \"pending\";\n}\n\nfunction ChecklistItemRow({ item }: { item: Test }) {\n return (\n <li className=\"flex items-start gap-1.5 text-xs\">\n <OutcomeIcon outcome={checklistItemOutcome(item)} className=\"mt-0.5 text-sm\" />\n <span className=\"min-w-0\">\n {item.name}\n {item.message ? (\n <span className=\"block text-[11px] text-muted-foreground\">{item.message}</span>\n ) : null}\n </span>\n </li>\n );\n}\n\n/** Renders every checklist item for the \"Acceptance criteria\" parent, or the\n * single item itself when a leaf criterion is selected directly. */\nexport function ChecklistDetail({ node }: { node: Test }) {\n const items = node.children && node.children.length > 0 ? node.children : [node];\n return (\n <div className=\"space-y-2 p-density-4\">\n <ul className=\"space-y-1\">\n {items.map((item, index) => (\n <ChecklistItemRow key={item.task_id ?? index} item={item} />\n ))}\n </ul>\n </div>\n );\n}\n\n// ── Fixture / CEL: the failing-step detail (command + CelDetails) ──────────\n\nfunction readCelTrace(detail: unknown): string | undefined {\n if (detail && typeof detail === \"object\" && !Array.isArray(detail)) {\n const value = (detail as Record<string, unknown>).cel_trace;\n if (typeof value === \"string\" && value.length > 0) return value;\n }\n return undefined;\n}\n\n// A command step with no CEL assertion stores the whole command result object\n// in `actual` — the command/output is already rendered above, so dumping it\n// again as JSON is noise. Anything a CEL expression compared is shown as-is,\n// structured values included. `hasCelGate` mirrors gavel's own gate: a plain\n// `context.cel_expression`, or a trace recorded in `node.detail` when the\n// expression itself wasn't preserved on `context`.\nfunction comparisonValue(hasCelGate: boolean, value: unknown): unknown {\n if (value === undefined) return undefined;\n if (hasCelGate) return value;\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) return undefined;\n return value;\n}\n\n// CEL detail is rendered only for a failing node: the expression and the\n// values it saw are what explain the verdict.\nexport function CelDetails({ node }: { node: Test }) {\n if (node.passed) return null;\n const context = node.context as FixtureContext | undefined;\n const vars = context?.cel_vars ?? {};\n const expression = readCelTrace(node.detail) || context?.cel_expression;\n const hasCelGate = !!expression;\n const expected = comparisonValue(hasCelGate, context?.expected);\n const actual = comparisonValue(hasCelGate, context?.actual);\n const hasComparison = expected !== undefined || actual !== undefined;\n if (!expression && Object.keys(vars).length === 0 && !hasComparison) return null;\n return (\n <Expectation\n check={expression}\n checkLabel=\"expression\"\n vars={vars}\n expected={expected}\n actual={actual}\n />\n );\n}\n\nexport function FixtureDetail({ node }: { node: Test }) {\n const context = node.context as FixtureContext | undefined;\n const command = context?.command ?? node.command;\n const cwd = context?.cwd ?? node.work_dir;\n return (\n <div className=\"space-y-4 p-density-4\">\n {node.message && (\n <p className=\"whitespace-pre-wrap break-words text-sm\">{node.message}</p>\n )}\n {command && (\n <div className=\"min-w-0 space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Command</div>\n <code className=\"block overflow-x-auto whitespace-pre rounded bg-muted px-2 py-1.5 text-xs\">\n {command}\n </code>\n <div className=\"flex flex-wrap items-center gap-2 text-[10px] text-muted-foreground\">\n {cwd && <span>in {cwd}</span>}\n {typeof context?.exit_code === \"number\" && (\n <span className={context.exit_code === 0 ? undefined : \"text-red-600\"}>\n exit {context.exit_code}\n </span>\n )}\n </div>\n </div>\n )}\n <TestOutput node={node} />\n <CelDetails node={node} />\n {node.detail != null && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Detail</div>\n <JsonView data={node.detail} />\n </div>\n )}\n </div>\n );\n}\n"],"names":["jsxs","jsx","OutcomeIcon","Expectation","TestOutput","JsonView"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"adapterViews.d.ts","sourceRoot":"","sources":["../../../src/data/verification/adapterViews.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAc,KAAK,IAAI,EAAuB,MAAM,gBAAgB,CAAC;AAiC5E;qEACqE;AACrE,wBAAgB,eAAe,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,+BAWvD;AAoCD,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,sCA4ClD;AAED,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,+BAmCrD"}
1
+ {"version":3,"file":"adapterViews.d.ts","sourceRoot":"","sources":["../../../src/data/verification/adapterViews.tsx"],"names":[],"mappings":"AAOA,OAAO,EAKL,KAAK,IAAI,EAEV,MAAM,gBAAgB,CAAC;AAwBxB;qEACqE;AACrE,wBAAgB,eAAe,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,+BAWvD;AA2BD,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,sCAmBlD;AAED,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,+BAmCrD"}
@@ -1,25 +1,16 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { cn } from "../../lib/utils.js";
3
- import { Icon } from "../Icon.js";
4
2
  import { JsonView } from "../JsonView.js";
5
3
  import { TestOutput } from "../test-runner/TestFailureDetail.js";
6
- import { UiPause } from "../../icons/components/UiPause.js";
7
- import { UiError } from "../../icons/components/UiError.js";
8
- import { UiPass } from "../../icons/components/UiPass.js";
9
- function checklistItemState(item) {
4
+ import { OutcomeIcon } from "../test-runner/MarkIcons.js";
5
+ import { Expectation } from "../test-runner/Expectation.js";
6
+ function checklistItemOutcome(item) {
10
7
  if (item.failed) return "failed";
11
8
  if (item.passed) return "passed";
12
9
  return "pending";
13
10
  }
14
- const CHECKLIST_ICONS = {
15
- passed: { icon: UiPass, tone: "text-emerald-600" },
16
- failed: { icon: UiError, tone: "text-red-600" },
17
- pending: { icon: UiPause, tone: "text-muted-foreground" }
18
- };
19
11
  function ChecklistItemRow({ item }) {
20
- const { icon, tone } = CHECKLIST_ICONS[checklistItemState(item)];
21
12
  return /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-1.5 text-xs", children: [
22
- /* @__PURE__ */ jsx(Icon, { icon, className: cn("mt-0.5 shrink-0 text-sm", tone) }),
13
+ /* @__PURE__ */ jsx(OutcomeIcon, { outcome: checklistItemOutcome(item), className: "mt-0.5 text-sm" }),
23
14
  /* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
24
15
  item.name,
25
16
  item.message ? /* @__PURE__ */ jsx("span", { className: "block text-[11px] text-muted-foreground", children: item.message }) : null
@@ -43,42 +34,26 @@ function comparisonValue(hasCelGate, value) {
43
34
  if (value !== null && typeof value === "object" && !Array.isArray(value)) return void 0;
44
35
  return value;
45
36
  }
46
- function formatCelValue(value) {
47
- if (typeof value === "string") return value;
48
- try {
49
- return JSON.stringify(value);
50
- } catch {
51
- return String(value);
52
- }
53
- }
54
37
  function CelDetails({ node }) {
55
38
  if (node.passed) return null;
56
39
  const context = node.context;
57
- const vars = Object.entries((context == null ? void 0 : context.cel_vars) ?? {});
40
+ const vars = (context == null ? void 0 : context.cel_vars) ?? {};
58
41
  const expression = readCelTrace(node.detail) || (context == null ? void 0 : context.cel_expression);
59
42
  const hasCelGate = !!expression;
60
43
  const expected = comparisonValue(hasCelGate, context == null ? void 0 : context.expected);
61
44
  const actual = comparisonValue(hasCelGate, context == null ? void 0 : context.actual);
62
45
  const hasComparison = expected !== void 0 || actual !== void 0;
63
- if (!expression && vars.length === 0 && !hasComparison) return null;
64
- return /* @__PURE__ */ jsxs("div", { className: "space-y-1 rounded border border-border bg-muted/30 px-2 py-1.5", children: [
65
- expression && /* @__PURE__ */ jsxs("div", { children: [
66
- /* @__PURE__ */ jsx("span", { className: "text-[10px] uppercase text-muted-foreground", children: "expression" }),
67
- /* @__PURE__ */ jsx("code", { className: "block overflow-x-auto whitespace-pre text-[11px]", children: expression })
68
- ] }),
69
- vars.length > 0 && /* @__PURE__ */ jsx("table", { className: "w-full table-fixed text-[11px]", children: /* @__PURE__ */ jsx("tbody", { children: vars.map(([name, value]) => /* @__PURE__ */ jsxs("tr", { className: "align-top", children: [
70
- /* @__PURE__ */ jsx("td", { className: "w-1/3 truncate pr-2 font-medium text-muted-foreground", children: name }),
71
- /* @__PURE__ */ jsx("td", { className: "break-words font-mono", children: formatCelValue(value) })
72
- ] }, name)) }) }),
73
- expected !== void 0 && /* @__PURE__ */ jsxs("div", { className: "text-[11px]", children: [
74
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "expected " }),
75
- /* @__PURE__ */ jsx("span", { className: "font-mono", children: formatCelValue(expected) })
76
- ] }),
77
- actual !== void 0 && /* @__PURE__ */ jsxs("div", { className: "text-[11px]", children: [
78
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "actual " }),
79
- /* @__PURE__ */ jsx("span", { className: "font-mono", children: formatCelValue(actual) })
80
- ] })
81
- ] });
46
+ if (!expression && Object.keys(vars).length === 0 && !hasComparison) return null;
47
+ return /* @__PURE__ */ jsx(
48
+ Expectation,
49
+ {
50
+ check: expression,
51
+ checkLabel: "expression",
52
+ vars,
53
+ expected,
54
+ actual
55
+ }
56
+ );
82
57
  }
83
58
  function FixtureDetail({ node }) {
84
59
  const context = node.context;
@@ -1 +1 @@
1
- {"version":3,"file":"adapterViews.js","sources":["../../../src/data/verification/adapterViews.tsx"],"sourcesContent":["// Detail-body components for the verification node adapters. Split from\n// adapters.ts (react/only-export-components: a file mixing component\n// declarations with the plain TestNodeAdapter/registry exports loses Fast\n// Refresh). Ported from gavel's VerificationStepOutput.tsx (the checklist list\n// and the CelDetails block).\n\nimport { cn } from \"../../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"../Icon\";\nimport { UiError, UiPass, UiPause } from \"../../icons\";\nimport { JsonView } from \"../JsonView\";\nimport { TestOutput, type Test, type FixtureContext } from \"../test-runner\";\n\n// ── Checklist: the synthesized \"Acceptance criteria\" node and its items ────\n\ntype ChecklistState = \"passed\" | \"failed\" | \"pending\";\n\nfunction checklistItemState(item: Test): ChecklistState {\n if (item.failed) return \"failed\";\n if (item.passed) return \"passed\";\n return \"pending\";\n}\n\nconst CHECKLIST_ICONS: Record<ChecklistState, { icon: StaticIconComponent; tone: string }> = {\n passed: { icon: UiPass, tone: \"text-emerald-600\" },\n failed: { icon: UiError, tone: \"text-red-600\" },\n pending: { icon: UiPause, tone: \"text-muted-foreground\" },\n};\n\nfunction ChecklistItemRow({ item }: { item: Test }) {\n const { icon, tone } = CHECKLIST_ICONS[checklistItemState(item)];\n return (\n <li className=\"flex items-start gap-1.5 text-xs\">\n <Icon icon={icon} className={cn(\"mt-0.5 shrink-0 text-sm\", tone)} />\n <span className=\"min-w-0\">\n {item.name}\n {item.message ? (\n <span className=\"block text-[11px] text-muted-foreground\">{item.message}</span>\n ) : null}\n </span>\n </li>\n );\n}\n\n/** Renders every checklist item for the \"Acceptance criteria\" parent, or the\n * single item itself when a leaf criterion is selected directly. */\nexport function ChecklistDetail({ node }: { node: Test }) {\n const items = node.children && node.children.length > 0 ? node.children : [node];\n return (\n <div className=\"space-y-2 p-density-4\">\n <ul className=\"space-y-1\">\n {items.map((item, index) => (\n <ChecklistItemRow key={item.task_id ?? index} item={item} />\n ))}\n </ul>\n </div>\n );\n}\n\n// ── Fixture / CEL: the failing-step detail (command + CelDetails) ──────────\n\nfunction readCelTrace(detail: unknown): string | undefined {\n if (detail && typeof detail === \"object\" && !Array.isArray(detail)) {\n const value = (detail as Record<string, unknown>).cel_trace;\n if (typeof value === \"string\" && value.length > 0) return value;\n }\n return undefined;\n}\n\n// A command step with no CEL assertion stores the whole command result object\n// in `actual` — the command/output is already rendered above, so dumping it\n// again as JSON is noise. Anything a CEL expression compared is shown as-is,\n// structured values included. `hasCelGate` mirrors gavel's own gate: a plain\n// `context.cel_expression`, or a trace recorded in `node.detail` when the\n// expression itself wasn't preserved on `context`.\nfunction comparisonValue(hasCelGate: boolean, value: unknown): unknown {\n if (value === undefined) return undefined;\n if (hasCelGate) return value;\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) return undefined;\n return value;\n}\n\nfunction formatCelValue(value: unknown): string {\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\n// CEL detail is rendered only for a failing node: the expression and the\n// values it saw are what explain the verdict.\nexport function CelDetails({ node }: { node: Test }) {\n if (node.passed) return null;\n const context = node.context as FixtureContext | undefined;\n const vars = Object.entries(context?.cel_vars ?? {});\n const expression = readCelTrace(node.detail) || context?.cel_expression;\n const hasCelGate = !!expression;\n const expected = comparisonValue(hasCelGate, context?.expected);\n const actual = comparisonValue(hasCelGate, context?.actual);\n const hasComparison = expected !== undefined || actual !== undefined;\n if (!expression && vars.length === 0 && !hasComparison) return null;\n return (\n <div className=\"space-y-1 rounded border border-border bg-muted/30 px-2 py-1.5\">\n {expression && (\n <div>\n <span className=\"text-[10px] uppercase text-muted-foreground\">expression</span>\n <code className=\"block overflow-x-auto whitespace-pre text-[11px]\">{expression}</code>\n </div>\n )}\n {vars.length > 0 && (\n <table className=\"w-full table-fixed text-[11px]\">\n <tbody>\n {vars.map(([name, value]) => (\n <tr key={name} className=\"align-top\">\n <td className=\"w-1/3 truncate pr-2 font-medium text-muted-foreground\">{name}</td>\n <td className=\"break-words font-mono\">{formatCelValue(value)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n )}\n {expected !== undefined && (\n <div className=\"text-[11px]\">\n <span className=\"text-muted-foreground\">expected </span>\n <span className=\"font-mono\">{formatCelValue(expected)}</span>\n </div>\n )}\n {actual !== undefined && (\n <div className=\"text-[11px]\">\n <span className=\"text-muted-foreground\">actual </span>\n <span className=\"font-mono\">{formatCelValue(actual)}</span>\n </div>\n )}\n </div>\n );\n}\n\nexport function FixtureDetail({ node }: { node: Test }) {\n const context = node.context as FixtureContext | undefined;\n const command = context?.command ?? node.command;\n const cwd = context?.cwd ?? node.work_dir;\n return (\n <div className=\"space-y-4 p-density-4\">\n {node.message && (\n <p className=\"whitespace-pre-wrap break-words text-sm\">{node.message}</p>\n )}\n {command && (\n <div className=\"min-w-0 space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Command</div>\n <code className=\"block overflow-x-auto whitespace-pre rounded bg-muted px-2 py-1.5 text-xs\">\n {command}\n </code>\n <div className=\"flex flex-wrap items-center gap-2 text-[10px] text-muted-foreground\">\n {cwd && <span>in {cwd}</span>}\n {typeof context?.exit_code === \"number\" && (\n <span className={context.exit_code === 0 ? undefined : \"text-red-600\"}>\n exit {context.exit_code}\n </span>\n )}\n </div>\n </div>\n )}\n <TestOutput node={node} />\n <CelDetails node={node} />\n {node.detail != null && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Detail</div>\n <JsonView data={node.detail} />\n </div>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapterViews.js","sources":["../../../src/data/verification/adapterViews.tsx"],"sourcesContent":["// Detail-body components for the verification node adapters. Split from\n// adapters.ts (react/only-export-components: a file mixing component\n// declarations with the plain TestNodeAdapter/registry exports loses Fast\n// Refresh). Ported from gavel's VerificationStepOutput.tsx (the checklist list\n// and the CelDetails block).\n\nimport { JsonView } from \"../JsonView\";\nimport {\n Expectation,\n OutcomeIcon,\n TestOutput,\n type FixtureContext,\n type Test,\n type TestOutcome,\n} from \"../test-runner\";\n\n// ── Checklist: the synthesized \"Acceptance criteria\" node and its items ────\n\nfunction checklistItemOutcome(item: Test): TestOutcome {\n if (item.failed) return \"failed\";\n if (item.passed) return \"passed\";\n return \"pending\";\n}\n\nfunction ChecklistItemRow({ item }: { item: Test }) {\n return (\n <li className=\"flex items-start gap-1.5 text-xs\">\n <OutcomeIcon outcome={checklistItemOutcome(item)} className=\"mt-0.5 text-sm\" />\n <span className=\"min-w-0\">\n {item.name}\n {item.message ? (\n <span className=\"block text-[11px] text-muted-foreground\">{item.message}</span>\n ) : null}\n </span>\n </li>\n );\n}\n\n/** Renders every checklist item for the \"Acceptance criteria\" parent, or the\n * single item itself when a leaf criterion is selected directly. */\nexport function ChecklistDetail({ node }: { node: Test }) {\n const items = node.children && node.children.length > 0 ? node.children : [node];\n return (\n <div className=\"space-y-2 p-density-4\">\n <ul className=\"space-y-1\">\n {items.map((item, index) => (\n <ChecklistItemRow key={item.task_id ?? index} item={item} />\n ))}\n </ul>\n </div>\n );\n}\n\n// ── Fixture / CEL: the failing-step detail (command + CelDetails) ──────────\n\nfunction readCelTrace(detail: unknown): string | undefined {\n if (detail && typeof detail === \"object\" && !Array.isArray(detail)) {\n const value = (detail as Record<string, unknown>).cel_trace;\n if (typeof value === \"string\" && value.length > 0) return value;\n }\n return undefined;\n}\n\n// A command step with no CEL assertion stores the whole command result object\n// in `actual` — the command/output is already rendered above, so dumping it\n// again as JSON is noise. Anything a CEL expression compared is shown as-is,\n// structured values included. `hasCelGate` mirrors gavel's own gate: a plain\n// `context.cel_expression`, or a trace recorded in `node.detail` when the\n// expression itself wasn't preserved on `context`.\nfunction comparisonValue(hasCelGate: boolean, value: unknown): unknown {\n if (value === undefined) return undefined;\n if (hasCelGate) return value;\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) return undefined;\n return value;\n}\n\n// CEL detail is rendered only for a failing node: the expression and the\n// values it saw are what explain the verdict.\nexport function CelDetails({ node }: { node: Test }) {\n if (node.passed) return null;\n const context = node.context as FixtureContext | undefined;\n const vars = context?.cel_vars ?? {};\n const expression = readCelTrace(node.detail) || context?.cel_expression;\n const hasCelGate = !!expression;\n const expected = comparisonValue(hasCelGate, context?.expected);\n const actual = comparisonValue(hasCelGate, context?.actual);\n const hasComparison = expected !== undefined || actual !== undefined;\n if (!expression && Object.keys(vars).length === 0 && !hasComparison) return null;\n return (\n <Expectation\n check={expression}\n checkLabel=\"expression\"\n vars={vars}\n expected={expected}\n actual={actual}\n />\n );\n}\n\nexport function FixtureDetail({ node }: { node: Test }) {\n const context = node.context as FixtureContext | undefined;\n const command = context?.command ?? node.command;\n const cwd = context?.cwd ?? node.work_dir;\n return (\n <div className=\"space-y-4 p-density-4\">\n {node.message && (\n <p className=\"whitespace-pre-wrap break-words text-sm\">{node.message}</p>\n )}\n {command && (\n <div className=\"min-w-0 space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Command</div>\n <code className=\"block overflow-x-auto whitespace-pre rounded bg-muted px-2 py-1.5 text-xs\">\n {command}\n </code>\n <div className=\"flex flex-wrap items-center gap-2 text-[10px] text-muted-foreground\">\n {cwd && <span>in {cwd}</span>}\n {typeof context?.exit_code === \"number\" && (\n <span className={context.exit_code === 0 ? undefined : \"text-red-600\"}>\n exit {context.exit_code}\n </span>\n )}\n </div>\n </div>\n )}\n <TestOutput node={node} />\n <CelDetails node={node} />\n {node.detail != null && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Detail</div>\n <JsonView data={node.detail} />\n </div>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -3,24 +3,136 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const adapterViews = require("./adapterViews.cjs");
5
5
  const adapter = require("../test-runner/adapter.cjs");
6
+ const UiTerminal = require("../../icons/components/UiTerminal.cjs");
7
+ const status = require("../test-runner/status.cjs");
6
8
  function isChecklistNode(node) {
7
9
  return node.framework === "checklist";
8
10
  }
11
+ function checklistMark(item) {
12
+ if (item.failed) return "[ ]";
13
+ if (item.passed) return "[x]";
14
+ return "[?]";
15
+ }
16
+ function checklistCopy(node) {
17
+ const items = node.children && node.children.length > 0 ? node.children : [node];
18
+ const lines = items.map(
19
+ (item) => `- ${checklistMark(item)} ${item.name}${item.message ? ` — ${item.message}` : ""}`
20
+ );
21
+ return { brief: [{ title: "Criteria", body: lines.join("\n") }] };
22
+ }
9
23
  const checklistAdapter = {
10
24
  id: "verification-checklist",
11
25
  match: isChecklistNode,
12
- renderDetail: ({ node }) => /* @__PURE__ */ jsxRuntime.jsx(adapterViews.ChecklistDetail, { node })
26
+ renderDetail: ({ node }) => /* @__PURE__ */ jsxRuntime.jsx(adapterViews.ChecklistDetail, { node }),
27
+ copy: ({ node }) => checklistCopy(node)
13
28
  };
14
29
  function isFixtureNode(node) {
15
30
  return node.context !== void 0;
16
31
  }
32
+ function readCelTrace(detail) {
33
+ if (detail && typeof detail === "object" && !Array.isArray(detail)) {
34
+ const value = detail.cel_trace;
35
+ if (typeof value === "string" && value.length > 0) return value;
36
+ }
37
+ return void 0;
38
+ }
39
+ function comparisonValue(hasCelGate, value) {
40
+ if (value === void 0) return void 0;
41
+ if (hasCelGate) return value;
42
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) return void 0;
43
+ return value;
44
+ }
45
+ function formatValue(value) {
46
+ return typeof value === "string" ? value : JSON.stringify(value, null, 2);
47
+ }
48
+ function commandSection(node, context) {
49
+ const command = (context == null ? void 0 : context.command) ?? node.command;
50
+ if (!command) return [];
51
+ const cwd = (context == null ? void 0 : context.cwd) ?? node.work_dir;
52
+ const exit = context == null ? void 0 : context.exit_code;
53
+ const lines = [`$ ${command}`, cwd && `cwd: ${cwd}`, exit !== void 0 && `exit: ${exit}`];
54
+ return [{ title: "Command", lang: "sh", body: lines.filter(Boolean).join("\n") }];
55
+ }
56
+ function assertionSection(node, context) {
57
+ const expression = context == null ? void 0 : context.cel_expression;
58
+ const trace = readCelTrace(node.detail);
59
+ const hasCelGate = !!(expression || trace);
60
+ const vars = (context == null ? void 0 : context.cel_vars) ?? {};
61
+ const expected = comparisonValue(hasCelGate, context == null ? void 0 : context.expected);
62
+ const actual = comparisonValue(hasCelGate, context == null ? void 0 : context.actual);
63
+ const lines = [
64
+ expression && `expression: ${expression}`,
65
+ trace && `trace:
66
+ ${trace}`,
67
+ Object.keys(vars).length > 0 && `vars: ${formatValue(vars)}`,
68
+ expected !== void 0 && `expected: ${formatValue(expected)}`,
69
+ actual !== void 0 && `actual: ${formatValue(actual)}`
70
+ ].filter(Boolean);
71
+ return lines.length > 0 ? [{ title: "Assertion", body: lines.join("\n") }] : [];
72
+ }
73
+ const OUTCOME_GLYPH = {
74
+ passed: "✓",
75
+ failed: "✗",
76
+ errored: "✗",
77
+ timedout: "⏱",
78
+ warned: "!",
79
+ skipped: "-",
80
+ pending: "○",
81
+ running: "…"
82
+ };
83
+ function childLine(child) {
84
+ var _a;
85
+ const outcome = status.outcomeFor(child);
86
+ const exit = (_a = child.context) == null ? void 0 : _a.exit_code;
87
+ const reason = child.message ?? (exit ? `exit ${exit}` : void 0);
88
+ return `${outcome ? OUTCOME_GLYPH[outcome] : "·"} ${child.name}${reason ? ` — ${reason}` : ""}`;
89
+ }
90
+ function summaryLine(summary) {
91
+ const counts = [
92
+ [summary.Passed, "passed"],
93
+ [summary.Failed, "failed"],
94
+ [summary.Warned, "warned"],
95
+ [summary.Timedout, "timed out"],
96
+ [summary.Skipped, "skipped"],
97
+ [summary.Pending, "pending"],
98
+ [summary.Running, "running"]
99
+ ];
100
+ const parts = counts.filter(([n]) => !!n).map(([n, label]) => `${n} ${label}`);
101
+ return [`${summary.Total} total`, ...parts].join(" · ");
102
+ }
103
+ function resultsSection(node) {
104
+ const lines = [
105
+ ...node.summary ? [summaryLine(node.summary)] : [],
106
+ ...(node.children ?? []).map(childLine)
107
+ ];
108
+ return lines.length > 0 ? [{ title: "Results", body: lines.join("\n") }] : [];
109
+ }
110
+ function fixtureCopy(node) {
111
+ const context = node.context;
112
+ const command = (context == null ? void 0 : context.command) ?? node.command;
113
+ return {
114
+ brief: [
115
+ ...commandSection(node, context),
116
+ ...assertionSection(node, context),
117
+ ...resultsSection(node)
118
+ ],
119
+ items: command ? [{ label: "Copy command", icon: UiTerminal.UiTerminal, value: command }] : []
120
+ };
121
+ }
17
122
  const fixtureAdapter = {
18
123
  id: "verification-fixture",
19
124
  match: isFixtureNode,
20
- renderDetail: ({ node }) => /* @__PURE__ */ jsxRuntime.jsx(adapterViews.FixtureDetail, { node })
125
+ renderDetail: ({ node }) => /* @__PURE__ */ jsxRuntime.jsx(adapterViews.FixtureDetail, { node }),
126
+ copy: ({ node }) => fixtureCopy(node)
127
+ };
128
+ const FIXTURE_STEP_FRAMEWORKS = /* @__PURE__ */ new Set(["exec", "query", "fixture", "test", "lint", "verify"]);
129
+ const fixtureStepCopyAdapter = {
130
+ id: "verification-step-copy",
131
+ match: (node) => FIXTURE_STEP_FRAMEWORKS.has(node.framework ?? ""),
132
+ copy: ({ node }) => fixtureCopy(node)
21
133
  };
22
134
  function verificationAdapters() {
23
- return adapter.createTestRunnerRegistry([checklistAdapter, fixtureAdapter]);
135
+ return adapter.createTestRunnerRegistry([checklistAdapter, fixtureAdapter, fixtureStepCopyAdapter]);
24
136
  }
25
137
  exports.verificationAdapters = verificationAdapters;
26
138
  //# sourceMappingURL=adapters.cjs.map