@cccsaurora/howler-ui 3.1.0-dev.1656 → 3.1.0-dev.1675

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 (353) hide show
  1. package/api/action/execute.test.d.ts +1 -0
  2. package/api/action/execute.test.js +38 -0
  3. package/api/action/index.test.d.ts +1 -0
  4. package/api/action/index.test.js +59 -0
  5. package/api/action/operations.test.d.ts +1 -0
  6. package/api/action/operations.test.js +23 -0
  7. package/api/analytic/comments/index.test.d.ts +1 -0
  8. package/api/analytic/comments/index.test.js +43 -0
  9. package/api/analytic/comments/react.test.d.ts +1 -0
  10. package/api/analytic/comments/react.test.js +27 -0
  11. package/api/analytic/favourite.test.d.ts +1 -0
  12. package/api/analytic/favourite.test.js +20 -0
  13. package/api/analytic/index.test.d.ts +1 -0
  14. package/api/analytic/index.test.js +54 -0
  15. package/api/analytic/notebooks/index.test.d.ts +1 -0
  16. package/api/analytic/notebooks/index.test.js +31 -0
  17. package/api/analytic/owner.test.d.ts +1 -0
  18. package/api/analytic/owner.test.js +25 -0
  19. package/api/auth/apikey.test.d.ts +1 -0
  20. package/api/auth/apikey.test.js +34 -0
  21. package/api/auth/index.test.d.ts +1 -0
  22. package/api/auth/index.test.js +21 -0
  23. package/api/auth/login.test.d.ts +1 -0
  24. package/api/auth/login.test.js +53 -0
  25. package/api/configs/index.test.d.ts +1 -0
  26. package/api/configs/index.test.js +22 -0
  27. package/api/dossier/index.test.d.ts +1 -0
  28. package/api/dossier/index.test.js +57 -0
  29. package/api/help.test.d.ts +1 -0
  30. package/api/help.test.js +25 -0
  31. package/api/hit/assign.test.d.ts +1 -0
  32. package/api/hit/assign.test.js +22 -0
  33. package/api/hit/comments/index.test.d.ts +1 -0
  34. package/api/hit/comments/index.test.js +47 -0
  35. package/api/hit/comments/react.test.d.ts +1 -0
  36. package/api/hit/comments/react.test.js +27 -0
  37. package/api/hit/index.test.d.ts +1 -0
  38. package/api/hit/index.test.js +49 -0
  39. package/api/hit/labels.test.d.ts +1 -0
  40. package/api/hit/labels.test.js +29 -0
  41. package/api/hit/overwrite.test.d.ts +1 -0
  42. package/api/hit/overwrite.test.js +23 -0
  43. package/api/hit/transition.test.d.ts +1 -0
  44. package/api/hit/transition.test.js +24 -0
  45. package/api/index.test.d.ts +1 -0
  46. package/api/index.test.js +137 -0
  47. package/api/notebook/environments.test.d.ts +1 -0
  48. package/api/notebook/environments.test.js +22 -0
  49. package/api/notebook/index.test.d.ts +1 -0
  50. package/api/notebook/index.test.js +28 -0
  51. package/api/overview/index.test.d.ts +1 -0
  52. package/api/overview/index.test.js +42 -0
  53. package/api/search/fields/index.test.d.ts +1 -0
  54. package/api/search/fields/index.test.js +31 -0
  55. package/api/search/grouped/index.test.d.ts +1 -0
  56. package/api/search/grouped/index.test.js +18 -0
  57. package/api/search/grouped/user.test.d.ts +1 -0
  58. package/api/search/grouped/user.test.js +33 -0
  59. package/api/search/index.test.d.ts +1 -0
  60. package/api/search/index.test.js +41 -0
  61. package/api/search/user.test.d.ts +1 -0
  62. package/api/search/user.test.js +41 -0
  63. package/api/socket/index.test.d.ts +1 -0
  64. package/api/socket/index.test.js +15 -0
  65. package/api/template/index.test.d.ts +1 -0
  66. package/api/template/index.test.js +43 -0
  67. package/api/user/avatar/index.test.d.ts +1 -0
  68. package/api/user/avatar/index.test.js +22 -0
  69. package/api/user/groups.test.d.ts +1 -0
  70. package/api/user/groups.test.js +22 -0
  71. package/api/user/index.test.d.ts +1 -0
  72. package/api/user/index.test.js +37 -0
  73. package/api/user/whoami.test.d.ts +1 -0
  74. package/api/user/whoami.test.js +26 -0
  75. package/api/utils/createPermissionsApi.test.d.ts +1 -0
  76. package/api/utils/createPermissionsApi.test.js +30 -0
  77. package/api/v2/case/index.test.d.ts +1 -0
  78. package/api/v2/case/index.test.js +57 -0
  79. package/api/v2/case/items.test.d.ts +1 -0
  80. package/api/v2/case/items.test.js +37 -0
  81. package/api/v2/case/rules.test.d.ts +1 -0
  82. package/api/v2/case/rules.test.js +33 -0
  83. package/api/v2/fuzzy.test.d.ts +1 -0
  84. package/api/v2/fuzzy.test.js +30 -0
  85. package/api/v2/index.test.d.ts +1 -0
  86. package/api/v2/index.test.js +13 -0
  87. package/api/v2/search/index.test.d.ts +1 -0
  88. package/api/v2/search/index.test.js +42 -0
  89. package/api/view/index.test.d.ts +1 -0
  90. package/api/view/index.test.js +54 -0
  91. package/branding/AppBrand.test.d.ts +1 -0
  92. package/branding/AppBrand.test.js +29 -0
  93. package/components/app/drawers/ApiKeyDrawer.test.d.ts +1 -0
  94. package/components/app/drawers/ApiKeyDrawer.test.js +119 -0
  95. package/components/app/drawers/AssignUserDrawer.test.d.ts +1 -0
  96. package/components/app/drawers/AssignUserDrawer.test.js +75 -0
  97. package/components/app/hooks/useTitle.test.d.ts +1 -0
  98. package/components/app/hooks/useTitle.test.js +103 -0
  99. package/components/app/providers/AnalyticProvider.test.d.ts +1 -0
  100. package/components/app/providers/AnalyticProvider.test.js +58 -0
  101. package/components/app/providers/AppBarProvider.test.d.ts +1 -0
  102. package/components/app/providers/AppBarProvider.test.js +23 -0
  103. package/components/app/providers/AppDrawerProvider.test.d.ts +1 -0
  104. package/components/app/providers/AppDrawerProvider.test.js +42 -0
  105. package/components/app/providers/AvatarProvider.test.d.ts +1 -0
  106. package/components/app/providers/AvatarProvider.test.js +50 -0
  107. package/components/app/providers/CustomPluginProvider.test.d.ts +1 -0
  108. package/components/app/providers/CustomPluginProvider.test.js +29 -0
  109. package/components/app/providers/FavouritesProvider.test.d.ts +1 -0
  110. package/components/app/providers/FavouritesProvider.test.js +115 -0
  111. package/components/app/providers/FieldProvider.test.d.ts +1 -0
  112. package/components/app/providers/FieldProvider.test.js +28 -0
  113. package/components/app/providers/LocalStorageProvider.test.d.ts +1 -0
  114. package/components/app/providers/LocalStorageProvider.test.js +42 -0
  115. package/components/app/providers/ModalProvider.test.d.ts +1 -0
  116. package/components/app/providers/ModalProvider.test.js +35 -0
  117. package/components/app/providers/OverviewProvider.test.d.ts +1 -0
  118. package/components/app/providers/OverviewProvider.test.js +62 -0
  119. package/components/app/providers/RecordProvider.test.d.ts +1 -0
  120. package/components/app/providers/RecordProvider.test.js +66 -0
  121. package/components/app/providers/contextUtils.test.d.ts +1 -0
  122. package/components/app/providers/contextUtils.test.js +8 -0
  123. package/components/elements/Comment.test.d.ts +1 -0
  124. package/components/elements/Comment.test.js +109 -0
  125. package/components/elements/EditRow.test.d.ts +1 -0
  126. package/components/elements/EditRow.test.js +88 -0
  127. package/components/elements/MarkdownEditor.test.d.ts +1 -0
  128. package/components/elements/MarkdownEditor.test.js +75 -0
  129. package/components/elements/ObjectDetails.test.d.ts +1 -0
  130. package/components/elements/ObjectDetails.test.js +70 -0
  131. package/components/elements/PluginChip.d.ts +3 -2
  132. package/components/elements/PluginChip.js +2 -2
  133. package/components/elements/PluginChip.test.d.ts +1 -0
  134. package/components/elements/PluginChip.test.js +30 -0
  135. package/components/elements/ThemedEditor.test.d.ts +1 -0
  136. package/components/elements/ThemedEditor.test.js +66 -0
  137. package/components/elements/addons/layout/FlexPort.test.d.ts +1 -0
  138. package/components/elements/addons/layout/FlexPort.test.js +34 -0
  139. package/components/elements/addons/lists/TuiListBase.test.d.ts +1 -0
  140. package/components/elements/addons/lists/TuiListBase.test.js +44 -0
  141. package/components/elements/addons/lists/TuiListProvider.test.d.ts +1 -0
  142. package/components/elements/addons/lists/TuiListProvider.test.js +50 -0
  143. package/components/elements/addons/search/phrase/Phrase.test.d.ts +1 -0
  144. package/components/elements/addons/search/phrase/Phrase.test.js +77 -0
  145. package/components/elements/addons/search/phrase/PhraseLexer.test.d.ts +1 -0
  146. package/components/elements/addons/search/phrase/PhraseLexer.test.js +92 -0
  147. package/components/elements/addons/search/phrase/index.test.d.ts +1 -0
  148. package/components/elements/addons/search/phrase/index.test.js +20 -0
  149. package/components/elements/case/CaseCard.test.d.ts +1 -0
  150. package/components/elements/case/CaseCard.test.js +107 -0
  151. package/components/elements/display/ClassificationChip.test.d.ts +1 -0
  152. package/components/elements/display/ClassificationChip.test.js +60 -0
  153. package/components/elements/display/HandlebarsMarkdown.test.d.ts +1 -0
  154. package/components/elements/display/HandlebarsMarkdown.test.js +41 -0
  155. package/components/elements/display/HowlerAvatar.test.d.ts +1 -0
  156. package/components/elements/display/HowlerAvatar.test.js +54 -0
  157. package/components/elements/display/ItemManager.test.d.ts +1 -0
  158. package/components/elements/display/ItemManager.test.js +68 -0
  159. package/components/elements/display/UserPageWrapper.test.d.ts +1 -0
  160. package/components/elements/display/UserPageWrapper.test.js +22 -0
  161. package/components/elements/display/handlebars/helpers.test.d.ts +1 -0
  162. package/components/elements/display/handlebars/helpers.test.js +104 -0
  163. package/components/elements/display/icons/SocketBadge.test.d.ts +1 -0
  164. package/components/elements/display/icons/SocketBadge.test.js +49 -0
  165. package/components/elements/display/markdownPlugins/tabs.test.d.ts +1 -0
  166. package/components/elements/display/markdownPlugins/tabs.test.js +50 -0
  167. package/components/elements/hit/HitActions.js +1 -1
  168. package/components/elements/hit/HitActions.test.d.ts +1 -0
  169. package/components/elements/hit/HitActions.test.js +166 -0
  170. package/components/elements/hit/HitLabels.test.js +34 -3
  171. package/components/elements/hit/HitNotebooks.test.d.ts +1 -0
  172. package/components/elements/hit/HitNotebooks.test.js +138 -0
  173. package/components/elements/hit/HitSummary.test.d.ts +1 -0
  174. package/components/elements/hit/HitSummary.test.js +188 -0
  175. package/components/elements/hit/actions/ButtonActions.test.d.ts +1 -0
  176. package/components/elements/hit/actions/ButtonActions.test.js +51 -0
  177. package/components/elements/hit/actions/DropdownActions.test.d.ts +1 -0
  178. package/components/elements/hit/actions/DropdownActions.test.js +60 -0
  179. package/components/elements/hit/grid/AddColumnModal.test.d.ts +1 -0
  180. package/components/elements/hit/grid/AddColumnModal.test.js +88 -0
  181. package/components/elements/hit/grid/RecordTable.test.d.ts +1 -0
  182. package/components/elements/hit/grid/RecordTable.test.js +99 -0
  183. package/components/elements/record/RecordComments.test.d.ts +1 -0
  184. package/components/elements/record/RecordComments.test.js +151 -0
  185. package/components/elements/record/RecordRelated.test.d.ts +1 -0
  186. package/components/elements/record/RecordRelated.test.js +77 -0
  187. package/components/elements/record/RecordWorklog.test.d.ts +1 -0
  188. package/components/elements/record/RecordWorklog.test.js +77 -0
  189. package/components/hooks/useHitActions.test.d.ts +1 -0
  190. package/components/hooks/useHitActions.test.js +189 -0
  191. package/components/hooks/useMyApi.test.d.ts +1 -0
  192. package/components/hooks/useMyApi.test.js +31 -0
  193. package/components/hooks/useMyChart.test.d.ts +1 -0
  194. package/components/hooks/useMyChart.test.js +62 -0
  195. package/components/hooks/useMySearch.test.d.ts +1 -0
  196. package/components/hooks/useMySearch.test.js +96 -0
  197. package/components/hooks/useMySnackbar.test.d.ts +1 -0
  198. package/components/hooks/useMySnackbar.test.js +36 -0
  199. package/components/hooks/useMyUserFunctions.test.d.ts +1 -0
  200. package/components/hooks/useMyUserFunctions.test.js +142 -0
  201. package/components/hooks/useRecordSelection.test.d.ts +1 -0
  202. package/components/hooks/useRecordSelection.test.js +102 -0
  203. package/components/logins/Login.test.d.ts +1 -0
  204. package/components/logins/Login.test.js +67 -0
  205. package/components/logins/hooks/useLogin.test.d.ts +1 -0
  206. package/components/logins/hooks/useLogin.test.js +142 -0
  207. package/components/routes/action/shared/OperationEntry.test.d.ts +1 -0
  208. package/components/routes/action/shared/OperationEntry.test.js +80 -0
  209. package/components/routes/action/shared/OperationStep.test.d.ts +1 -0
  210. package/components/routes/action/shared/OperationStep.test.js +84 -0
  211. package/components/routes/action/useMyActionFunctions.test.d.ts +1 -0
  212. package/components/routes/action/useMyActionFunctions.test.js +217 -0
  213. package/components/routes/action/view/ActionDetails.test.d.ts +1 -0
  214. package/components/routes/action/view/ActionDetails.test.js +170 -0
  215. package/components/routes/action/view/ActionSearch.test.d.ts +1 -0
  216. package/components/routes/action/view/ActionSearch.test.js +185 -0
  217. package/components/routes/action/view/Integrations.test.d.ts +1 -0
  218. package/components/routes/action/view/Integrations.test.js +62 -0
  219. package/components/routes/admin/users/UserEditor.test.d.ts +1 -0
  220. package/components/routes/admin/users/UserEditor.test.js +74 -0
  221. package/components/routes/admin/users/UserSearch.test.d.ts +1 -0
  222. package/components/routes/admin/users/UserSearch.test.js +146 -0
  223. package/components/routes/advanced/QueryBuilder.test.d.ts +1 -0
  224. package/components/routes/advanced/QueryBuilder.test.js +185 -0
  225. package/components/routes/advanced/QueryEditor.test.d.ts +1 -0
  226. package/components/routes/advanced/QueryEditor.test.js +130 -0
  227. package/components/routes/advanced/completionProviders.test.d.ts +1 -0
  228. package/components/routes/advanced/completionProviders.test.js +144 -0
  229. package/components/routes/analytics/AnalyticComments.test.d.ts +1 -0
  230. package/components/routes/analytics/AnalyticComments.test.js +156 -0
  231. package/components/routes/analytics/AnalyticDetails.test.d.ts +1 -0
  232. package/components/routes/analytics/AnalyticDetails.test.js +161 -0
  233. package/components/routes/analytics/AnalyticNotebooks.test.d.ts +1 -0
  234. package/components/routes/analytics/AnalyticNotebooks.test.js +112 -0
  235. package/components/routes/analytics/AnalyticOverview.test.d.ts +1 -0
  236. package/components/routes/analytics/AnalyticOverview.test.js +97 -0
  237. package/components/routes/analytics/AnalyticOverviews.test.d.ts +1 -0
  238. package/components/routes/analytics/AnalyticOverviews.test.js +70 -0
  239. package/components/routes/analytics/AnalyticSearch.test.d.ts +1 -0
  240. package/components/routes/analytics/AnalyticSearch.test.js +167 -0
  241. package/components/routes/analytics/AnalyticTemplates.test.d.ts +1 -0
  242. package/components/routes/analytics/AnalyticTemplates.test.js +63 -0
  243. package/components/routes/analytics/TriageSettings.test.d.ts +1 -0
  244. package/components/routes/analytics/TriageSettings.test.js +89 -0
  245. package/components/routes/analytics/widgets/Assessment.test.d.ts +1 -0
  246. package/components/routes/analytics/widgets/Assessment.test.js +45 -0
  247. package/components/routes/analytics/widgets/Created.test.d.ts +1 -0
  248. package/components/routes/analytics/widgets/Created.test.js +41 -0
  249. package/components/routes/analytics/widgets/DetectionStatus.test.d.ts +1 -0
  250. package/components/routes/analytics/widgets/DetectionStatus.test.js +21 -0
  251. package/components/routes/analytics/widgets/Stacked.test.d.ts +1 -0
  252. package/components/routes/analytics/widgets/Stacked.test.js +51 -0
  253. package/components/routes/cases/Cases.test.d.ts +1 -0
  254. package/components/routes/cases/Cases.test.js +132 -0
  255. package/components/routes/dossiers/Dossiers.test.d.ts +1 -0
  256. package/components/routes/dossiers/Dossiers.test.js +150 -0
  257. package/components/routes/help/ActionDocumentation.test.d.ts +1 -0
  258. package/components/routes/help/ActionDocumentation.test.js +58 -0
  259. package/components/routes/help/ActionIntroductionDocumentation.test.d.ts +1 -0
  260. package/components/routes/help/ActionIntroductionDocumentation.test.js +68 -0
  261. package/components/routes/help/ApiDocumentation.test.d.ts +1 -0
  262. package/components/routes/help/ApiDocumentation.test.js +79 -0
  263. package/components/routes/help/AuthDocumentation.test.d.ts +1 -0
  264. package/components/routes/help/AuthDocumentation.test.js +34 -0
  265. package/components/routes/help/ClientDocumentation.test.d.ts +1 -0
  266. package/components/routes/help/ClientDocumentation.test.js +34 -0
  267. package/components/routes/help/Help.test.d.ts +1 -0
  268. package/components/routes/help/Help.test.js +57 -0
  269. package/components/routes/help/HitBannerDocumentation.test.d.ts +1 -0
  270. package/components/routes/help/HitBannerDocumentation.test.js +25 -0
  271. package/components/routes/help/HitDocumentation.test.d.ts +1 -0
  272. package/components/routes/help/HitDocumentation.test.js +53 -0
  273. package/components/routes/help/HitLabelsDocumentation.test.d.ts +1 -0
  274. package/components/routes/help/HitLabelsDocumentation.test.js +17 -0
  275. package/components/routes/help/HitLinksDocumentation.test.d.ts +1 -0
  276. package/components/routes/help/HitLinksDocumentation.test.js +27 -0
  277. package/components/routes/help/HitSchemaDocumentation.test.d.ts +1 -0
  278. package/components/routes/help/HitSchemaDocumentation.test.js +67 -0
  279. package/components/routes/help/NotebookDocumentation.test.d.ts +1 -0
  280. package/components/routes/help/NotebookDocumentation.test.js +34 -0
  281. package/components/routes/help/OverviewDocumentation.test.d.ts +1 -0
  282. package/components/routes/help/OverviewDocumentation.test.js +26 -0
  283. package/components/routes/help/RetentionDocumentation.test.d.ts +1 -0
  284. package/components/routes/help/RetentionDocumentation.test.js +61 -0
  285. package/components/routes/help/SearchDocumentation.test.d.ts +1 -0
  286. package/components/routes/help/SearchDocumentation.test.js +65 -0
  287. package/components/routes/help/TemplateDocumentation.test.d.ts +1 -0
  288. package/components/routes/help/TemplateDocumentation.test.js +58 -0
  289. package/components/routes/help/ViewDocumentation.test.d.ts +1 -0
  290. package/components/routes/help/ViewDocumentation.test.js +34 -0
  291. package/components/routes/help/components/HelpTabs.test.d.ts +1 -0
  292. package/components/routes/help/components/HelpTabs.test.js +26 -0
  293. package/components/routes/hits/search/InformationPane.test.d.ts +1 -0
  294. package/components/routes/hits/search/InformationPane.test.js +251 -0
  295. package/components/routes/hits/search/RecordBrowser.test.js +179 -51
  296. package/components/routes/hits/search/RecordQuery.test.d.ts +1 -0
  297. package/components/routes/hits/search/RecordQuery.test.js +117 -0
  298. package/components/routes/hits/search/SearchPane.test.d.ts +1 -0
  299. package/components/routes/hits/search/SearchPane.test.js +178 -0
  300. package/components/routes/hits/search/grid/RecordGrid.test.d.ts +1 -0
  301. package/components/routes/hits/search/grid/RecordGrid.test.js +107 -0
  302. package/components/routes/hits/search/shared/CustomSort.test.d.ts +1 -0
  303. package/components/routes/hits/search/shared/CustomSort.test.js +77 -0
  304. package/components/routes/hits/search/shared/HitFilter.test.d.ts +1 -0
  305. package/components/routes/hits/search/shared/HitFilter.test.js +83 -0
  306. package/components/routes/hits/search/shared/HitSort.test.d.ts +1 -0
  307. package/components/routes/hits/search/shared/HitSort.test.js +61 -0
  308. package/components/routes/hits/search/shared/LayoutSettings.test.d.ts +1 -0
  309. package/components/routes/hits/search/shared/LayoutSettings.test.js +84 -0
  310. package/components/routes/hits/search/shared/SearchSpan.test.d.ts +1 -0
  311. package/components/routes/hits/search/shared/SearchSpan.test.js +84 -0
  312. package/components/routes/home/AnalyticCard.test.d.ts +1 -0
  313. package/components/routes/home/AnalyticCard.test.js +87 -0
  314. package/components/routes/home/index.test.d.ts +1 -0
  315. package/components/routes/home/index.test.js +190 -0
  316. package/components/routes/overviews/OverviewViewer.test.d.ts +1 -0
  317. package/components/routes/overviews/OverviewViewer.test.js +151 -0
  318. package/components/routes/overviews/Overviews.test.d.ts +1 -0
  319. package/components/routes/overviews/Overviews.test.js +154 -0
  320. package/components/routes/settings/AdminSection.test.d.ts +1 -0
  321. package/components/routes/settings/AdminSection.test.js +26 -0
  322. package/components/routes/settings/LocalSection.test.d.ts +1 -0
  323. package/components/routes/settings/LocalSection.test.js +75 -0
  324. package/components/routes/settings/ProfileSection.test.d.ts +1 -0
  325. package/components/routes/settings/ProfileSection.test.js +95 -0
  326. package/components/routes/settings/SecuritySection.test.d.ts +1 -0
  327. package/components/routes/settings/SecuritySection.test.js +90 -0
  328. package/components/routes/settings/Settings.test.d.ts +1 -0
  329. package/components/routes/settings/Settings.test.js +60 -0
  330. package/components/routes/templates/TemplateEditor.test.d.ts +1 -0
  331. package/components/routes/templates/TemplateEditor.test.js +94 -0
  332. package/components/routes/templates/TemplateViewer.test.d.ts +1 -0
  333. package/components/routes/templates/TemplateViewer.test.js +145 -0
  334. package/components/routes/templates/Templates.test.d.ts +1 -0
  335. package/components/routes/templates/Templates.test.js +165 -0
  336. package/components/routes/views/ViewComposer.test.d.ts +1 -0
  337. package/components/routes/views/ViewComposer.test.js +320 -0
  338. package/components/routes/views/Views.test.d.ts +1 -0
  339. package/components/routes/views/Views.test.js +247 -0
  340. package/package.json +2 -2
  341. package/plugins/HowlerPlugin.test.d.ts +1 -0
  342. package/plugins/HowlerPlugin.test.js +103 -0
  343. package/plugins/clue/components/ClueChip.js +2 -2
  344. package/plugins/clue/helpers.test.d.ts +1 -0
  345. package/plugins/clue/helpers.test.js +100 -0
  346. package/plugins/store.test.d.ts +1 -0
  347. package/plugins/store.test.js +53 -0
  348. package/utils/classificationParser.test.d.ts +1 -0
  349. package/utils/classificationParser.test.js +199 -0
  350. package/utils/constants.test.d.ts +1 -0
  351. package/utils/constants.test.js +62 -0
  352. package/utils/typeUtils.test.d.ts +1 -0
  353. package/utils/typeUtils.test.js +22 -0
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /// <reference types="vitest" />
3
+ import { act, render, screen } from '@testing-library/react';
4
+ import { useContext } from 'react';
5
+ import { describe, expect, it, vi } from 'vitest';
6
+ const mockDispatchApi = vi.hoisted(() => vi.fn());
7
+ vi.mock('api', () => ({
8
+ default: { search: { fields: { hit: { get: () => ({}) } } } }
9
+ }));
10
+ vi.mock('components/hooks/useMyApi', () => ({
11
+ default: () => ({ dispatchApi: mockDispatchApi })
12
+ }));
13
+ import FieldProvider, { FieldContext } from './FieldProvider';
14
+ const Consumer = () => {
15
+ const ctx = useContext(FieldContext);
16
+ return (_jsxs("div", { children: [_jsx("button", { onClick: () => void ctx.getHitFields(), children: "load" }), _jsx("span", { children: ctx.hitFields.length })] }));
17
+ };
18
+ describe('FieldProvider', () => {
19
+ it('loads hit fields once and reuses the cached value', async () => {
20
+ mockDispatchApi.mockResolvedValue([{ name: 'field-a' }]);
21
+ render(_jsx(FieldProvider, { children: _jsx(Consumer, {}) }));
22
+ await act(async () => screen.getByText('load').click());
23
+ expect(mockDispatchApi).toHaveBeenCalledTimes(1);
24
+ expect(screen.getByText('1')).toBeInTheDocument();
25
+ await act(async () => screen.getByText('load').click());
26
+ expect(mockDispatchApi).toHaveBeenCalledTimes(1);
27
+ });
28
+ });
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /// <reference types="vitest" />
3
+ import { act, renderHook, waitFor } from '@testing-library/react';
4
+ import { useContext } from 'react';
5
+ import { describe, expect, it, vi } from 'vitest';
6
+ import { StorageKey } from '@cccsaurora/howler-ui/utils/constants';
7
+ const mockGetStored = vi.hoisted(() => vi.fn());
8
+ const mockSetStored = vi.hoisted(() => vi.fn());
9
+ const mockRemoveStored = vi.hoisted(() => vi.fn());
10
+ vi.mock('components/hooks/useLocalStorage', () => ({
11
+ default: () => ({
12
+ get: mockGetStored,
13
+ set: mockSetStored,
14
+ remove: mockRemoveStored
15
+ })
16
+ }));
17
+ import LocalStorageProvider, { LocalStorageContext } from './LocalStorageProvider';
18
+ describe('LocalStorageProvider', () => {
19
+ it('hydrates values, updates stored state, and removes keys', async () => {
20
+ mockGetStored.mockImplementation((key) => {
21
+ if (key === StorageKey.PAGE_COUNT)
22
+ return 25;
23
+ if (key === StorageKey.NEXT_LOCATION)
24
+ return '/hits';
25
+ return undefined;
26
+ });
27
+ const wrapper = ({ children }) => _jsx(LocalStorageProvider, { children: children });
28
+ const { result } = renderHook(() => useContext(LocalStorageContext), { wrapper });
29
+ await waitFor(() => expect(result.current.values[StorageKey.PAGE_COUNT]).toBe(25));
30
+ expect(result.current.values[StorageKey.NEXT_LOCATION]).toBe('/hits');
31
+ act(() => {
32
+ result.current.set(StorageKey.PAGE_COUNT, 50);
33
+ });
34
+ expect(mockSetStored).toHaveBeenCalledWith(StorageKey.PAGE_COUNT, 50);
35
+ expect(result.current.values[StorageKey.PAGE_COUNT]).toBe(50);
36
+ act(() => {
37
+ result.current.remove(StorageKey.PAGE_COUNT);
38
+ });
39
+ expect(mockRemoveStored).toHaveBeenCalledWith(StorageKey.PAGE_COUNT);
40
+ expect(result.current.values[StorageKey.PAGE_COUNT]).toBeUndefined();
41
+ });
42
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /// <reference types="vitest" />
3
+ import { act, fireEvent, render, screen } from '@testing-library/react';
4
+ import { useContext } from 'react';
5
+ import { describe, expect, it, vi } from 'vitest';
6
+ vi.mock('components/elements/display/modals/ConfirmDeleteModal', () => ({
7
+ default: ({ onConfirm, preferDelete, preferCancel }) => (_jsx("button", { onClick: onConfirm, children: `confirm:${String(preferDelete)}:${String(preferCancel)}` }))
8
+ }));
9
+ import ModalProvider, { ModalContext } from './ModalProvider';
10
+ const Consumer = () => {
11
+ const modal = useContext(ModalContext);
12
+ return (_jsxs("div", { children: [_jsx("button", { onClick: () => modal.showModal(_jsx("div", { children: "modal-body" }), { disableClose: true, maxWidth: 'xl' }), children: "show" }), _jsx("button", { onClick: () => modal.withConfirmDeleteModal(vi.fn(), true, false), children: "confirm-wrapper" }), _jsx("button", { onClick: () => modal.close(), children: "close" }), _jsx("div", { children: String(modal.options?.disableClose) }), _jsx("div", { children: modal.content })] }));
13
+ };
14
+ describe('ModalProvider', () => {
15
+ it('shows modal content, resets options, and closes', async () => {
16
+ render(_jsx(ModalProvider, { children: _jsx(Consumer, {}) }));
17
+ fireEvent.click(screen.getByText('show'));
18
+ expect(screen.getByText('modal-body')).toBeInTheDocument();
19
+ expect(screen.getAllByText('true')[0]).toBeInTheDocument();
20
+ fireEvent.click(screen.getByText('close'));
21
+ await act(async () => { });
22
+ expect(screen.queryByText('modal-body')).not.toBeInTheDocument();
23
+ });
24
+ it('builds confirm-delete modal wrappers', () => {
25
+ const onConfirm = vi.fn();
26
+ const TestConsumer = () => {
27
+ const modal = useContext(ModalContext);
28
+ return (_jsxs("div", { children: [_jsx("button", { onClick: () => modal.withConfirmDeleteModal(onConfirm, true, false), children: "show-confirm" }), _jsx("div", { children: modal.content })] }));
29
+ };
30
+ render(_jsx(ModalProvider, { children: _jsx(TestConsumer, {}) }));
31
+ fireEvent.click(screen.getByText('show-confirm'));
32
+ fireEvent.click(screen.getByText('confirm:true:false'));
33
+ expect(onConfirm).toHaveBeenCalled();
34
+ });
35
+ });
@@ -0,0 +1,62 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /// <reference types="vitest" />
3
+ import { act, renderHook, waitFor } from '@testing-library/react';
4
+ import { useContext } from 'react';
5
+ import { setupContextSelectorMock } from '@cccsaurora/howler-ui/tests/mocks';
6
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
7
+ setupContextSelectorMock();
8
+ const mockOverviewGet = vi.hoisted(() => vi.fn());
9
+ vi.mock('api', () => ({
10
+ default: {
11
+ overview: {
12
+ get: mockOverviewGet
13
+ }
14
+ }
15
+ }));
16
+ import OverviewProvider, { OverviewContext } from './OverviewProvider';
17
+ describe('OverviewProvider', () => {
18
+ const wrapper = ({ children }) => _jsx(OverviewProvider, { children: children });
19
+ beforeEach(() => {
20
+ mockOverviewGet.mockReset();
21
+ });
22
+ it('loads and caches overviews until forced to refresh', async () => {
23
+ const dataset = [
24
+ { overview_id: '1', analytic: 'a1' },
25
+ { overview_id: '2', analytic: 'a2', detection: 'Phishing' }
26
+ ];
27
+ mockOverviewGet.mockResolvedValue(dataset);
28
+ const { result } = renderHook(() => useContext(OverviewContext), { wrapper });
29
+ await act(async () => {
30
+ await expect(result.current.getOverviews()).resolves.toEqual(dataset);
31
+ });
32
+ await waitFor(() => expect(result.current.loaded).toBe(true));
33
+ expect(mockOverviewGet).toHaveBeenCalledTimes(1);
34
+ await act(async () => {
35
+ await expect(result.current.getOverviews()).resolves.toEqual(dataset);
36
+ });
37
+ expect(mockOverviewGet).toHaveBeenCalledTimes(1);
38
+ await act(async () => {
39
+ await expect(result.current.getOverviews(true)).resolves.toEqual(dataset);
40
+ });
41
+ expect(mockOverviewGet).toHaveBeenCalledTimes(2);
42
+ });
43
+ it('matches the most specific overview for a hit and can refresh state', async () => {
44
+ mockOverviewGet.mockResolvedValue([
45
+ { overview_id: 'generic', analytic: 'analytic-1' },
46
+ { overview_id: 'specific', analytic: 'analytic-1', detection: 'Malware' }
47
+ ]);
48
+ const { result } = renderHook(() => useContext(OverviewContext), { wrapper });
49
+ await act(async () => {
50
+ await result.current.getOverviews();
51
+ });
52
+ expect(result.current.getMatchingOverview({ howler: { analytic: 'analytic-1', detection: 'malware' } })).toMatchObject({ overview_id: 'specific' });
53
+ expect(result.current.getMatchingOverview({ howler: { analytic: 'analytic-1' } })).toMatchObject({
54
+ overview_id: 'generic'
55
+ });
56
+ mockOverviewGet.mockResolvedValueOnce([{ overview_id: 'refreshed', analytic: 'analytic-2' }]);
57
+ act(() => {
58
+ result.current.refresh();
59
+ });
60
+ await waitFor(() => expect(mockOverviewGet).toHaveBeenCalledTimes(2));
61
+ });
62
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,66 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /// <reference types="vitest" />
3
+ import { act, render, screen, waitFor } from '@testing-library/react';
4
+ import { describe, expect, it, vi } from 'vitest';
5
+ const socketContextToken = vi.hoisted(() => ({ name: 'socket-context' }));
6
+ const mockDispatchApi = vi.hoisted(() => vi.fn());
7
+ const mockAddListener = vi.hoisted(() => vi.fn());
8
+ const mockRemoveListener = vi.hoisted(() => vi.fn());
9
+ vi.mock('api', () => ({
10
+ default: {
11
+ v2: {
12
+ search: {
13
+ post: (_indexes, body) => body
14
+ }
15
+ }
16
+ }
17
+ }));
18
+ vi.mock('components/hooks/useMyApi', () => ({
19
+ default: () => ({ dispatchApi: mockDispatchApi })
20
+ }));
21
+ vi.mock('./SocketProvider', () => ({
22
+ SocketContext: socketContextToken
23
+ }));
24
+ vi.mock('react', async (importOriginal) => {
25
+ const actual = await importOriginal();
26
+ return {
27
+ ...actual,
28
+ useContext: (context) => {
29
+ if (context === socketContextToken) {
30
+ return { addListener: mockAddListener, removeListener: mockRemoveListener };
31
+ }
32
+ return actual.useContext(context);
33
+ }
34
+ };
35
+ });
36
+ import RecordProvider, { useRecordContextSelector } from './RecordProvider';
37
+ const Consumer = () => {
38
+ const records = useRecordContextSelector(ctx => ctx.records);
39
+ const selected = useRecordContextSelector(ctx => ctx.selectedRecords);
40
+ const loadRecords = useRecordContextSelector(ctx => ctx.loadRecords);
41
+ const updateRecord = useRecordContextSelector(ctx => ctx.updateRecord);
42
+ const getRecord = useRecordContextSelector(ctx => ctx.getRecord);
43
+ const addRecordToSelection = useRecordContextSelector(ctx => ctx.addRecordToSelection);
44
+ const removeRecordFromSelection = useRecordContextSelector(ctx => ctx.removeRecordFromSelection);
45
+ const clearSelectedRecords = useRecordContextSelector(ctx => ctx.clearSelectedRecords);
46
+ return (_jsxs("div", { children: [_jsx("button", { onClick: () => loadRecords([{ howler: { id: 'h1' } }, { howler: { id: 'h2' } }]), children: "load" }), _jsx("button", { onClick: () => updateRecord({ howler: { id: 'h2' }, updated: true }), children: "update" }), _jsx("button", { onClick: () => addRecordToSelection('h1'), children: "select-one" }), _jsx("button", { onClick: () => addRecordToSelection('missing'), children: "select-missing" }), _jsx("button", { onClick: () => removeRecordFromSelection('h1'), children: "remove" }), _jsx("button", { onClick: () => clearSelectedRecords('h2'), children: "clear-except" }), _jsx("button", { onClick: () => void getRecord('missing').then(r => (document.body.dataset.record = r.howler.id)), children: "fetch" }), _jsx("span", { children: Object.keys(records).join(',') }), _jsx("span", { children: selected.map((item) => item.howler.id).join(',') })] }));
47
+ };
48
+ describe('RecordProvider', () => {
49
+ it('loads, updates, selects, and fetches records while wiring socket listeners', async () => {
50
+ mockDispatchApi.mockResolvedValue({ items: [{ howler: { id: 'missing' } }] });
51
+ render(_jsx(RecordProvider, { children: _jsx(Consumer, {}) }));
52
+ expect(mockAddListener).toHaveBeenCalledWith('hits', expect.any(Function));
53
+ await act(async () => screen.getByText('load').click());
54
+ expect(screen.getByText('h1,h2')).toBeInTheDocument();
55
+ await act(async () => screen.getByText('update').click());
56
+ await act(async () => screen.getByText('select-one').click());
57
+ expect(screen.getByText('h1')).toBeInTheDocument();
58
+ await act(async () => screen.getByText('select-missing').click());
59
+ await waitFor(() => expect(mockDispatchApi).toHaveBeenCalled());
60
+ await act(async () => screen.getByText('fetch').click());
61
+ expect(document.body.dataset.record).toBe('missing');
62
+ await act(async () => screen.getByText('clear-except').click());
63
+ expect(screen.getByText('h2')).toBeInTheDocument();
64
+ await act(async () => screen.getByText('remove').click());
65
+ });
66
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ /// <reference types="vitest" />
2
+ import { describe, expect, it } from 'vitest';
3
+ import { missingContext } from './contextUtils';
4
+ describe('missingContext', () => {
5
+ it('throws a provider-specific error', () => {
6
+ expect(() => missingContext('DemoContext')).toThrow('DemoContext must be used within its provider.');
7
+ });
8
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,109 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ /// <reference types="vitest" />
3
+ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
4
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
5
+ let currentUser = { username: 'author', is_admin: false };
6
+ vi.mock('@mui/icons-material', () => ({
7
+ Celebration: () => _jsx("div", { children: "confetti" }),
8
+ Check: () => _jsx("div", { children: "check" }),
9
+ Clear: () => _jsx("div", { children: "clear" }),
10
+ Delete: () => _jsx("div", { children: "delete" }),
11
+ Edit: () => _jsx("div", { children: "edit" }),
12
+ Favorite: () => _jsx("div", { children: "heart" }),
13
+ FireTruck: () => _jsx("div", { children: "fire" }),
14
+ FormatQuote: () => _jsx("div", { children: "quote" }),
15
+ Mood: () => _jsx("div", { children: "laugh" }),
16
+ MoreHoriz: () => _jsx("div", { children: "menu" }),
17
+ RocketLaunch: () => _jsx("div", { children: "rocket" }),
18
+ ThumbDown: () => _jsx("div", { children: "minus" }),
19
+ ThumbUp: () => _jsx("div", { children: "plus" })
20
+ }));
21
+ vi.mock('@mui/material', () => ({
22
+ CardActions: ({ children }) => _jsx("div", { children: children }),
23
+ CardContent: ({ children }) => _jsx("div", { children: children }),
24
+ Chip: ({ label, onClick }) => _jsx("button", { onClick: onClick, children: String(label ?? '') }),
25
+ CircularProgress: () => _jsx("div", { children: "loading" }),
26
+ Collapse: ({ children, in: open }) => (open ? _jsx("div", { children: children }) : null),
27
+ Fade: ({ children }) => _jsx(_Fragment, { children: children }),
28
+ IconButton: ({ children, onClick, disabled, id }) => (_jsx("button", { id: id, onClick: onClick, disabled: disabled, children: children })),
29
+ ListItemIcon: ({ children }) => _jsx("div", { children: children }),
30
+ ListItemText: ({ children }) => _jsx("div", { children: children }),
31
+ Menu: ({ children, open }) => (open ? _jsx("div", { children: children }) : null),
32
+ MenuItem: ({ children, onClick, disabled }) => (_jsx("button", { onClick: onClick, disabled: disabled, children: children })),
33
+ Stack: ({ children, onMouseEnter, onMouseLeave }) => (_jsx("div", { onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: children })),
34
+ TextField: ({ defaultValue, onChange, onKeyDown }) => (_jsx("textarea", { "aria-label": "comment-editor", defaultValue: defaultValue, onChange: onChange, onKeyDown: onKeyDown })),
35
+ Tooltip: ({ children }) => _jsx(_Fragment, { children: children }),
36
+ Typography: ({ children }) => _jsx("div", { children: children })
37
+ }));
38
+ vi.mock('@tui/core', () => ({
39
+ useAppUser: () => ({ user: currentUser })
40
+ }));
41
+ vi.mock('components/elements/addons/layout/FlexOne', () => ({
42
+ default: () => _jsx("div", { children: "flex-one" })
43
+ }));
44
+ vi.mock('components/hooks/useMyUtils', () => ({
45
+ default: () => ({ shiftColor: () => '#999' })
46
+ }));
47
+ vi.mock('react-i18next', () => ({
48
+ useTranslation: () => ({ t: (key) => key })
49
+ }));
50
+ vi.mock('utils/utils', () => ({
51
+ compareTimestamp: () => 2,
52
+ twitterShort: () => 'short-time'
53
+ }));
54
+ vi.mock('./display/HowlerAvatar', () => ({
55
+ default: ({ userId }) => _jsx("div", { children: `avatar-${userId}` })
56
+ }));
57
+ vi.mock('./display/HowlerCard', () => ({
58
+ default: ({ children, onClick, onMouseEnter, onMouseLeave }) => (_jsx("div", { onClick: onClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: children }))
59
+ }));
60
+ vi.mock('./display/Markdown', () => ({
61
+ default: ({ md }) => _jsx("div", { children: md })
62
+ }));
63
+ import Comment from './Comment';
64
+ describe('Comment', () => {
65
+ beforeEach(() => {
66
+ currentUser = { username: 'author', is_admin: false };
67
+ });
68
+ it('quotes and deletes a comment from the action menu', async () => {
69
+ const handleDelete = vi.fn().mockResolvedValue(undefined);
70
+ const handleQuote = vi.fn();
71
+ render(_jsx(Comment, { comment: {
72
+ id: 'c1',
73
+ user: 'author',
74
+ value: 'hello',
75
+ timestamp: '2026-01-01T00:00:00Z',
76
+ modified: '2026-01-02T00:00:00Z'
77
+ }, handleDelete: handleDelete, handleQuote: handleQuote, users: { author: { name: 'Author Name' } }, extra: _jsx("div", { children: "extra" }) }));
78
+ expect(screen.getByText('Author Name')).toBeInTheDocument();
79
+ expect(screen.getByText('comments.edited')).toBeInTheDocument();
80
+ expect(screen.getByText('hello')).toBeInTheDocument();
81
+ fireEvent.mouseEnter(screen.getByText('hello').closest('div'));
82
+ fireEvent.click(screen.getByText('menu'));
83
+ fireEvent.click(screen.getByText('comments.quote'));
84
+ expect(handleQuote).toHaveBeenCalled();
85
+ fireEvent.click(screen.getByText('menu'));
86
+ fireEvent.click(screen.getByText('comments.delete'));
87
+ await waitFor(() => expect(handleDelete).toHaveBeenCalled());
88
+ });
89
+ it('edits and reacts to a comment', async () => {
90
+ const handleEdit = vi.fn().mockResolvedValue(undefined);
91
+ const handleReact = vi.fn().mockResolvedValue(undefined);
92
+ render(_jsx(Comment, { comment: {
93
+ id: 'c2',
94
+ user: 'author',
95
+ value: 'old text',
96
+ timestamp: '2026-01-01T00:00:00Z',
97
+ modified: '2026-01-01T00:00:00Z',
98
+ reactions: { other: 'heart' }
99
+ }, handleEdit: handleEdit, handleReact: handleReact, users: { author: { name: 'Author Name' } } }));
100
+ fireEvent.mouseEnter(screen.getByText('old text').closest('div'));
101
+ fireEvent.click(screen.getByText('menu'));
102
+ fireEvent.click(screen.getByText('comments.edit'));
103
+ fireEvent.change(screen.getByLabelText('comment-editor'), { target: { value: 'new text' } });
104
+ fireEvent.keyDown(screen.getByLabelText('comment-editor'), { key: 'Enter', ctrlKey: true });
105
+ await waitFor(() => expect(handleEdit).toHaveBeenCalledWith('new text'));
106
+ fireEvent.click(screen.getByText('1'));
107
+ await waitFor(() => expect(handleReact).toHaveBeenCalledWith('heart'));
108
+ });
109
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,88 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /// <reference types="vitest" />
3
+ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
4
+ import { describe, expect, it, vi } from 'vitest';
5
+ const mockShowErrorMessage = vi.hoisted(() => vi.fn());
6
+ vi.mock('@mui/icons-material', async (importOriginal) => {
7
+ const actual = await importOriginal();
8
+ return {
9
+ ...actual,
10
+ Check: () => _jsx("div", { children: "check-icon" }),
11
+ Close: () => _jsx("div", { children: "close-icon" }),
12
+ Delete: () => _jsx("div", { children: "delete-icon" }),
13
+ Edit: () => _jsx("div", { children: "edit-icon" })
14
+ };
15
+ });
16
+ vi.mock('@mui/material', () => ({
17
+ Box: ({ children }) => _jsx("div", { children: children }),
18
+ Checkbox: ({ checked, onChange }) => (_jsx("input", { "aria-label": "checkbox", type: "checkbox", checked: checked, onChange: onChange })),
19
+ CircularProgress: () => _jsx("div", { children: "loading" }),
20
+ IconButton: ({ children, onClick, disabled }) => (_jsx("button", { disabled: disabled, onClick: onClick, children: children })),
21
+ Slider: ({ value, onChange }) => (_jsx("input", { "aria-label": "slider", type: "range", value: value, onChange: e => onChange(null, Number(e.target.value)) })),
22
+ Stack: ({ children }) => _jsx("div", { children: children }),
23
+ TableCell: ({ children }) => _jsx("div", { children: children }),
24
+ TableRow: ({ children }) => _jsx("div", { children: children }),
25
+ TextField: ({ value, onChange, onKeyDown, label, type, error }) => (_jsxs("label", { children: [label ?? type ?? 'text', _jsx("input", { "aria-label": label ?? type ?? 'text', value: String(value ?? ''), onChange: onChange, onKeyDown: onKeyDown, "data-error": String(error) })] })),
26
+ Typography: ({ children }) => _jsx("div", { children: children })
27
+ }));
28
+ vi.mock('components/hooks/useMySnackbar', () => ({
29
+ default: () => ({ showErrorMessage: mockShowErrorMessage })
30
+ }));
31
+ vi.mock('react-i18next', () => ({
32
+ useTranslation: () => ({ t: (key) => key })
33
+ }));
34
+ import EditRow from './EditRow';
35
+ describe('EditRow', () => {
36
+ it('edits text values and closes on escape when unchanged', async () => {
37
+ const onEdit = vi.fn(async () => undefined);
38
+ render(_jsx(EditRow, { titleKey: "title", descriptionKey: "description", value: "current", onEdit: onEdit }));
39
+ fireEvent.click(screen.getByText('edit-icon'));
40
+ fireEvent.change(screen.getByLabelText('text'), { target: { value: 'updated' } });
41
+ fireEvent.click(screen.getByText('check-icon'));
42
+ await waitFor(() => expect(onEdit).toHaveBeenCalledWith('updated'));
43
+ fireEvent.click(screen.getByText('edit-icon'));
44
+ fireEvent.keyDown(screen.getByLabelText('text'), { key: 'Escape' });
45
+ expect(screen.queryByLabelText('text')).not.toBeInTheDocument();
46
+ expect(screen.getByText('description')).toBeInTheDocument();
47
+ });
48
+ it('validates passwords and supports optional delete', async () => {
49
+ const onEdit = vi.fn(async () => undefined);
50
+ render(_jsx(EditRow, { titleKey: "password.title", value: "secret", type: "password", onEdit: onEdit, optional: true }));
51
+ fireEvent.click(screen.getByText('edit-icon'));
52
+ fireEvent.change(screen.getByLabelText('password'), { target: { value: 'next-secret' } });
53
+ fireEvent.change(screen.getByLabelText('password.confirm'), { target: { value: 'wrong' } });
54
+ fireEvent.click(screen.getByText('check-icon'));
55
+ expect(mockShowErrorMessage).toHaveBeenCalledWith('password.match');
56
+ fireEvent.change(screen.getByLabelText('password.confirm'), { target: { value: 'next-secret' } });
57
+ fireEvent.click(screen.getByText('check-icon'));
58
+ await waitFor(() => expect(onEdit).toHaveBeenCalledWith('next-secret'));
59
+ fireEvent.click(screen.getByText('edit-icon'));
60
+ fireEvent.click(screen.getByText('delete-icon'));
61
+ await waitFor(() => expect(onEdit).toHaveBeenCalledWith(undefined));
62
+ });
63
+ it('applies checkbox and range edits with validation', async () => {
64
+ const checkboxEdit = vi.fn(async () => undefined);
65
+ const rangeEdit = vi.fn(async () => undefined);
66
+ const { rerender } = render(_jsx(EditRow, { titleKey: "checkbox.title", value: false, type: "checkbox", onEdit: checkboxEdit }));
67
+ fireEvent.click(screen.getByLabelText('checkbox'));
68
+ await waitFor(() => expect(checkboxEdit).toHaveBeenCalledWith('true'));
69
+ rerender(_jsx(EditRow, { titleKey: "range.title", value: 10, type: "range", min: 5, max: 20, onEdit: rangeEdit, valueLabelFormat: value => `${value}%` }));
70
+ expect(screen.getByText('10%')).toBeInTheDocument();
71
+ fireEvent.click(screen.getByText('edit-icon'));
72
+ fireEvent.change(screen.getByLabelText('slider'), { target: { value: '15' } });
73
+ fireEvent.click(screen.getByText('check-icon'));
74
+ await waitFor(() => expect(rangeEdit).toHaveBeenCalledWith('15'));
75
+ });
76
+ it('tracks validation errors and failOnValidate behavior for text and numbers', () => {
77
+ const onEdit = vi.fn(async () => undefined);
78
+ const { unmount } = render(_jsx(EditRow, { titleKey: "text.title", value: "alpha", onEdit: onEdit, validate: (value) => value !== 'bad' }));
79
+ fireEvent.click(screen.getByText('edit-icon'));
80
+ fireEvent.change(screen.getByLabelText('text'), { target: { value: 'bad' } });
81
+ expect(screen.getByLabelText('text')).toHaveAttribute('data-error', 'true');
82
+ unmount();
83
+ render(_jsx(EditRow, { titleKey: "number.title", value: 5, type: "number", min: 2, max: 10, onEdit: onEdit, failOnValidate: true }));
84
+ fireEvent.click(screen.getByText('edit-icon'));
85
+ fireEvent.change(screen.getByLabelText('number'), { target: { value: '1' } });
86
+ expect(screen.getByLabelText('number')).toHaveValue('5');
87
+ });
88
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,75 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /// <reference types="vitest" />
3
+ import { render } from '@testing-library/react';
4
+ import { describe, expect, it, vi } from 'vitest';
5
+ const apiConfigContextToken = vi.hoisted(() => ({ name: 'api-config-context' }));
6
+ const capturedProps = vi.hoisted(() => ({ current: null }));
7
+ let monacoValue = null;
8
+ vi.mock('@monaco-editor/react', () => ({
9
+ useMonaco: () => monacoValue
10
+ }));
11
+ vi.mock('@mui/material', () => ({
12
+ useTheme: () => ({ palette: { mode: 'light' } })
13
+ }));
14
+ vi.mock('components/app/providers/ApiConfigProvider', () => ({
15
+ ApiConfigContext: apiConfigContextToken
16
+ }));
17
+ vi.mock('components/elements/ThemedEditor', () => ({
18
+ default: (props) => {
19
+ capturedProps.current = props;
20
+ return _jsx("div", { children: "themed-editor" });
21
+ }
22
+ }));
23
+ vi.mock('../routes/overviews/markdownExtendedTokenProvider', () => ({
24
+ conf: { autoClosingPairs: [] },
25
+ language: { tokenizer: {} }
26
+ }));
27
+ vi.mock('react', async (importOriginal) => {
28
+ const actual = await importOriginal();
29
+ return {
30
+ ...actual,
31
+ useContext: (context) => {
32
+ if (context === apiConfigContextToken)
33
+ return { config: { lookups: {} } };
34
+ return actual.useContext(context);
35
+ }
36
+ };
37
+ });
38
+ import MarkdownEditor from './MarkdownEditor';
39
+ describe('MarkdownEditor', () => {
40
+ it('configures markdown-extended editors and normalizes onChange values', () => {
41
+ const setEOL = vi.fn();
42
+ const model = { setEOL, getLanguageId: () => 'plaintext' };
43
+ const dispose = vi.fn();
44
+ monacoValue = {
45
+ editor: {
46
+ EndOfLineSequence: { LF: 1 },
47
+ getModels: () => [model],
48
+ onDidCreateModel: (cb) => {
49
+ cb(model);
50
+ return { dispose };
51
+ },
52
+ setModelLanguage: vi.fn()
53
+ },
54
+ languages: {
55
+ register: vi.fn(),
56
+ setLanguageConfiguration: vi.fn(() => ({ dispose })),
57
+ setMonarchTokensProvider: vi.fn(() => ({ dispose })),
58
+ getLanguages: () => [{ id: 'markdown-extended' }]
59
+ }
60
+ };
61
+ const setContent = vi.fn();
62
+ render(_jsx(MarkdownEditor, { content: "hello", setContent: setContent, editorOptions: { wordWrap: 'on' } }));
63
+ capturedProps.current.beforeMount(monacoValue);
64
+ expect(monacoValue.languages.register).toHaveBeenCalledWith({ id: 'markdown-extended' });
65
+ expect(setEOL).toHaveBeenCalledWith(1);
66
+ expect(monacoValue.editor.setModelLanguage).toHaveBeenCalledWith(model, 'markdown-extended');
67
+ expect(capturedProps.current.options).toMatchObject({
68
+ fontSize: 16,
69
+ wordWrap: 'on',
70
+ bracketPairColorization: { enabled: false }
71
+ });
72
+ capturedProps.current.onChange(undefined);
73
+ expect(setContent).toHaveBeenCalledWith('');
74
+ });
75
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,70 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /// <reference types="vitest" />
3
+ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
4
+ import { describe, expect, it, vi } from 'vitest';
5
+ vi.mock('@mui/icons-material', () => ({
6
+ ArrowDropDown: () => _jsx("div", { children: "expand-icon" }),
7
+ InfoOutlined: () => _jsx("div", { children: "info-icon" })
8
+ }));
9
+ vi.mock('@mui/material', () => ({
10
+ Accordion: ({ children }) => _jsx("div", { children: children }),
11
+ AccordionDetails: ({ children }) => _jsx("div", { children: children }),
12
+ AccordionSummary: ({ children }) => _jsx("div", { children: children }),
13
+ Box: ({ children }) => _jsx("div", { children: children }),
14
+ Divider: () => _jsx("div", { children: "divider" }),
15
+ Grid: ({ children }) => _jsx("div", { children: children }),
16
+ Stack: ({ children }) => _jsx("div", { children: children }),
17
+ TextField: ({ value, onChange, label }) => (_jsxs("label", { children: [label, _jsx("input", { "aria-label": label, value: value, onChange: onChange })] })),
18
+ Tooltip: ({ children }) => _jsx(_Fragment, { children: children }),
19
+ Typography: ({ children }) => _jsx("div", { children: children }),
20
+ useTheme: () => ({
21
+ palette: { divider: '#ddd' },
22
+ spacing: (n) => `${n * 8}px`
23
+ })
24
+ }));
25
+ vi.mock('components/elements/PluginTypography', () => ({
26
+ default: ({ children }) => _jsx("span", { children: children })
27
+ }));
28
+ vi.mock('react-i18next', () => ({
29
+ useTranslation: () => ({ t: (key) => key })
30
+ }));
31
+ vi.mock('utils/Throttler', () => ({
32
+ default: class {
33
+ debounce(fn) {
34
+ fn();
35
+ }
36
+ }
37
+ }));
38
+ import ObjectDetails from './ObjectDetails';
39
+ describe('ObjectDetails', () => {
40
+ it('renders grouped sections, nested values, and filters by search query', async () => {
41
+ render(_jsx(ObjectDetails, { obj: {
42
+ event: {
43
+ id: 'evt-1',
44
+ nested: { key: 'value' },
45
+ dup: ['alpha', 'alpha', 'beta']
46
+ },
47
+ source: {
48
+ ip: '1.1.1.1',
49
+ port: 443,
50
+ enabled: false
51
+ },
52
+ howler: { id: 'skip-me' },
53
+ labels: { tag: 'skip' },
54
+ __hidden: { value: 'skip' }
55
+ } }));
56
+ expect(screen.getByText('Event')).toBeInTheDocument();
57
+ expect(screen.getByText('Source')).toBeInTheDocument();
58
+ expect(screen.queryByText('Howler')).not.toBeInTheDocument();
59
+ expect(screen.getByText('evt-1')).toBeInTheDocument();
60
+ expect(screen.getByText('value')).toBeInTheDocument();
61
+ expect(screen.getByText('alpha')).toBeInTheDocument();
62
+ expect(screen.getByText('beta')).toBeInTheDocument();
63
+ expect(screen.getByText('info-icon')).toBeInTheDocument();
64
+ fireEvent.change(screen.getByLabelText('overview.search'), { target: { value: 'ip' } });
65
+ await waitFor(() => {
66
+ expect(screen.getByText('1.1.1.1')).toBeInTheDocument();
67
+ expect(screen.queryByText('evt-1')).not.toBeInTheDocument();
68
+ });
69
+ });
70
+ });
@@ -1,7 +1,8 @@
1
1
  import { type ChipProps } from '@mui/material';
2
2
  import type { Hit } from '@cccsaurora/howler-ui/models/entities/generated/Hit';
3
- import type { FC } from 'react';
4
- export type PluginChipProps = ChipProps & {
3
+ import { type FC, type ReactNode } from 'react';
4
+ export type PluginChipProps = Omit<ChipProps, 'children'> & {
5
+ children?: ReactNode;
5
6
  value: string;
6
7
  context: string;
7
8
  field?: string;