@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,119 @@
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 { beforeEach, describe, expect, it, vi } from 'vitest';
5
+ const mockDispatchApi = vi.hoisted(() => vi.fn());
6
+ const mockShowInfoMessage = vi.hoisted(() => vi.fn());
7
+ const mockApiKeyPost = vi.hoisted(() => vi.fn((name, privs, expiry) => ({ name, privs, expiry })));
8
+ const apiConfigContextToken = vi.hoisted(() => ({ name: 'api-config-context' }));
9
+ let configValue = {
10
+ configuration: {
11
+ auth: {
12
+ max_apikey_duration_amount: 1,
13
+ max_apikey_duration_unit: 'days',
14
+ allow_extended_apikeys: true
15
+ }
16
+ }
17
+ };
18
+ vi.mock('@mui/material', () => ({
19
+ Alert: ({ children }) => _jsx("div", { children: children }),
20
+ AlertTitle: ({ children }) => _jsx("div", { children: children }),
21
+ Button: ({ children, onClick, disabled }) => (_jsx("button", { disabled: disabled, onClick: onClick, children: children })),
22
+ Checkbox: ({ onChange }) => _jsx("input", { "aria-label": "checkbox", type: "checkbox", onChange: onChange }),
23
+ Divider: () => _jsx("div", { children: "divider" }),
24
+ FormControl: ({ children }) => _jsx("div", { children: children }),
25
+ FormControlLabel: ({ control, label }) => (_jsxs("label", { children: [control, label] })),
26
+ FormGroup: ({ children }) => _jsx("div", { children: children }),
27
+ FormLabel: ({ children }) => _jsx("div", { children: children }),
28
+ Stack: ({ children }) => _jsx("div", { children: children }),
29
+ TextField: ({ label, value, onChange, inputProps, size }) => (_jsxs("label", { children: [label ?? size ?? 'text', _jsx("input", { "aria-label": label ?? size ?? 'text', value: value, onChange: onChange, readOnly: inputProps?.readOnly })] })),
30
+ Typography: ({ children }) => _jsx("div", { children: children })
31
+ }));
32
+ vi.mock('@mui/x-date-pickers', () => ({
33
+ LocalizationProvider: ({ children }) => _jsx(_Fragment, { children: children }),
34
+ StaticDateTimePicker: ({ value, onChange }) => (_jsx("button", { onClick: () => onChange({ toISOString: () => '2027-01-01T00:00:00.000Z' }), children: value ? 'change-date' : 'set-date' }))
35
+ }));
36
+ vi.mock('@mui/x-date-pickers/AdapterDayjs', () => ({
37
+ AdapterDayjs: class {
38
+ }
39
+ }));
40
+ vi.mock('api', () => ({
41
+ default: {
42
+ auth: {
43
+ apikey: {
44
+ post: mockApiKeyPost
45
+ }
46
+ }
47
+ }
48
+ }));
49
+ vi.mock('components/hooks/useMyApi', () => ({
50
+ default: () => ({ dispatchApi: mockDispatchApi })
51
+ }));
52
+ vi.mock('components/hooks/useMySnackbar', () => ({
53
+ default: () => ({ showInfoMessage: mockShowInfoMessage })
54
+ }));
55
+ vi.mock('dayjs', () => {
56
+ const factory = () => ({
57
+ add: () => ({ toISOString: () => '2026-09-19T00:00:00.000Z', format: () => 'Sep 19 00:00:00' })
58
+ });
59
+ factory.duration = (amount, unit) => ({
60
+ asSeconds: () => (unit === 'days' ? amount * 86400 : amount)
61
+ });
62
+ return { default: factory };
63
+ });
64
+ vi.mock('react-i18next', () => ({
65
+ Trans: ({ i18nKey }) => _jsx(_Fragment, { children: i18nKey }),
66
+ useTranslation: () => ({ t: (key) => key })
67
+ }));
68
+ vi.mock('../providers/ApiConfigProvider', () => ({
69
+ ApiConfigContext: apiConfigContextToken
70
+ }));
71
+ vi.mock('react', async (importOriginal) => {
72
+ const actual = await importOriginal();
73
+ return {
74
+ ...actual,
75
+ useContext: (context) => {
76
+ if (context === apiConfigContextToken)
77
+ return { config: configValue };
78
+ return actual.useContext(context);
79
+ }
80
+ };
81
+ });
82
+ import ApiKeyDrawer from './ApiKeyDrawer';
83
+ describe('ApiKeyDrawer', () => {
84
+ beforeEach(() => {
85
+ configValue = {
86
+ configuration: {
87
+ auth: {
88
+ max_apikey_duration_amount: 1,
89
+ max_apikey_duration_unit: 'days',
90
+ allow_extended_apikeys: true
91
+ }
92
+ }
93
+ };
94
+ mockDispatchApi.mockReset();
95
+ mockShowInfoMessage.mockReset();
96
+ mockApiKeyPost.mockClear();
97
+ Object.assign(navigator, {
98
+ clipboard: { writeText: vi.fn().mockResolvedValue(undefined) }
99
+ });
100
+ });
101
+ it('validates input, creates a key, and copies the generated value', async () => {
102
+ const onCreated = vi.fn();
103
+ mockDispatchApi.mockResolvedValueOnce({ apikey: 'demo-key:secret' });
104
+ render(_jsx(ApiKeyDrawer, { onCreated: onCreated }));
105
+ expect(screen.getByText('app.drawer.user.apikey.limit.title')).toBeInTheDocument();
106
+ fireEvent.change(screen.getByLabelText('app.drawer.user.apikey.field.name'), { target: { value: 'bad-name!' } });
107
+ expect(screen.getByLabelText('app.drawer.user.apikey.field.name')).toHaveValue('');
108
+ fireEvent.change(screen.getByLabelText('app.drawer.user.apikey.field.name'), { target: { value: 'demo_key' } });
109
+ fireEvent.click(screen.getAllByLabelText('checkbox')[0]);
110
+ fireEvent.click(screen.getByText('change-date'));
111
+ fireEvent.click(screen.getByText('button.create'));
112
+ await waitFor(() => expect(mockDispatchApi).toHaveBeenCalledWith({ name: 'demo_key', privs: ['R'], expiry: '2027-01-01T00:00:00.000Z' }, { throwError: true, showError: true }));
113
+ expect(onCreated).toHaveBeenCalledWith('demo-key', ['R'], '2027-01-01T00:00:00.000Z', 'demo-key:secret');
114
+ expect(screen.getByDisplayValue('demo-key:secret')).toBeInTheDocument();
115
+ fireEvent.click(screen.getByText('button.copy'));
116
+ await waitFor(() => expect(navigator.clipboard.writeText).toHaveBeenCalledWith('demo-key:secret'));
117
+ expect(mockShowInfoMessage).toHaveBeenCalledWith('drawer.apikey.copied');
118
+ });
119
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,75 @@
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 { beforeEach, describe, expect, it, vi } from 'vitest';
5
+ const mockDispatchApi = vi.hoisted(() => vi.fn());
6
+ const mockShowInfoMessage = vi.hoisted(() => vi.fn());
7
+ const mockAssignPut = vi.hoisted(() => vi.fn((id, body) => ({ id, body })));
8
+ vi.mock('@mui/icons-material', () => ({
9
+ PersonOff: () => _jsx("div", { children: "person-off" })
10
+ }));
11
+ vi.mock('@mui/material', () => ({
12
+ Autocomplete: ({ onChange, options, renderInput, disabled }) => (_jsxs("div", { children: [_jsx("div", { children: String(disabled) }), _jsx("button", { onClick: () => onChange(null, options[0]), children: "pick-first" }), _jsx("button", { onClick: () => onChange(null, options[options.length - 1]), children: "pick-unassigned" }), renderInput({})] })),
13
+ Avatar: ({ children }) => _jsx("div", { children: children }),
14
+ Box: ({ children }) => _jsx("div", { children: children }),
15
+ Button: ({ children, disabled, onClick }) => (_jsx("button", { disabled: disabled, onClick: onClick, children: children })),
16
+ CircularProgress: () => _jsx("div", { children: "loading" }),
17
+ Stack: ({ children }) => _jsx("div", { children: children }),
18
+ TextField: ({ label }) => _jsx("div", { children: label }),
19
+ Typography: ({ children }) => _jsx("div", { children: children })
20
+ }));
21
+ vi.mock('api', () => ({
22
+ default: {
23
+ hit: {
24
+ assign: { put: mockAssignPut }
25
+ }
26
+ }
27
+ }));
28
+ vi.mock('components/elements/display/HowlerAvatar', () => ({
29
+ default: ({ userId }) => _jsx("div", { children: userId })
30
+ }));
31
+ vi.mock('components/hooks/useMyApi', () => ({
32
+ default: () => ({ dispatchApi: mockDispatchApi })
33
+ }));
34
+ vi.mock('components/hooks/useMySnackbar', () => ({
35
+ default: () => ({ showInfoMessage: mockShowInfoMessage })
36
+ }));
37
+ vi.mock('components/hooks/useMyUserList', () => ({
38
+ default: () => ({
39
+ alice: { username: 'alice', name: 'Alice', email: 'alice@example.com' }
40
+ })
41
+ }));
42
+ vi.mock('react-i18next', () => ({
43
+ Trans: ({ i18nKey }) => _jsx("span", { children: i18nKey }),
44
+ useTranslation: () => ({ t: (key) => key })
45
+ }));
46
+ import AssignUserDrawer from './AssignUserDrawer';
47
+ describe('AssignUserDrawer', () => {
48
+ beforeEach(() => {
49
+ mockDispatchApi.mockReset();
50
+ mockShowInfoMessage.mockReset();
51
+ mockAssignPut.mockReset();
52
+ });
53
+ it('submits assignments through the API and reports success', async () => {
54
+ const onAssigned = vi.fn();
55
+ render(_jsx(AssignUserDrawer, { assignment: "unassigned", ids: ['h1', 'h2'], onAssigned: onAssigned }));
56
+ fireEvent.click(screen.getByText('pick-first'));
57
+ await act(async () => {
58
+ fireEvent.click(screen.getByText('button.save'));
59
+ });
60
+ expect(mockAssignPut).toHaveBeenCalledWith('h1', { value: 'alice' });
61
+ expect(mockAssignPut).toHaveBeenCalledWith('h2', { value: 'alice' });
62
+ expect(mockShowInfoMessage).toHaveBeenCalledWith('app.drawer.hit.assignment.success');
63
+ expect(onAssigned).toHaveBeenCalledWith('alice');
64
+ });
65
+ it('supports unassigned targets and skip-submit mode', async () => {
66
+ const onAssigned = vi.fn();
67
+ render(_jsx(AssignUserDrawer, { assignment: "alice", ids: ['h1'], onAssigned: onAssigned, skipSubmit: true }));
68
+ fireEvent.click(screen.getByText('pick-unassigned'));
69
+ await act(async () => {
70
+ fireEvent.click(screen.getByText('button.save'));
71
+ });
72
+ expect(mockDispatchApi).not.toHaveBeenCalled();
73
+ expect(onAssigned).toHaveBeenCalledWith('unassigned');
74
+ });
75
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,103 @@
1
+ /// <reference types="vitest" />
2
+ import { renderHook, waitFor } from '@testing-library/react';
3
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
4
+ const analyticContextToken = vi.hoisted(() => ({ name: 'analytic-context' }));
5
+ const recordContextToken = vi.hoisted(() => ({ name: 'record-context' }));
6
+ let locationValue = { pathname: '/', search: '' };
7
+ let paramsValue = {};
8
+ let searchParamsValue = new URLSearchParams();
9
+ let breadcrumbsValue = [];
10
+ let analyticContextValue = {};
11
+ let recordValue = { records: {}, getRecord: vi.fn() };
12
+ vi.mock('@tui/core', () => ({
13
+ useAppRouter: () => ({ breadcrumbs: () => breadcrumbsValue })
14
+ }));
15
+ vi.mock('react-i18next', () => ({
16
+ useTranslation: () => ({ t: (key) => `translated:${key}` })
17
+ }));
18
+ vi.mock('react-router', () => ({
19
+ useLocation: () => locationValue,
20
+ useParams: () => paramsValue,
21
+ useSearchParams: () => [searchParamsValue]
22
+ }));
23
+ vi.mock('../providers/AnalyticProvider', () => ({
24
+ AnalyticContext: analyticContextToken
25
+ }));
26
+ vi.mock('../providers/RecordProvider', () => ({
27
+ RecordContext: recordContextToken
28
+ }));
29
+ vi.mock('use-context-selector', async (importOriginal) => {
30
+ const actual = await importOriginal();
31
+ return {
32
+ ...actual,
33
+ useContextSelector: (_context, selector) => selector(recordValue)
34
+ };
35
+ });
36
+ vi.mock('react', async (importOriginal) => {
37
+ const actual = await importOriginal();
38
+ return {
39
+ ...actual,
40
+ useContext: (context) => {
41
+ if (context === analyticContextToken) {
42
+ return analyticContextValue;
43
+ }
44
+ return actual.useContext(context);
45
+ }
46
+ };
47
+ });
48
+ import useTitle from './useTitle';
49
+ describe('useTitle', () => {
50
+ beforeEach(() => {
51
+ document.head.innerHTML = '<title></title>';
52
+ locationValue = { pathname: '/', search: '' };
53
+ paramsValue = {};
54
+ searchParamsValue = new URLSearchParams();
55
+ breadcrumbsValue = [];
56
+ analyticContextValue = {};
57
+ recordValue = { records: {}, getRecord: vi.fn() };
58
+ });
59
+ it('sets analytic titles from ids or falls back to the section title', async () => {
60
+ locationValue = { pathname: '/analytics/123', search: '' };
61
+ paramsValue = { id: '123' };
62
+ analyticContextValue = { getAnalyticFromId: vi.fn().mockResolvedValue({ name: 'Suspicious Login' }) };
63
+ renderHook(() => useTitle());
64
+ await waitFor(() => expect(document.title).toBe('translated:route.analytics.view - Suspicious Login'));
65
+ analyticContextValue = { getAnalyticFromId: vi.fn().mockResolvedValue(undefined) };
66
+ renderHook(() => useTitle());
67
+ await waitFor(() => expect(document.title).toBe('translated:route.analytics.view'));
68
+ locationValue = { pathname: '/analytics', search: '' };
69
+ paramsValue = {};
70
+ renderHook(() => useTitle());
71
+ await waitFor(() => expect(document.title).toBe('Howler - translated:route.analytics'));
72
+ });
73
+ it('sets hit titles from cached or fetched records', async () => {
74
+ locationValue = { pathname: '/hits/h1', search: '' };
75
+ paramsValue = { id: 'h1' };
76
+ recordValue = {
77
+ records: {
78
+ h1: { howler: { escalation: 'alert', analytic: 'One', detection: 'Two' } }
79
+ },
80
+ getRecord: vi.fn()
81
+ };
82
+ renderHook(() => useTitle());
83
+ await waitFor(() => expect(document.title).toBe('Alert - One: Two'));
84
+ recordValue = {
85
+ records: {},
86
+ getRecord: vi.fn().mockResolvedValue({ howler: { escalation: 'hit', analytic: 'Three' } })
87
+ };
88
+ paramsValue = { id: 'h2' };
89
+ renderHook(() => useTitle());
90
+ await waitFor(() => expect(document.title).toBe('Hit - Three'));
91
+ });
92
+ it('sets template and breadcrumb titles', async () => {
93
+ locationValue = { pathname: '/templates/view', search: '?analytic=Demo&detection=X' };
94
+ searchParamsValue = new URLSearchParams('analytic=Demo&detection=X');
95
+ renderHook(() => useTitle());
96
+ await waitFor(() => expect(document.title).toBe('translated:route.templates.view - Demo: X'));
97
+ locationValue = { pathname: '/views', search: '' };
98
+ searchParamsValue = new URLSearchParams();
99
+ breadcrumbsValue = [{ i18nKey: 'route.views' }];
100
+ renderHook(() => useTitle());
101
+ await waitFor(() => expect(document.title).toBe('Howler - translated:route.views'));
102
+ });
103
+ });
@@ -0,0 +1,58 @@
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 { beforeEach, describe, expect, it, vi } from 'vitest';
6
+ const mockAnalyticGet = vi.hoisted(() => vi.fn());
7
+ const mockAnalyticSearchPost = vi.hoisted(() => vi.fn());
8
+ let userReady = true;
9
+ vi.mock('@tui/core', () => ({
10
+ useAppUser: () => ({
11
+ isReady: () => userReady
12
+ })
13
+ }));
14
+ vi.mock('api', () => ({
15
+ default: {
16
+ analytic: { get: mockAnalyticGet },
17
+ search: { analytic: { post: mockAnalyticSearchPost } }
18
+ }
19
+ }));
20
+ import AnalyticProvider, { AnalyticContext } from './AnalyticProvider';
21
+ describe('AnalyticProvider', () => {
22
+ const wrapper = ({ children }) => _jsx(AnalyticProvider, { children: children });
23
+ beforeEach(() => {
24
+ userReady = true;
25
+ mockAnalyticGet.mockReset();
26
+ mockAnalyticSearchPost.mockReset();
27
+ });
28
+ it('loads analytics once the user is ready', async () => {
29
+ mockAnalyticGet.mockResolvedValue([{ analytic_id: 'a1', name: 'Analytic One' }]);
30
+ const { result } = renderHook(() => useContext(AnalyticContext), { wrapper });
31
+ await waitFor(() => expect(result.current.ready).toBe(true));
32
+ expect(result.current.analytics).toEqual([{ analytic_id: 'a1', name: 'Analytic One' }]);
33
+ expect(mockAnalyticGet).toHaveBeenCalledTimes(1);
34
+ });
35
+ it('returns cached analytics and falls back to search by id', async () => {
36
+ mockAnalyticGet.mockResolvedValue([{ analytic_id: 'a1', name: 'Analytic One' }]);
37
+ mockAnalyticSearchPost.mockResolvedValue({ items: [{ analytic_id: 'a2', name: 'Analytic Two' }] });
38
+ const { result } = renderHook(() => useContext(AnalyticContext), { wrapper });
39
+ await waitFor(() => expect(result.current.ready).toBe(true));
40
+ await expect(result.current.getAnalyticFromId('a1')).resolves.toEqual({ analytic_id: 'a1', name: 'Analytic One' });
41
+ await act(async () => {
42
+ await expect(result.current.getAnalyticFromId('a2')).resolves.toEqual({
43
+ analytic_id: 'a2',
44
+ name: 'Analytic Two'
45
+ });
46
+ });
47
+ expect(mockAnalyticSearchPost).toHaveBeenCalledWith({ query: 'analytic_id:a2' });
48
+ });
49
+ it('handles search failures gracefully', async () => {
50
+ mockAnalyticGet.mockResolvedValue([]);
51
+ mockAnalyticSearchPost.mockRejectedValue(new Error('boom'));
52
+ const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined);
53
+ const { result } = renderHook(() => useContext(AnalyticContext), { wrapper });
54
+ await waitFor(() => expect(result.current.ready).toBe(true));
55
+ await expect(result.current.getAnalyticFromId('missing')).resolves.toBeUndefined();
56
+ expect(errorSpy).toHaveBeenCalled();
57
+ });
58
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
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 } from 'vitest';
6
+ import AppBarProvider, { AppBarContext } from './AppBarProvider';
7
+ const Consumer = () => {
8
+ const ctx = useContext(AppBarContext);
9
+ return (_jsxs("div", { children: [_jsx("button", { onClick: () => ctx.addToAppBar('left', 'a', _jsx("span", { children: "A" })), children: "add-left" }), _jsx("button", { onClick: () => ctx.addToAppBar('right', 'b', _jsx("span", { children: "B" })), children: "add-right" }), _jsx("button", { onClick: () => ctx.addToAppBar('left', 'a', _jsx("span", { children: "A2" })), children: "add-duplicate" }), _jsx("button", { onClick: () => ctx.removeFromAppBar('a'), children: "remove-left" }), _jsx("span", { children: ctx.leftItems.map(item => item.id).join(',') }), _jsx("span", { children: ctx.rightItems.map(item => item.id).join(',') })] }));
10
+ };
11
+ describe('AppBarProvider', () => {
12
+ it('adds unique app bar items and removes them from both sides', async () => {
13
+ render(_jsx(AppBarProvider, { children: _jsx(Consumer, {}) }));
14
+ await act(async () => screen.getByText('add-left').click());
15
+ await act(async () => screen.getByText('add-right').click());
16
+ await act(async () => screen.getByText('add-duplicate').click());
17
+ expect(screen.getByText('a')).toBeInTheDocument();
18
+ expect(screen.getByText('b')).toBeInTheDocument();
19
+ await act(async () => screen.getByText('remove-left').click());
20
+ expect(screen.queryByText(/^a$/)).not.toBeInTheDocument();
21
+ expect(screen.getByText('b')).toBeInTheDocument();
22
+ });
23
+ });
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /// <reference types="vitest" />
3
+ import { fireEvent, render, screen } from '@testing-library/react';
4
+ import { useContext } from 'react';
5
+ import { describe, expect, it, vi } from 'vitest';
6
+ vi.mock('@tui/core', () => ({
7
+ PageContent: ({ children }) => _jsx("div", { children: children })
8
+ }));
9
+ vi.mock('@mui/material', () => ({
10
+ Drawer: ({ children, open, onClose }) => (_jsxs("div", { "data-open": String(open), children: [_jsx("button", { onClick: onClose, children: "close-drawer" }), children] })),
11
+ Typography: ({ children }) => _jsx("div", { children: children })
12
+ }));
13
+ vi.mock('react-i18next', () => ({
14
+ useTranslation: () => ({ t: (key) => `translated:${key}` })
15
+ }));
16
+ import AppDrawerProvider, { AppDrawerContext } from './AppDrawerProvider';
17
+ const Consumer = () => {
18
+ const drawer = useContext(AppDrawerContext);
19
+ return (_jsxs("div", { children: [_jsx("button", { onClick: () => drawer.open({ titleKey: 'drawer.title', children: _jsx("div", { children: "drawer-body" }), onClosed: vi.fn() }), children: "open" }), _jsx("button", { onClick: () => drawer.close(), children: "close" })] }));
20
+ };
21
+ describe('AppDrawerProvider', () => {
22
+ it('opens and closes the drawer with translated content', () => {
23
+ const onClosed = vi.fn();
24
+ const TestConsumer = () => {
25
+ const drawer = useContext(AppDrawerContext);
26
+ return (_jsx("button", { onClick: () => drawer.open({ titleKey: 'drawer.title', children: _jsx("div", { children: "drawer-body" }), onClosed }), children: "open" }));
27
+ };
28
+ render(_jsx(AppDrawerProvider, { children: _jsx(TestConsumer, {}) }));
29
+ expect(screen.getByText('close-drawer').parentElement).toHaveAttribute('data-open', 'false');
30
+ fireEvent.click(screen.getByText('open'));
31
+ expect(screen.getByText('close-drawer').parentElement).toHaveAttribute('data-open', 'true');
32
+ expect(screen.getByText('translated:drawer.title')).toBeInTheDocument();
33
+ expect(screen.getByText('drawer-body')).toBeInTheDocument();
34
+ fireEvent.click(screen.getByText('close-drawer'));
35
+ expect(onClosed).toHaveBeenCalled();
36
+ });
37
+ it('exposes default no-op context methods before open is called', () => {
38
+ render(_jsx(AppDrawerProvider, { children: _jsx(Consumer, {}) }));
39
+ fireEvent.click(screen.getByText('close'));
40
+ expect(screen.getByText('close-drawer').parentElement).toHaveAttribute('data-open', 'false');
41
+ });
42
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,50 @@
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 { beforeEach, describe, expect, it, vi } from 'vitest';
6
+ const mockDispatchApi = vi.hoisted(() => vi.fn());
7
+ const mockUserGet = vi.hoisted(() => vi.fn());
8
+ const mockAvatarGet = vi.hoisted(() => vi.fn());
9
+ vi.mock('api', () => ({
10
+ default: {
11
+ user: {
12
+ get: mockUserGet,
13
+ avatar: { get: mockAvatarGet }
14
+ }
15
+ }
16
+ }));
17
+ vi.mock('components/hooks/useMyApi', () => ({
18
+ default: () => ({ dispatchApi: mockDispatchApi })
19
+ }));
20
+ import AvatarProvider, { AvatarContext } from './AvatarProvider';
21
+ const Consumer = () => {
22
+ const ctx = useContext(AvatarContext);
23
+ return (_jsxs("div", { children: [_jsx("button", { onClick: () => void ctx.getAvatar('alice').then(v => (document.body.dataset.value = v)), children: "load-alice" }), _jsx("button", { onClick: () => void ctx.getAvatar('bob').then(v => (document.body.dataset.value = v)), children: "load-bob" }), _jsx("button", { onClick: () => void ctx.getAvatar('').then(v => (document.body.dataset.empty = v)), children: "empty" })] }));
24
+ };
25
+ describe('AvatarProvider', () => {
26
+ beforeEach(() => {
27
+ document.body.dataset.value = '';
28
+ document.body.dataset.empty = '';
29
+ mockDispatchApi.mockReset();
30
+ mockUserGet.mockReset();
31
+ mockAvatarGet.mockReset();
32
+ });
33
+ it('returns empty avatars for blank ids and caches resolved avatar lookups', async () => {
34
+ mockDispatchApi.mockResolvedValue('avatar-url');
35
+ render(_jsx(AvatarProvider, { children: _jsx(Consumer, {}) }));
36
+ await act(async () => screen.getByText('empty').click());
37
+ expect(document.body.dataset.empty).toBe('');
38
+ await act(async () => screen.getByText('load-alice').click());
39
+ expect(document.body.dataset.value).toBe('avatar-url');
40
+ await act(async () => screen.getByText('load-alice').click());
41
+ expect(mockDispatchApi).toHaveBeenCalledTimes(1);
42
+ });
43
+ it('falls back to the user name when the avatar request returns nothing or throws', async () => {
44
+ mockUserGet.mockResolvedValue({ name: 'Alice Name' });
45
+ mockDispatchApi.mockResolvedValueOnce(undefined).mockRejectedValueOnce(new Error('boom'));
46
+ render(_jsx(AvatarProvider, { children: _jsx(Consumer, {}) }));
47
+ await act(async () => screen.getByText('load-bob').click());
48
+ expect(document.body.dataset.value).toBe('Alice Name');
49
+ });
50
+ });
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /// <reference types="vitest" />
3
+ import { render, screen } from '@testing-library/react';
4
+ import { describe, expect, it, vi } from 'vitest';
5
+ const mockExecuteFunction = vi.hoisted(() => vi.fn());
6
+ vi.mock('plugins/store', () => ({
7
+ default: { plugins: ['one', 'two', 'three'] }
8
+ }));
9
+ vi.mock('react-pluggable', () => ({
10
+ usePluginStore: () => ({ executeFunction: mockExecuteFunction })
11
+ }));
12
+ import CustomPluginProvider from './CustomPluginProvider';
13
+ describe('CustomPluginProvider', () => {
14
+ it('wraps children with every plugin provider returned by the store', () => {
15
+ mockExecuteFunction.mockImplementation((key) => {
16
+ if (key === 'one.provider')
17
+ return ({ children }) => _jsxs("div", { children: ["one:", children] });
18
+ if (key === 'two.provider')
19
+ return undefined;
20
+ if (key === 'three.provider')
21
+ return ({ children }) => _jsxs("div", { children: ["three:", children] });
22
+ return undefined;
23
+ });
24
+ render(_jsx(CustomPluginProvider, { children: _jsx("span", { children: "child" }) }));
25
+ expect(screen.getByText('three:')).toBeInTheDocument();
26
+ expect(screen.getByText('one:')).toBeInTheDocument();
27
+ expect(screen.getByText('child')).toBeInTheDocument();
28
+ });
29
+ });
@@ -0,0 +1,115 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /// <reference types="vitest" />
3
+ import { render, waitFor } from '@testing-library/react';
4
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
5
+ const mockSetMenus = vi.hoisted(() => vi.fn());
6
+ const mockApplyMainMenuOperations = vi.hoisted(() => vi.fn((_menu, operations) => ({ id: 'root', operations })));
7
+ const mockFetchViews = vi.hoisted(() => vi.fn());
8
+ let appUserValue = {
9
+ isReady: () => true,
10
+ user: {
11
+ favourite_views: ['view-2', 'view-1', 'view-1'],
12
+ favourite_analytics: ['analytic-2', 'missing', 'analytic-1']
13
+ }
14
+ };
15
+ const analyticContextToken = vi.hoisted(() => ({ name: 'analytic-context' }));
16
+ const viewContextToken = vi.hoisted(() => ({ name: 'view-context' }));
17
+ let analyticContextValue = { analytics: [], ready: false };
18
+ vi.mock('@mui/icons-material', () => ({
19
+ QueryStats: () => _jsx("div", { children: "query-stats" }),
20
+ SavedSearch: () => _jsx("div", { children: "saved-search" })
21
+ }));
22
+ vi.mock('@tui/core', () => ({
23
+ useAppLeftNav: () => ({ setMenus: mockSetMenus }),
24
+ useAppUser: () => appUserValue
25
+ }));
26
+ vi.mock('react-i18next', () => ({
27
+ useTranslation: () => ({ t: (key) => `translated:${key}` })
28
+ }));
29
+ vi.mock('utils/menuUtils', () => ({
30
+ applyMainMenuOperations: mockApplyMainMenuOperations
31
+ }));
32
+ vi.mock('./AnalyticProvider', () => ({
33
+ AnalyticContext: analyticContextToken
34
+ }));
35
+ vi.mock('./ViewProvider', () => ({
36
+ ViewContext: viewContextToken
37
+ }));
38
+ vi.mock('use-context-selector', async (importOriginal) => {
39
+ const actual = await importOriginal();
40
+ return {
41
+ ...actual,
42
+ useContextSelector: (context, selector) => {
43
+ if (context === viewContextToken) {
44
+ return selector({ fetchViews: mockFetchViews });
45
+ }
46
+ return selector(null);
47
+ }
48
+ };
49
+ });
50
+ vi.mock('react', async (importOriginal) => {
51
+ const actual = await importOriginal();
52
+ return {
53
+ ...actual,
54
+ useContext: (context) => {
55
+ if (context === analyticContextToken) {
56
+ return analyticContextValue;
57
+ }
58
+ return actual.useContext(context);
59
+ }
60
+ };
61
+ });
62
+ import FavouriteProvider from './FavouritesProvider';
63
+ describe('FavouriteProvider', () => {
64
+ beforeEach(() => {
65
+ mockSetMenus.mockReset();
66
+ mockApplyMainMenuOperations.mockReset();
67
+ mockFetchViews.mockReset();
68
+ analyticContextValue = {
69
+ ready: true,
70
+ analytics: [
71
+ { analytic_id: 'analytic-1', name: 'One' },
72
+ { analytic_id: 'analytic-2', name: 'Two' }
73
+ ]
74
+ };
75
+ appUserValue = {
76
+ isReady: () => true,
77
+ user: {
78
+ favourite_views: ['view-2', 'view-1', 'view-1'],
79
+ favourite_analytics: ['analytic-2', 'missing', 'analytic-1']
80
+ }
81
+ };
82
+ });
83
+ it('builds favourite view and analytic menus and applies main-menu operations', async () => {
84
+ mockFetchViews.mockResolvedValue([
85
+ { view_id: 'view-1', title: 'Zulu', span: 'date.range.1.month' },
86
+ { view_id: 'view-2', title: 'Alpha', sort: 'created asc', indexes: ['hit'] }
87
+ ]);
88
+ render(_jsx(FavouriteProvider, { children: _jsx("div", { children: "child" }) }));
89
+ await waitFor(() => expect(mockSetMenus).toHaveBeenCalled());
90
+ expect(mockFetchViews).toHaveBeenCalledWith(['view-2', 'view-1']);
91
+ const callback = mockSetMenus.mock.calls[0][0];
92
+ const updated = callback([{ id: 'root', items: [] }, { id: 'secondary' }]);
93
+ expect(mockApplyMainMenuOperations).toHaveBeenCalled();
94
+ expect(updated[0]).toEqual(expect.objectContaining({
95
+ id: 'root',
96
+ operations: expect.arrayContaining([
97
+ { type: 'remove', targetId: 'views' },
98
+ { type: 'remove', targetId: 'analytics' },
99
+ expect.objectContaining({ type: 'insertRelative', anchorId: 'cases' }),
100
+ expect.objectContaining({ type: 'insertRelative', anchorId: 'views' })
101
+ ])
102
+ }));
103
+ });
104
+ it('skips menu work until both the user and analytics are ready', async () => {
105
+ appUserValue = {
106
+ isReady: () => false,
107
+ user: { favourite_views: ['view-1'], favourite_analytics: ['analytic-1'] }
108
+ };
109
+ analyticContextValue = { ready: false, analytics: [] };
110
+ render(_jsx(FavouriteProvider, { children: _jsx("div", { children: "child" }) }));
111
+ await new Promise(resolve => setTimeout(resolve, 0));
112
+ expect(mockSetMenus).not.toHaveBeenCalled();
113
+ expect(mockFetchViews).not.toHaveBeenCalled();
114
+ });
115
+ });
@@ -0,0 +1 @@
1
+ export {};