@jmruthers/pace-core 0.6.8 → 0.6.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (669) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/audit-tool/audits/02-project-structure.cjs +97 -32
  3. package/audit-tool/audits/03-architecture.cjs +145 -19
  4. package/audit-tool/audits/04-code-quality.cjs +86 -1
  5. package/audit-tool/audits/06-security-rbac.cjs +109 -11
  6. package/cursor-rules/02-project-structure.mdc +2 -26
  7. package/cursor-rules/05-styling.mdc +84 -6
  8. package/cursor-rules/06-security-rbac.mdc +124 -1
  9. package/dist/{DataTable-6RMSCQJ6.js → DataTable-SAXFG4XI.js} +11 -13
  10. package/dist/{AuthService-DmfO5rGS.d.ts → InactivityServiceProvider-DHryoh6K.d.ts} +24 -249
  11. package/dist/UnifiedAuthProvider-BBD2PS3Q.js +7 -0
  12. package/dist/{UnifiedAuthProvider-CKvHP1MK.d.ts → UnifiedAuthProvider-CiBAl9-s.d.ts} +34 -22
  13. package/dist/{api-7P7DI652.js → api-F47QJ7FX.js} +3 -3
  14. package/dist/assets/app-icons/admin_favicon.svg +462 -0
  15. package/dist/assets/app-icons/base_favicon.svg +85 -0
  16. package/dist/assets/app-icons/cake_favicon.svg +68 -0
  17. package/dist/assets/app-icons/core_favicon.svg +256 -0
  18. package/dist/assets/app-icons/gear_favicon.svg +91 -0
  19. package/dist/assets/app-icons/medi_favicon.svg +92 -0
  20. package/dist/assets/app-icons/mint_favicon.svg +83 -0
  21. package/dist/assets/app-icons/pace_favicon.svg +49 -0
  22. package/dist/assets/app-icons/pump_favicon.svg +68 -0
  23. package/dist/assets/app-icons/seed_favicon.svg +91 -0
  24. package/dist/assets/app-icons/team_favicon.svg +67 -0
  25. package/dist/assets/app-icons/trac_favicon.svg +112 -0
  26. package/dist/assets/app-icons/trip_favicon.svg +102 -0
  27. package/dist/audit-Z6ZZBWLU.js +3 -0
  28. package/dist/chunk-3GWSPISD.js +61 -0
  29. package/dist/{chunk-4DDCYDQ3.js → chunk-66R6RLUZ.js} +12 -27
  30. package/dist/{chunk-FYHN4DD5.js → chunk-7YDC7LMU.js} +80 -8
  31. package/dist/{chunk-S7DKJPLT.js → chunk-BCTXBU6U.js} +22 -17
  32. package/dist/{chunk-TTRFSOKR.js → chunk-BTHN5MKC.js} +4 -4
  33. package/dist/{chunk-A3W6LW53.js → chunk-DDMPHZ3D.js} +6 -18
  34. package/dist/{chunk-MPBLMWVR.js → chunk-FBZ7U3ID.js} +140 -92
  35. package/dist/chunk-FN52B75D.js +246 -0
  36. package/dist/{chunk-5W2A3DRC.js → chunk-JJEYZ3DX.js} +5 -4
  37. package/dist/chunk-KPYQWGFQ.js +183 -0
  38. package/dist/{chunk-IUBRCBSY.js → chunk-KSNLMI7N.js} +14 -8
  39. package/dist/chunk-KYURMOQM.js +977 -0
  40. package/dist/{chunk-LX6U42O3.js → chunk-LNHFAF4X.js} +160 -58
  41. package/dist/{chunk-NKHKXPI4.js → chunk-MPY44PWB.js} +683 -627
  42. package/dist/{chunk-AHU7G2R5.js → chunk-NIU6DPQV.js} +10 -6
  43. package/dist/{chunk-HF6O3O37.js → chunk-RMLY6KB5.js} +1 -1
  44. package/dist/{chunk-6GLLNA6U.js → chunk-SACF5YSM.js} +1 -1
  45. package/dist/{chunk-EURB7QFZ.js → chunk-TFIPNIPE.js} +867 -534
  46. package/dist/{chunk-OJ4SKRSV.js → chunk-UZNAFKGW.js} +25 -5
  47. package/dist/chunk-W46INAVW.js +1216 -0
  48. package/dist/chunk-X5EAU5G7.js +793 -0
  49. package/dist/{chunk-T5CVK4R3.js → chunk-Y4PF6HIM.js} +110 -64
  50. package/dist/components.d.ts +8 -86
  51. package/dist/components.js +21 -55
  52. package/dist/{database.generated-CcnC_DRc.d.ts → database.generated-DT8JTZiP.d.ts} +12 -12
  53. package/dist/eslint-rules/rules/05-styling.cjs +507 -0
  54. package/dist/eslint-rules/rules/06-security-rbac.cjs +10 -0
  55. package/dist/{event-CW5YB_2p.d.ts → event-WTAQuGcq.d.ts} +1 -1
  56. package/dist/{functions-lBy5L2ry.d.ts → functions-DH45k8ec.d.ts} +1 -1
  57. package/dist/hooks.d.ts +12 -11
  58. package/dist/hooks.js +69 -44
  59. package/dist/index.d.ts +380 -32
  60. package/dist/index.js +46 -32
  61. package/dist/papaparseLoader-WG2UXQ22.js +7 -0
  62. package/dist/providers.d.ts +28 -14
  63. package/dist/providers.js +5 -5
  64. package/dist/rbac/eslint-rules.js +2 -2
  65. package/dist/rbac/index.d.ts +58 -214
  66. package/dist/rbac/index.js +11 -11
  67. package/dist/theming/runtime.d.ts +9 -3
  68. package/dist/theming/runtime.js +2 -2
  69. package/dist/{timezone-BZe_eUxx.d.ts → timezone-K-ptz3HO.d.ts} +22 -23
  70. package/dist/{types-t9H8qKRw.d.ts → types-BE2sEHKd.d.ts} +1 -1
  71. package/dist/{types-BeoeWV5I.d.ts → types-CvOPXWWZ.d.ts} +6 -5
  72. package/dist/{types-DXstZpNI.d.ts → types-D05dCGma.d.ts} +56 -149
  73. package/dist/types-Dr8sNhER.d.ts +50 -0
  74. package/dist/types.d.ts +5 -5
  75. package/dist/{PublicPageProvider-CIGSujI2.d.ts → usePublicPageContext-vxBlEHO9.d.ts} +294 -151
  76. package/dist/{usePublicRouteParams-MamNgwqe.d.ts → usePublicRouteParams-G3Ks53mk.d.ts} +8 -7
  77. package/dist/utils.d.ts +301 -137
  78. package/dist/utils.js +42 -41
  79. package/dist/{validation-643vUDZW.d.ts → validation-g5n0hDkh.d.ts} +2 -2
  80. package/docs/api/modules.md +542 -549
  81. package/docs/api-reference/components.md +5 -5
  82. package/docs/api-reference/rpc-functions.md +3 -3
  83. package/docs/implementation-guides/data-tables.md +256 -8
  84. package/docs/rbac/RBAC_CONTRACT.md +0 -12
  85. package/docs/standards/2-project-structure-standards.md +12 -74
  86. package/docs/standards/6-security-rbac-standards.md +222 -7
  87. package/docs/standards/7-api-tech-stack-standards.md +91 -3
  88. package/docs/testing/README.md +10 -0
  89. package/docs/testing/test-setup-for-consumers.md +914 -0
  90. package/eslint-config-pace-core.cjs +4 -0
  91. package/package.json +1 -1
  92. package/scripts/eslint-audit.cjs +110 -11
  93. package/src/__mocks__/lucide-react.ts +0 -2
  94. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -2
  95. package/src/__tests__/index.test.ts +532 -0
  96. package/src/__tests__/integration/UserProfile.test.tsx +1 -1
  97. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +10 -8
  98. package/src/__tests__/rls-policies.test.ts +3 -2
  99. package/src/assets/app-icons/admin_favicon.svg +462 -0
  100. package/src/assets/app-icons/base_favicon.svg +85 -0
  101. package/src/assets/app-icons/cake_favicon.svg +68 -0
  102. package/src/assets/app-icons/core_favicon.svg +256 -0
  103. package/src/assets/app-icons/gear_favicon.svg +91 -0
  104. package/src/assets/app-icons/index.ts +83 -0
  105. package/src/assets/app-icons/medi_favicon.svg +92 -0
  106. package/src/assets/app-icons/mint_favicon.svg +83 -0
  107. package/src/assets/app-icons/pace_favicon.svg +49 -0
  108. package/src/assets/app-icons/pump_favicon.svg +68 -0
  109. package/src/assets/app-icons/seed_favicon.svg +91 -0
  110. package/src/assets/app-icons/team_favicon.svg +67 -0
  111. package/src/assets/app-icons/trac_favicon.svg +112 -0
  112. package/src/assets/app-icons/trip_favicon.svg +102 -0
  113. package/src/components/AddressField/AddressField.test.tsx +378 -3
  114. package/src/components/AddressField/AddressField.tsx +2 -2
  115. package/src/components/AddressField/types.ts +2 -2
  116. package/src/components/Alert/Alert.test.tsx +35 -25
  117. package/src/components/Alert/Alert.tsx +8 -8
  118. package/src/components/AppSwitcher/AppSwitcher.test.tsx +1250 -0
  119. package/src/components/AppSwitcher/AppSwitcher.tsx +315 -0
  120. package/src/components/Avatar/Avatar.test.tsx +11 -1
  121. package/src/components/Avatar/Avatar.tsx +3 -2
  122. package/src/components/Badge/Badge.test.tsx +11 -1
  123. package/src/components/Button/Button.test.tsx +13 -3
  124. package/src/components/Calendar/Calendar.test.tsx +523 -131
  125. package/src/components/Calendar/Calendar.tsx +107 -488
  126. package/src/components/Card/Card.test.tsx +220 -249
  127. package/src/components/Checkbox/Checkbox.test.tsx +58 -174
  128. package/src/components/ContextSelector/ContextSelector.tsx +3 -3
  129. package/src/components/ContextSelector/__tests__/ContextSelector.test.tsx +360 -0
  130. package/src/components/DataTable/DataTable.tsx +2 -2
  131. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -1
  132. package/src/components/DataTable/__tests__/DataTable.export.test.tsx +2 -2
  133. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +1 -1
  134. package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +485 -0
  135. package/src/components/DataTable/__tests__/DataTable.test.tsx +2 -2
  136. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +1 -1
  137. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +76 -580
  138. package/src/components/DataTable/__tests__/README.md +1 -1
  139. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +1 -1
  140. package/src/components/DataTable/__tests__/keyboard.test.tsx +1 -1
  141. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +1 -3
  142. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -6
  143. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +14 -6
  144. package/src/components/DataTable/components/ActionButtons.tsx +9 -4
  145. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +3 -3
  146. package/src/components/DataTable/components/ColumnFilter.tsx +2 -7
  147. package/src/components/DataTable/components/DataTableCore.tsx +44 -52
  148. package/src/components/DataTable/components/DataTableLayout.tsx +37 -26
  149. package/src/components/DataTable/components/DataTableModals.tsx +118 -30
  150. package/src/components/DataTable/components/DataTableToolbar.tsx +2 -2
  151. package/src/components/DataTable/components/EditFields.tsx +6 -47
  152. package/src/components/DataTable/components/EditableRow.tsx +8 -8
  153. package/src/components/DataTable/components/EmptyState.tsx +6 -3
  154. package/src/components/DataTable/components/FilterRow.tsx +18 -11
  155. package/src/components/DataTable/components/GroupingDropdown.tsx +0 -1
  156. package/src/components/DataTable/components/ImportModal.tsx +305 -133
  157. package/src/components/DataTable/components/LoadingState.tsx +2 -2
  158. package/src/components/DataTable/components/PaginationControls.tsx +0 -4
  159. package/src/components/DataTable/components/RowComponent.tsx +42 -22
  160. package/src/components/DataTable/components/UnifiedTableBody.tsx +52 -12
  161. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +51 -463
  162. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +122 -116
  163. package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +40 -68
  164. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +9 -137
  165. package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +57 -17
  166. package/src/components/DataTable/components/__tests__/DataTableCore.test.tsx +792 -0
  167. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +24 -65
  168. package/src/components/DataTable/components/__tests__/DataTableLayout.test.tsx +467 -0
  169. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +8 -125
  170. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +528 -56
  171. package/src/components/DataTable/components/__tests__/EditFields.test.tsx +526 -0
  172. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +1 -68
  173. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +8 -25
  174. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +3 -62
  175. package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +9 -14
  176. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +50 -186
  177. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +39 -97
  178. package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +13 -103
  179. package/src/components/DataTable/components/__tests__/RowComponent.test.tsx +629 -0
  180. package/src/components/DataTable/components/__tests__/SortIndicator.test.tsx +135 -0
  181. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +31 -171
  182. package/src/components/DataTable/components/__tests__/cellValueUtils.test.ts +453 -0
  183. package/src/components/DataTable/components/hooks/useImportModalFocus.test.ts +184 -0
  184. package/src/components/DataTable/components/hooks/usePermissionTracking.test.ts +381 -0
  185. package/src/components/DataTable/context/DataTableContext.tsx +9 -10
  186. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +12 -26
  187. package/src/components/DataTable/core/ColumnFactory.ts +3 -3
  188. package/src/components/DataTable/core/ColumnManager.ts +0 -1
  189. package/src/components/DataTable/core/DataManager.ts +4 -2
  190. package/src/components/DataTable/core/LocalDataAdapter.ts +1 -1
  191. package/src/components/DataTable/core/PluginRegistry.ts +2 -2
  192. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +114 -2
  193. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +103 -5
  194. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +57 -0
  195. package/src/components/DataTable/core/__tests__/DataManager.test.ts +63 -0
  196. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +42 -9
  197. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +29 -7
  198. package/src/components/DataTable/core/__tests__/StateManager.test.ts +58 -4
  199. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +16 -21
  200. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +93 -4
  201. package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +227 -54
  202. package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +215 -62
  203. package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +217 -39
  204. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +101 -6
  205. package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +157 -27
  206. package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +80 -0
  207. package/src/components/DataTable/hooks/__tests__/useKeyboardNavigation.test.ts +787 -0
  208. package/src/components/DataTable/hooks/__tests__/useServerSideDataEffect.test.ts +258 -0
  209. package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +298 -23
  210. package/src/components/DataTable/hooks/__tests__/useTableHandlers.test.ts +440 -0
  211. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +12 -9
  212. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +12 -9
  213. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +1 -1
  214. package/src/components/DataTable/hooks/useDataTablePermissions.ts +11 -22
  215. package/src/components/DataTable/hooks/useDataTableState.ts +20 -24
  216. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +5 -5
  217. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +13 -1
  218. package/src/components/DataTable/hooks/useTableColumns.ts +36 -38
  219. package/src/components/DataTable/hooks/useTableHandlers.ts +8 -20
  220. package/src/components/DataTable/index.ts +24 -2
  221. package/src/components/DataTable/types.ts +6 -3
  222. package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +3 -67
  223. package/src/components/DataTable/utils/__tests__/aggregationUtils.test.ts +288 -0
  224. package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +3 -60
  225. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +1 -1
  226. package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +9 -21
  227. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +102 -86
  228. package/src/components/DataTable/utils/__tests__/paginationUtils.test.ts +593 -0
  229. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +33 -49
  230. package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +208 -0
  231. package/src/components/DataTable/utils/a11yUtils.ts +1 -1
  232. package/src/components/DataTable/utils/aggregationUtils.ts +5 -5
  233. package/src/components/DataTable/utils/errorHandling.ts +3 -1
  234. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  235. package/src/components/DataTable/utils/flexibleImport.ts +2 -2
  236. package/src/components/DataTable/utils/hierarchicalSorting.ts +3 -3
  237. package/src/components/DataTable/utils/paginationUtils.ts +1 -1
  238. package/src/components/DataTable/utils/performanceUtils.ts +1 -1
  239. package/src/components/DataTable/utils/selectFieldUtils.ts +127 -0
  240. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +17 -24
  241. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +1 -1
  242. package/src/components/DateTimeField/DateTimeField.test.tsx +2 -15
  243. package/src/components/DateTimeField/DateTimeField.tsx +1 -1
  244. package/src/components/Dialog/Dialog.test.tsx +2007 -407
  245. package/src/components/Dialog/Dialog.tsx +97 -192
  246. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +2 -62
  247. package/src/components/ErrorBoundary/ErrorBoundaryContext.context.ts +17 -0
  248. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +2 -45
  249. package/src/components/ErrorBoundary/ErrorBoundaryContext.types.ts +41 -0
  250. package/src/components/ErrorBoundary/index.ts +3 -4
  251. package/src/components/ErrorBoundary/useErrorBoundaryContext.ts +20 -0
  252. package/src/components/FileDisplay/FileDisplay.test.tsx +454 -222
  253. package/src/components/FileDisplay/FileDisplay.tsx +14 -12
  254. package/src/components/FileDisplay/index.tsx +1 -1
  255. package/src/components/FileUpload/FileUpload.test.tsx +54 -18
  256. package/src/components/FileUpload/FileUpload.tsx +10 -7
  257. package/src/components/FileUpload/index.tsx +1 -1
  258. package/src/components/Footer/Footer.test.tsx +33 -114
  259. package/src/components/Form/Form.test.tsx +388 -68
  260. package/src/components/Form/Form.tsx +57 -42
  261. package/src/components/Header/Header.test.tsx +645 -154
  262. package/src/components/Header/Header.tsx +52 -43
  263. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +35 -76
  264. package/src/components/Input/Input.test.tsx +34 -120
  265. package/src/components/Label/Label.test.tsx +47 -46
  266. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +9 -12
  267. package/src/components/LoginForm/LoginForm.test.tsx +0 -1
  268. package/src/components/NavigationMenu/NavigationMenu.test.tsx +1399 -82
  269. package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
  270. package/src/components/NavigationMenu/__tests__/useNavigationFiltering.test.ts +1934 -0
  271. package/src/components/NavigationMenu/useNavigationFiltering.ts +5 -15
  272. package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +1307 -0
  273. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +47 -46
  274. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +81 -38
  275. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +87 -66
  276. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +245 -39
  277. package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -20
  278. package/src/components/PaceAppLayout/README.md +0 -9
  279. package/src/components/PaceAppLayout/test-setup.tsx +15 -9
  280. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +759 -3
  281. package/src/components/PaceLoginPage/PaceLoginPage.tsx +2 -3
  282. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +1 -1
  283. package/src/components/Progress/Progress.test.tsx +127 -1
  284. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +1196 -4
  285. package/src/components/ProtectedRoute/ProtectedRoute.tsx +24 -6
  286. package/src/components/PublicLayout/PublicLayout.test.tsx +1435 -14
  287. package/src/components/PublicLayout/PublicPageContext.ts +28 -0
  288. package/src/components/PublicLayout/PublicPageLayout.tsx +6 -6
  289. package/src/components/PublicLayout/PublicPageProvider.tsx +2 -41
  290. package/src/components/PublicLayout/usePublicPageContext.ts +36 -0
  291. package/src/components/Select/Select.test.tsx +46 -9
  292. package/src/components/Select/Select.tsx +31 -24
  293. package/src/components/Select/__tests__/context.test.tsx +56 -0
  294. package/src/components/Select/hooks/__tests__/useSelectEvents.test.ts +279 -0
  295. package/src/components/Select/hooks/__tests__/useSelectSearch.test.tsx +295 -0
  296. package/src/components/Select/hooks/__tests__/useSelectState.test.ts +254 -0
  297. package/src/components/Select/hooks/useSelectState.ts +16 -16
  298. package/src/components/Select/types.ts +3 -0
  299. package/src/components/Select/utils/__tests__/text.test.tsx +104 -0
  300. package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +28 -112
  301. package/src/components/Switch/Switch.test.tsx +57 -153
  302. package/src/components/Table/Table.test.tsx +47 -317
  303. package/src/components/Tabs/Tabs.tsx +3 -3
  304. package/src/components/Textarea/Textarea.test.tsx +11 -38
  305. package/src/components/Toast/Toast.test.tsx +78 -569
  306. package/src/components/Tooltip/Tooltip.test.tsx +4 -21
  307. package/src/components/UserMenu/UserMenu.test.tsx +1 -21
  308. package/src/components/UserMenu/UserMenu.tsx +3 -6
  309. package/src/components/__tests__/index.test.ts +346 -0
  310. package/src/components/index.ts +12 -1
  311. package/src/constants/__tests__/performance.test.ts +91 -0
  312. package/src/hooks/__tests__/ServiceHooks.test.tsx +239 -129
  313. package/src/hooks/__tests__/hooks.integration.test.tsx +4 -3
  314. package/src/hooks/__tests__/useApiFetch.unit.test.ts +1 -1
  315. package/src/hooks/__tests__/useAppConfig.unit.test.ts +88 -29
  316. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +282 -98
  317. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +53 -109
  318. package/src/hooks/__tests__/useDataTableState.test.ts +143 -49
  319. package/src/hooks/__tests__/useDebounce.unit.test.ts +94 -19
  320. package/src/hooks/__tests__/useEvents.unit.test.ts +100 -125
  321. package/src/hooks/__tests__/useFileDisplay.test.ts +540 -0
  322. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +1 -4
  323. package/src/hooks/__tests__/useFileUrl.unit.test.ts +27 -247
  324. package/src/hooks/__tests__/useFileUrlCache.test.ts +246 -56
  325. package/src/hooks/__tests__/useFocusManagement.unit.test.ts +442 -68
  326. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +345 -560
  327. package/src/hooks/__tests__/useFormDialog.test.ts +51 -222
  328. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +1 -1
  329. package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +1 -4
  330. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -1
  331. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +1 -1
  332. package/src/hooks/__tests__/usePermissionCache.test.ts +506 -0
  333. package/src/hooks/__tests__/usePreventTabReload.test.ts +255 -36
  334. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +17 -8
  335. package/src/hooks/__tests__/usePublicEvent.test.ts +16 -24
  336. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +12 -4
  337. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +3 -6
  338. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +1 -2
  339. package/src/hooks/__tests__/useQueryCache.test.ts +313 -66
  340. package/src/hooks/__tests__/useSessionDraft.test.ts +496 -103
  341. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +2 -2
  342. package/src/hooks/__tests__/useStorage.unit.test.ts +72 -102
  343. package/src/hooks/__tests__/useToast.test.ts +413 -0
  344. package/src/hooks/__tests__/useToast.unit.test.tsx +1 -1
  345. package/src/hooks/__tests__/useZodForm.unit.test.tsx +175 -21
  346. package/src/hooks/index.ts +13 -1
  347. package/src/hooks/public/usePublicEvent.test.ts +304 -0
  348. package/src/hooks/public/usePublicEvent.ts +11 -11
  349. package/src/hooks/public/usePublicEventLogo.test.ts +655 -120
  350. package/src/hooks/public/usePublicEventLogo.ts +2 -2
  351. package/src/hooks/public/usePublicFileDisplay.test.ts +723 -0
  352. package/src/hooks/public/usePublicFileDisplay.ts +79 -49
  353. package/src/hooks/public/usePublicRouteParams.test.ts +595 -0
  354. package/src/hooks/public/usePublicRouteParams.ts +2 -2
  355. package/src/hooks/services/useAuthService.ts +1 -1
  356. package/src/hooks/services/useEventService.ts +1 -1
  357. package/src/hooks/useAccessibleApps.test.ts +400 -0
  358. package/src/hooks/useAccessibleApps.ts +264 -0
  359. package/src/hooks/useAddressAutocomplete.test.ts +165 -42
  360. package/src/hooks/useAddressAutocomplete.ts +41 -28
  361. package/src/hooks/useAppConfig.ts +13 -3
  362. package/src/hooks/useDataTablePerformance.ts +13 -12
  363. package/src/hooks/useDataTableState.ts +5 -5
  364. package/src/hooks/useEventTheme.test.ts +66 -17
  365. package/src/hooks/useEventTheme.ts +1 -1
  366. package/src/hooks/useEvents.ts +8 -1
  367. package/src/hooks/useFileDisplay.ts +66 -33
  368. package/src/hooks/useFileReference.test.ts +365 -87
  369. package/src/hooks/useFileReference.ts +2 -6
  370. package/src/hooks/useFileUrlCache.ts +4 -1
  371. package/src/hooks/useFormDialog.ts +2 -2
  372. package/src/hooks/useInactivityTracker.ts +3 -3
  373. package/src/hooks/useOrganisationPermissions.test.ts +1 -2
  374. package/src/hooks/useOrganisationPermissions.ts +1 -4
  375. package/src/hooks/useOrganisationSecurity.test.ts +1 -30
  376. package/src/hooks/useOrganisationSecurity.ts +3 -3
  377. package/src/hooks/useOrganisations.ts +1 -1
  378. package/src/hooks/usePerformanceMonitor.ts +1 -1
  379. package/src/hooks/usePermissionCache.ts +2 -6
  380. package/src/hooks/useQueryCache.ts +7 -7
  381. package/src/hooks/useSessionDraft.ts +14 -11
  382. package/src/hooks/useSessionRestoration.ts +1 -1
  383. package/src/hooks/useStorage.ts +75 -40
  384. package/src/hooks/useToast.ts +2 -2
  385. package/src/hooks/useZodForm.ts +3 -3
  386. package/src/icons/__tests__/index.test.ts +133 -0
  387. package/src/icons/index.ts +1 -1
  388. package/src/index.ts +43 -4
  389. package/src/providers/OrganisationProvider.test.tsx +40 -0
  390. package/src/providers/OrganisationProvider.tsx +5 -5
  391. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +7 -12
  392. package/src/providers/__tests__/AuthProvider.test.tsx +22 -91
  393. package/src/providers/__tests__/EventProvider.test.tsx +16 -80
  394. package/src/providers/__tests__/InactivityProvider.test.tsx +29 -173
  395. package/src/providers/__tests__/OrganisationProvider.test.tsx +4 -5
  396. package/src/providers/__tests__/OrganisationProvider.wrapper.test.tsx +591 -0
  397. package/src/providers/__tests__/ProviderLifecycle.test.tsx +80 -196
  398. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +40 -133
  399. package/src/providers/__tests__/index.test.ts +138 -0
  400. package/src/providers/services/AuthServiceContext.ts +27 -0
  401. package/src/providers/services/AuthServiceProvider.tsx +81 -20
  402. package/src/providers/services/EventServiceContext.ts +25 -0
  403. package/src/providers/services/EventServiceProvider.tsx +11 -20
  404. package/src/providers/services/InactivityServiceContext.ts +25 -0
  405. package/src/providers/services/InactivityServiceProvider.tsx +7 -17
  406. package/src/providers/services/OrganisationServiceContext.ts +25 -0
  407. package/src/providers/services/OrganisationServiceProvider.tsx +7 -17
  408. package/src/providers/services/UnifiedAuthContext.ts +99 -0
  409. package/src/providers/services/UnifiedAuthProvider.test.tsx +212 -0
  410. package/src/providers/services/UnifiedAuthProvider.tsx +38 -143
  411. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +61 -95
  412. package/src/providers/services/__tests__/AuthServiceProvider.test.tsx +638 -0
  413. package/src/providers/services/__tests__/EventServiceProvider.test.tsx +839 -0
  414. package/src/providers/services/__tests__/InactivityServiceProvider.test.tsx +662 -0
  415. package/src/providers/services/__tests__/OrganisationServiceProvider.test.tsx +440 -0
  416. package/src/providers/services/__tests__/UnifiedAuthProvider.advanced.test.tsx +435 -0
  417. package/src/providers/services/__tests__/UnifiedAuthProvider.appId.test.tsx +408 -0
  418. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +55 -48
  419. package/src/providers/services/__tests__/contexts.test.tsx +281 -0
  420. package/src/providers/services/__tests__/useUnifiedAuth.test.tsx +251 -0
  421. package/src/providers/services/useUnifiedAuth.ts +29 -0
  422. package/src/rbac/README.md +5 -5
  423. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +9 -14
  424. package/src/rbac/__tests__/audit-batched.test.ts +550 -0
  425. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +1 -14
  426. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +43 -12
  427. package/src/rbac/__tests__/cache-invalidation.test.ts +8 -14
  428. package/src/rbac/__tests__/engine.comprehensive.test.ts +2 -7
  429. package/src/rbac/__tests__/index.test.ts +107 -0
  430. package/src/rbac/__tests__/performance.test.ts +451 -0
  431. package/src/rbac/__tests__/rbac-core.test.tsx +2 -2
  432. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -5
  433. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +1 -7
  434. package/src/rbac/__tests__/rbac-functions.test.ts +0 -1
  435. package/src/rbac/__tests__/rbac-integration.test.ts +0 -1
  436. package/src/rbac/__tests__/scenarios.user-role.test.tsx +21 -32
  437. package/src/rbac/adapters.test.tsx +654 -0
  438. package/src/rbac/adapters.tsx +24 -9
  439. package/src/rbac/api.test.ts +13 -217
  440. package/src/rbac/api.ts +85 -16
  441. package/src/rbac/audit-batched.ts +5 -4
  442. package/src/rbac/audit.test.ts +225 -28
  443. package/src/rbac/audit.ts +22 -17
  444. package/src/rbac/cache-invalidation.ts +18 -15
  445. package/src/rbac/cache.test.ts +123 -63
  446. package/src/rbac/cache.ts +3 -4
  447. package/src/rbac/components/AccessDenied.tsx +20 -18
  448. package/src/rbac/components/NavigationGuard.tsx +10 -8
  449. package/src/rbac/components/PagePermissionGuard.tsx +27 -25
  450. package/src/rbac/components/__tests__/AccessDenied.test.tsx +324 -0
  451. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +242 -71
  452. package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +20 -37
  453. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +18 -17
  454. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +452 -129
  455. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -13
  456. package/src/rbac/config.test.ts +131 -48
  457. package/src/rbac/config.ts +11 -8
  458. package/src/rbac/docs/event-based-apps.md +26 -13
  459. package/src/rbac/engine.test.ts +496 -146
  460. package/src/rbac/engine.ts +53 -13
  461. package/src/rbac/errors.test.ts +99 -87
  462. package/src/rbac/eslint-rules.js +2 -2
  463. package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -5
  464. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +601 -1
  465. package/src/rbac/hooks/permissions/__tests__/useAccessLevel.test.ts +622 -0
  466. package/src/rbac/hooks/permissions/__tests__/useCan.test.ts +798 -0
  467. package/src/rbac/hooks/permissions/__tests__/useMultiplePermissions.test.ts +843 -0
  468. package/src/rbac/hooks/permissions/__tests__/usePermissions.test.ts +545 -0
  469. package/src/rbac/hooks/permissions/useAccessLevel.ts +7 -8
  470. package/src/rbac/hooks/permissions/useCan.ts +12 -10
  471. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +57 -8
  472. package/src/rbac/hooks/permissions/usePermissions.ts +15 -14
  473. package/src/rbac/hooks/useCan.test.ts +319 -3
  474. package/src/rbac/hooks/usePermissions.test.ts +426 -0
  475. package/src/rbac/hooks/usePermissions.ts +5 -7
  476. package/src/rbac/hooks/useRBAC.test.ts +1669 -2
  477. package/src/rbac/hooks/useRBAC.ts +7 -11
  478. package/src/rbac/hooks/useResolvedScope.test.ts +442 -5
  479. package/src/rbac/hooks/useResolvedScope.ts +4 -1
  480. package/src/rbac/hooks/useResourcePermissions.test.ts +538 -1
  481. package/src/rbac/hooks/useResourcePermissions.ts +9 -7
  482. package/src/rbac/hooks/useRoleManagement.test.ts +659 -1
  483. package/src/rbac/hooks/useRoleManagement.ts +16 -12
  484. package/src/rbac/hooks/useSecureSupabase.ts +11 -12
  485. package/src/rbac/index.ts +32 -32
  486. package/src/rbac/permissions.test.ts +149 -68
  487. package/src/rbac/permissions.ts +0 -3
  488. package/src/rbac/request-deduplication.test.ts +347 -0
  489. package/src/rbac/secureClient.test.ts +112 -159
  490. package/src/rbac/secureClient.ts +46 -26
  491. package/src/rbac/security.test.ts +125 -44
  492. package/src/rbac/security.ts +7 -6
  493. package/src/rbac/types.test.ts +236 -0
  494. package/src/rbac/types.ts +7 -5
  495. package/src/rbac/utils/__tests__/clientSecurity.test.ts +192 -0
  496. package/src/rbac/utils/__tests__/contextValidator.test.ts +1 -3
  497. package/src/rbac/utils/__tests__/deep-equal.test.ts +23 -0
  498. package/src/rbac/utils/__tests__/eventContext.test.ts +10 -57
  499. package/src/rbac/utils/clientSecurity.ts +6 -4
  500. package/src/rbac/utils/contextValidator.ts +1 -2
  501. package/src/rbac/utils/eventContext.ts +2 -2
  502. package/src/services/AuthService.ts +13 -11
  503. package/src/services/EventService.ts +4 -5
  504. package/src/services/OrganisationService.ts +13 -30
  505. package/src/services/__tests__/AuthService.edge-cases.test.ts +746 -0
  506. package/src/services/__tests__/AuthService.restoreSession.test.ts +23 -3
  507. package/src/services/__tests__/AuthService.test.ts +4 -8
  508. package/src/services/__tests__/BaseService.edge-cases.test.ts +506 -0
  509. package/src/services/__tests__/BaseService.test.ts +49 -0
  510. package/src/services/__tests__/EventService.edge-cases.test.ts +633 -0
  511. package/src/services/__tests__/EventService.eventColours.test.ts +0 -12
  512. package/src/services/__tests__/EventService.test.ts +0 -7
  513. package/src/services/__tests__/InactivityService.edge-cases.test.ts +492 -0
  514. package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -5
  515. package/src/services/__tests__/OrganisationService.edge-cases.test.ts +633 -0
  516. package/src/services/base/BaseService.test.ts +214 -0
  517. package/src/services/interfaces/IOrganisationService.ts +0 -1
  518. package/src/services/interfaces/__tests__/IAuthService.test.ts +190 -0
  519. package/src/services/interfaces/__tests__/IEventService.test.ts +176 -0
  520. package/src/services/interfaces/__tests__/IInactivityService.test.ts +183 -0
  521. package/src/services/interfaces/__tests__/IOrganisationService.test.ts +207 -0
  522. package/src/styles/core.css +1 -0
  523. package/src/theming/__tests__/runtime.test.ts +29 -94
  524. package/src/theming/parseEventColours.ts +18 -9
  525. package/src/theming/runtime.ts +1 -5
  526. package/src/types/__tests__/core.test.ts +397 -0
  527. package/src/types/__tests__/database-generated.test.ts +78 -0
  528. package/src/types/__tests__/file-reference.test.ts +270 -366
  529. package/src/types/__tests__/guards.test.ts +26 -26
  530. package/src/types/__tests__/index.test.ts +265 -0
  531. package/src/types/__tests__/type-validation.test.ts +3 -3
  532. package/src/types/__tests__/validation.test.ts +0 -2
  533. package/src/types/auth.ts +0 -1
  534. package/src/types/database.generated.ts +9 -9
  535. package/src/types/event.ts +1 -1
  536. package/src/types/rpc-responses.ts +33 -0
  537. package/src/types/supabase.ts +1 -2
  538. package/src/types/vitest-globals.d.ts +1 -1
  539. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +64 -77
  540. package/src/utils/__tests__/dynamicUtils.unit.test.ts +13 -0
  541. package/src/utils/__tests__/formatDate.unit.test.ts +1 -1
  542. package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -1
  543. package/src/utils/__tests__/logger.unit.test.ts +1 -1
  544. package/src/utils/__tests__/performanceBenchmark.test.ts +1 -2
  545. package/src/utils/__tests__/performanceBudgets.unit.test.ts +48 -13
  546. package/src/utils/__tests__/request-deduplication.test.ts +349 -0
  547. package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -1
  548. package/src/utils/__tests__/timezone.test.ts +1 -1
  549. package/src/utils/__tests__/validation.unit.test.ts +1 -2
  550. package/src/utils/__tests__/validationUtils.unit.test.ts +1 -1
  551. package/src/utils/app/appConfig.test.ts +235 -0
  552. package/src/utils/app/appIdResolver.test.ts +188 -20
  553. package/src/utils/app/appNameResolver.test.ts +18 -10
  554. package/src/utils/app/appNameResolver.ts +11 -9
  555. package/src/utils/app/appPortMap.test.ts +125 -0
  556. package/src/utils/app/appPortMap.ts +51 -0
  557. package/src/utils/app/buildAppUrl.test.ts +273 -0
  558. package/src/utils/app/buildAppUrl.ts +114 -0
  559. package/src/utils/audit/audit.test.ts +354 -39
  560. package/src/utils/context/organisationContext.test.ts +10 -4
  561. package/src/utils/context/organisationContext.ts +5 -5
  562. package/src/utils/context/sessionTracking.test.ts +354 -0
  563. package/src/utils/core/__tests__/cn.test.ts +66 -0
  564. package/src/utils/core/__tests__/debugLogger.test.ts +113 -0
  565. package/src/utils/core/__tests__/logger.test.ts +217 -0
  566. package/src/utils/core/debugLogger.ts +15 -8
  567. package/src/utils/core/logger.ts +20 -16
  568. package/src/utils/device/deviceFingerprint.test.ts +8 -5
  569. package/src/utils/device/deviceFingerprint.ts +3 -3
  570. package/src/utils/dynamic/__tests__/dynamicUtils.test.ts +185 -0
  571. package/src/utils/dynamic/__tests__/lazyLoad.test.tsx +156 -0
  572. package/src/utils/dynamic/createLazyComponent.tsx +38 -0
  573. package/src/utils/dynamic/dynamicUtils.ts +6 -6
  574. package/src/utils/dynamic/lazyLoad.tsx +8 -36
  575. package/src/utils/dynamic/papaparseLoader.ts +7 -0
  576. package/src/utils/file-reference/__tests__/file-reference.test.ts +583 -145
  577. package/src/utils/file-reference/index.ts +0 -1
  578. package/src/utils/formatting/formatDate.test.ts +22 -148
  579. package/src/utils/formatting/formatDateTime.test.ts +41 -119
  580. package/src/utils/formatting/formatDateTimeTimezone.test.ts +40 -84
  581. package/src/utils/formatting/formatNumber.test.ts +259 -0
  582. package/src/utils/formatting/formatTime.test.ts +36 -128
  583. package/src/utils/formatting/formatting.ts +1 -1
  584. package/src/utils/google-places/googlePlacesUtils.test.ts +72 -3
  585. package/src/utils/google-places/googlePlacesUtils.ts +15 -2
  586. package/src/utils/google-places/loadGoogleMapsScript.test.ts +58 -1
  587. package/src/utils/google-places/loadGoogleMapsScript.ts +2 -1
  588. package/src/utils/index.ts +52 -11
  589. package/src/utils/location/location.test.ts +18 -115
  590. package/src/utils/performance/__tests__/bundleAnalysis.test.ts +148 -0
  591. package/src/utils/performance/__tests__/performanceBenchmark.test.ts +251 -0
  592. package/src/utils/performance/__tests__/performanceBudgets.test.ts +241 -0
  593. package/src/utils/performance/bundleAnalysis.ts +16 -22
  594. package/src/utils/performance/performanceBenchmark.ts +12 -4
  595. package/src/utils/performance/performanceBudgets.ts +9 -6
  596. package/src/utils/permissions/__tests__/permissionTypes.test.ts +149 -0
  597. package/src/utils/permissions/permissionUtils.test.ts +20 -42
  598. package/src/utils/persistence/__tests__/keyDerivation.test.ts +180 -9
  599. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +164 -16
  600. package/src/utils/persistence/sensitiveFieldDetection.ts +2 -2
  601. package/src/utils/request-deduplication.ts +6 -4
  602. package/src/utils/security/auth-utils.ts +7 -7
  603. package/src/utils/security/secureDataAccess.test.ts +22 -191
  604. package/src/utils/security/secureErrors.test.ts +163 -0
  605. package/src/utils/security/secureStorage.test.ts +156 -0
  606. package/src/utils/security/secureStorage.ts +1 -1
  607. package/src/utils/security/security.test.ts +204 -0
  608. package/src/utils/security/securityMonitor.test.ts +90 -0
  609. package/src/utils/security/securityMonitor.ts +1 -1
  610. package/src/utils/storage/__tests__/config.unit.test.ts +239 -0
  611. package/src/utils/storage/__tests__/index.unit.test.ts +64 -12
  612. package/src/utils/storage/helpers.test.ts +757 -430
  613. package/src/utils/storage/helpers.ts +1 -2
  614. package/src/utils/storage/{index.ts → storageUtils.ts} +1 -36
  615. package/src/utils/storage/types.ts +2 -2
  616. package/src/utils/supabase/createBaseClient.test.ts +201 -0
  617. package/src/utils/supabase/createBaseClient.ts +27 -8
  618. package/src/utils/timezone/timezone.test.ts +25 -43
  619. package/src/utils/validation/__tests__/common.test.ts +115 -0
  620. package/src/utils/validation/__tests__/csrf.test.ts +65 -0
  621. package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +27 -7
  622. package/src/utils/validation/__tests__/passwordSchema.test.ts +164 -0
  623. package/src/utils/validation/__tests__/schema.test.ts +127 -0
  624. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +76 -3
  625. package/src/utils/validation/__tests__/user.test.ts +173 -0
  626. package/src/utils/validation/__tests__/validation.test.ts +197 -0
  627. package/src/utils/validation/__tests__/validationUtils.test.ts +265 -43
  628. package/src/utils/validation/htmlSanitization.ts +27 -31
  629. package/src/utils/validation/schema.ts +6 -3
  630. package/src/utils/validation/sqlInjectionProtection.ts +2 -2
  631. package/src/vite-env.d.ts +6 -0
  632. package/dist/DataTable-DRUIgtUH.d.ts +0 -166
  633. package/dist/UnifiedAuthProvider-7SNDOWYD.js +0 -7
  634. package/dist/audit-MYQXYZFU.js +0 -3
  635. package/dist/chunk-7ILTDCL2.js +0 -80
  636. package/dist/chunk-EF2UGZWY.js +0 -611
  637. package/dist/chunk-FEJLJNWA.js +0 -181
  638. package/dist/chunk-GS5672WG.js +0 -2003
  639. package/dist/chunk-S6ZQKDY6.js +0 -62
  640. package/dist/chunk-Z2FNRKF3.js +0 -994
  641. package/dist/useToast-AyaT-x7p.d.ts +0 -68
  642. package/src/components/DataTable/components/index.ts +0 -16
  643. package/src/components/DataTable/core/index.ts +0 -1
  644. package/src/components/DataTable/hooks/index.ts +0 -13
  645. package/src/components/DataTable/utils/index.ts +0 -9
  646. package/src/components/PublicLayout/index.ts +0 -32
  647. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
  648. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
  649. package/src/hooks/public/index.ts +0 -36
  650. package/src/hooks/usePermissionCache.test.ts +0 -536
  651. package/src/rbac/__tests__/isSuperAdmin.real.test.ts +0 -82
  652. package/src/rbac/audit-enhanced.ts +0 -384
  653. package/src/rbac/compliance/database-validator.ts +0 -165
  654. package/src/rbac/compliance/index.ts +0 -48
  655. package/src/rbac/compliance/pattern-detector.ts +0 -553
  656. package/src/rbac/compliance/quick-fix-suggestions.ts +0 -209
  657. package/src/rbac/compliance/runtime-compliance.ts +0 -99
  658. package/src/rbac/compliance/setup-validator.ts +0 -131
  659. package/src/rbac/components/index.ts +0 -26
  660. package/src/rbac/hooks/index.ts +0 -34
  661. package/src/rbac/hooks/permissions/index.ts +0 -4
  662. package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
  663. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -490
  664. package/src/utils/app/appNameResolver.simple.test.ts +0 -212
  665. package/src/utils/google-places/index.ts +0 -26
  666. package/src/utils/location/index.ts +0 -16
  667. package/src/utils/storage/__tests__/helpers.unit.test.ts +0 -332
  668. package/src/utils/timezone/index.ts +0 -17
  669. package/src/utils/validation/index.ts +0 -73
@@ -1,13 +1,27 @@
1
+ /**
2
+ * @file DataTableToolbar Component Tests
3
+ * @package @jmruthers/pace-core
4
+ * @module Components/DataTable/Components/__tests__
5
+ * @since 0.4.0
6
+ *
7
+ * Comprehensive test suite for DataTableToolbar component following testing guidelines.
8
+ * Tests cover all major functionality, edge cases, RBAC permissions, and user interactions.
9
+ */
10
+
1
11
  import React from 'react';
2
12
  import { render, screen } from '@testing-library/react';
3
13
  import userEvent from '@testing-library/user-event';
4
14
  import { describe, it, expect, vi, beforeEach } from 'vitest';
5
15
  import { DataTableToolbar } from '../DataTableToolbar';
6
- import type { DataTableFeatureConfig } from '../../types';
16
+ import type { DataTableFeatureConfig, DataTableRBACConfig } from '../../types';
7
17
 
8
18
  vi.mock('../GroupingDropdown', () => ({
9
- GroupingDropdown: ({ onGroupByChange }: any) => (
10
- <button onClick={() => onGroupByChange('grouped')} data-testid="grouping-dropdown">
19
+ GroupingDropdown: ({ onGroupByChange, currentGroupBy }: any) => (
20
+ <button
21
+ onClick={() => onGroupByChange('grouped')}
22
+ data-testid="grouping-dropdown"
23
+ data-current-group={currentGroupBy}
24
+ >
11
25
  Grouping Dropdown
12
26
  </button>
13
27
  ),
@@ -25,17 +39,34 @@ vi.mock('../ColumnVisibilityDropdown', () => ({
25
39
  }));
26
40
 
27
41
  vi.mock('../../Button/Button', () => ({
28
- Button: ({ children, onClick, variant, ...rest }: any) => (
29
- <button onClick={onClick} data-variant={variant} {...rest}>
42
+ Button: ({ children, onClick, variant, disabled, ...rest }: any) => (
43
+ <button onClick={onClick} data-variant={variant} disabled={disabled} {...rest}>
30
44
  {children}
31
45
  </button>
32
46
  ),
33
47
  }));
34
48
 
35
49
  vi.mock('../../Input/Input', () => ({
36
- Input: ({ value, onChange, placeholder, ...rest }: any) => (
37
- <input value={value} onChange={onChange} placeholder={placeholder} {...rest} />
38
- ),
50
+ Input: React.forwardRef(({ value, onChange, placeholder, ...rest }: any, ref: any) => (
51
+ <input
52
+ ref={ref}
53
+ value={value}
54
+ onChange={onChange}
55
+ placeholder={placeholder}
56
+ data-testid="search-input"
57
+ {...rest}
58
+ />
59
+ )),
60
+ }));
61
+
62
+ vi.mock('lucide-react', () => ({
63
+ Search: () => <span data-testid="search-icon">Search</span>,
64
+ Plus: () => <span data-testid="plus-icon">Plus</span>,
65
+ Upload: () => <span data-testid="upload-icon">Upload</span>,
66
+ Download: () => <span data-testid="download-icon">Download</span>,
67
+ Settings2: () => <span data-testid="settings-icon">Settings</span>,
68
+ Filter: () => <span data-testid="filter-icon">Filter</span>,
69
+ Trash2: () => <span data-testid="trash-icon">Trash</span>,
39
70
  }));
40
71
 
41
72
  describe('[component] DataTableToolbar', () => {
@@ -52,17 +83,22 @@ describe('[component] DataTableToolbar', () => {
52
83
  deleteSelected: true,
53
84
  };
54
85
 
55
- const permissions = {
86
+ const baseRBAC: DataTableRBACConfig = {
87
+ pageId: 'test-page',
88
+ pageName: 'Test Page',
89
+ };
90
+
91
+ const basePermissions = {
56
92
  canCreate: { can: true, isLoading: false },
57
93
  canImport: { can: true, isLoading: false },
58
94
  canExport: { can: true, isLoading: false },
59
95
  canDelete: { can: true, isLoading: false },
60
96
  };
61
97
 
62
- const commonProps = {
98
+ const createCommonProps = (overrides: any = {}) => ({
63
99
  features: baseFeatures,
64
- rbac: { pageId: 'test-page' },
65
- permissions,
100
+ rbac: baseRBAC,
101
+ permissions: basePermissions,
66
102
  globalFilter: '',
67
103
  onGlobalFilterChange: vi.fn(),
68
104
  columns: [
@@ -87,71 +123,507 @@ describe('[component] DataTableToolbar', () => {
87
123
  onDeleteSelected: vi.fn(),
88
124
  onToggleFilterRow: vi.fn(),
89
125
  showFilterRow: false,
90
- };
126
+ ...overrides,
127
+ });
91
128
 
92
129
  beforeEach(() => {
93
130
  vi.clearAllMocks();
94
131
  });
95
132
 
96
- it('renders search input and passes global filter changes', async () => {
97
- const onGlobalFilterChange = vi.fn();
133
+ describe('Rendering', () => {
134
+ it('renders search input when search feature is enabled', () => {
135
+ const props = createCommonProps();
136
+ render(<DataTableToolbar {...props} />);
137
+
138
+ const searchInput = screen.getByPlaceholderText('Search...');
139
+ expect(searchInput).toBeInTheDocument();
140
+ expect(searchInput).toHaveAttribute('id', 'table-search');
141
+ });
142
+
143
+ it('does not render search input when search feature is disabled', () => {
144
+ const props = createCommonProps({
145
+ features: { ...baseFeatures, search: false },
146
+ });
147
+ render(<DataTableToolbar {...props} />);
148
+
149
+ expect(screen.queryByTestId('search-input')).not.toBeInTheDocument();
150
+ });
151
+
152
+ it('renders grouping dropdown when grouping feature is enabled', () => {
153
+ const props = createCommonProps();
154
+ render(<DataTableToolbar {...props} />);
155
+
156
+ expect(screen.getByTestId('grouping-dropdown')).toBeInTheDocument();
157
+ });
158
+
159
+ it('does not render grouping dropdown when grouping feature is disabled', () => {
160
+ const props = createCommonProps({
161
+ features: { ...baseFeatures, grouping: false },
162
+ });
163
+ render(<DataTableToolbar {...props} />);
98
164
 
99
- render(<DataTableToolbar {...commonProps} onGlobalFilterChange={onGlobalFilterChange} />);
165
+ expect(screen.queryByTestId('grouping-dropdown')).not.toBeInTheDocument();
166
+ });
100
167
 
101
- const searchInput = screen.getByPlaceholderText('Search...');
102
- await userEvent.type(searchInput, 'alpha');
168
+ it('renders column visibility dropdown when columnVisibility feature is enabled', () => {
169
+ const props = createCommonProps();
170
+ render(<DataTableToolbar {...props} />);
103
171
 
104
- const calls = onGlobalFilterChange.mock.calls.map((call) => call[0]);
105
- expect(calls).toEqual(['a', 'l', 'p', 'h', 'a']);
172
+ expect(screen.getByTestId('column-visibility-dropdown')).toBeInTheDocument();
173
+ });
174
+
175
+ it('renders filter toggle button when filtering feature is enabled', () => {
176
+ const props = createCommonProps();
177
+ render(<DataTableToolbar {...props} />);
178
+
179
+ expect(screen.getByText('Show Filters')).toBeInTheDocument();
180
+ });
181
+
182
+ it('shows "Hide Filters" when filter row is visible', () => {
183
+ const props = createCommonProps({ showFilterRow: true });
184
+ render(<DataTableToolbar {...props} />);
185
+
186
+ expect(screen.getByText('Hide Filters')).toBeInTheDocument();
187
+ });
188
+
189
+ it('renders all action buttons when features and permissions are enabled', () => {
190
+ const props = createCommonProps();
191
+ render(<DataTableToolbar {...props} />);
192
+
193
+ expect(screen.getByText('Add Row')).toBeInTheDocument();
194
+ expect(screen.getByText('Import')).toBeInTheDocument();
195
+ expect(screen.getByText('Export')).toBeInTheDocument();
196
+ });
106
197
  });
107
198
 
108
- it('shows feature controls and triggers handlers with permissions', async () => {
109
- const onDeleteSelected = vi.fn();
110
- const props = {
111
- ...commonProps,
112
- rowSelection: { row1: true },
113
- onDeleteSelected,
114
- showFilterRow: true,
115
- };
199
+ describe('User Interactions', () => {
200
+ it('calls onGlobalFilterChange when search input changes', async () => {
201
+ const user = userEvent.setup();
202
+ const onGlobalFilterChange = vi.fn();
203
+ const props = createCommonProps({ onGlobalFilterChange });
204
+
205
+ render(<DataTableToolbar {...props} />);
206
+
207
+ const searchInput = screen.getByPlaceholderText('Search...');
208
+ await user.type(searchInput, 'test');
209
+
210
+ expect(onGlobalFilterChange).toHaveBeenCalled();
211
+ const calls = onGlobalFilterChange.mock.calls.map((call) => call[0]);
212
+ expect(calls).toContain('t');
213
+ expect(calls).toContain('e');
214
+ expect(calls).toContain('s');
215
+ expect(calls).toContain('t');
216
+ });
217
+
218
+ it('calls onGroupByChange when grouping dropdown is clicked', async () => {
219
+ const user = userEvent.setup();
220
+ const onGroupByChange = vi.fn();
221
+ const props = createCommonProps({ onGroupByChange });
222
+
223
+ render(<DataTableToolbar {...props} />);
224
+
225
+ await user.click(screen.getByTestId('grouping-dropdown'));
226
+
227
+ expect(onGroupByChange).toHaveBeenCalledWith('grouped');
228
+ });
229
+
230
+ it('calls onColumnVisibilityChange when column visibility dropdown is clicked', async () => {
231
+ const user = userEvent.setup();
232
+ const onColumnVisibilityChange = vi.fn();
233
+ const props = createCommonProps({ onColumnVisibilityChange });
234
+
235
+ render(<DataTableToolbar {...props} />);
116
236
 
117
- render(<DataTableToolbar {...props} />);
237
+ await user.click(screen.getByTestId('column-visibility-dropdown'));
118
238
 
119
- await userEvent.click(screen.getByText('Grouping Dropdown'));
120
- expect(props.onGroupByChange).toHaveBeenCalledWith('grouped');
239
+ expect(onColumnVisibilityChange).toHaveBeenCalledWith('column-id', true);
240
+ });
121
241
 
122
- await userEvent.click(screen.getByText('Column Visibility Dropdown'));
123
- expect(props.onColumnVisibilityChange).toHaveBeenCalledWith('column-id', true);
242
+ it('calls onToggleFilterRow when filter toggle button is clicked', async () => {
243
+ const user = userEvent.setup();
244
+ const onToggleFilterRow = vi.fn();
245
+ const props = createCommonProps({ onToggleFilterRow });
124
246
 
125
- await userEvent.click(screen.getByText('Hide Filters'));
126
- expect(props.onToggleFilterRow).toHaveBeenCalled();
247
+ render(<DataTableToolbar {...props} />);
127
248
 
128
- await userEvent.click(screen.getByText('Add Row'));
129
- expect(props.onCreateRow).toHaveBeenCalled();
249
+ await user.click(screen.getByText('Show Filters'));
130
250
 
131
- await userEvent.click(screen.getByText('Import'));
132
- expect(props.onImportClick).toHaveBeenCalled();
251
+ expect(onToggleFilterRow).toHaveBeenCalledTimes(1);
252
+ });
133
253
 
134
- await userEvent.click(screen.getByText('Export'));
135
- expect(props.onExport).toHaveBeenCalled();
254
+ it('calls onCreateRow when Add Row button is clicked', async () => {
255
+ const user = userEvent.setup();
256
+ const onCreateRow = vi.fn();
257
+ const props = createCommonProps({ onCreateRow });
136
258
 
137
- await userEvent.click(screen.getByText('Delete'));
138
- expect(onDeleteSelected).toHaveBeenCalledWith({ row1: true });
259
+ render(<DataTableToolbar {...props} />);
260
+
261
+ await user.click(screen.getByText('Add Row'));
262
+
263
+ expect(onCreateRow).toHaveBeenCalledTimes(1);
264
+ });
265
+
266
+ it('calls onImportClick when Import button is clicked', async () => {
267
+ const user = userEvent.setup();
268
+ const onImportClick = vi.fn();
269
+ const props = createCommonProps({ onImportClick });
270
+
271
+ render(<DataTableToolbar {...props} />);
272
+
273
+ await user.click(screen.getByText('Import'));
274
+
275
+ expect(onImportClick).toHaveBeenCalledTimes(1);
276
+ });
277
+
278
+ it('calls onExport when Export button is clicked', async () => {
279
+ const user = userEvent.setup();
280
+ const onExport = vi.fn();
281
+ const props = createCommonProps({ onExport });
282
+
283
+ render(<DataTableToolbar {...props} />);
284
+
285
+ await user.click(screen.getByText('Export'));
286
+
287
+ expect(onExport).toHaveBeenCalledTimes(1);
288
+ });
289
+
290
+ it('calls onDeleteSelected with rowSelection when Delete button is clicked', async () => {
291
+ const user = userEvent.setup();
292
+ const onDeleteSelected = vi.fn();
293
+ const rowSelection = { 'row-1': true, 'row-2': true };
294
+ const props = createCommonProps({ onDeleteSelected, rowSelection });
295
+
296
+ render(<DataTableToolbar {...props} />);
297
+
298
+ await user.click(screen.getByText('Delete'));
299
+
300
+ expect(onDeleteSelected).toHaveBeenCalledWith(rowSelection);
301
+ });
139
302
  });
140
303
 
141
- it('respects permission gates for creation and deletion', () => {
142
- const props = {
143
- ...commonProps,
144
- permissions: {
145
- ...permissions,
146
- canCreate: { can: false, isLoading: false },
147
- canDelete: { can: false, isLoading: false },
148
- },
149
- rowSelection: { row1: true },
150
- };
304
+ describe('RBAC Permissions', () => {
305
+ it('hides Add Row button when user lacks create permission', () => {
306
+ const props = createCommonProps({
307
+ permissions: {
308
+ ...basePermissions,
309
+ canCreate: { can: false, isLoading: false },
310
+ },
311
+ });
312
+
313
+ render(<DataTableToolbar {...props} />);
314
+
315
+ expect(screen.queryByText('Add Row')).not.toBeInTheDocument();
316
+ });
317
+
318
+ it('shows Add Row button when create permission is loading but can is true', () => {
319
+ const props = createCommonProps({
320
+ permissions: {
321
+ ...basePermissions,
322
+ canCreate: { can: true, isLoading: true },
323
+ },
324
+ });
325
+
326
+ render(<DataTableToolbar {...props} />);
327
+
328
+ // Button renders when can is true, even if loading
329
+ expect(screen.getByText('Add Row')).toBeInTheDocument();
330
+ });
331
+
332
+ it('hides Import button when user lacks import permission', () => {
333
+ const props = createCommonProps({
334
+ permissions: {
335
+ ...basePermissions,
336
+ canImport: { can: false, isLoading: false },
337
+ },
338
+ });
339
+
340
+ render(<DataTableToolbar {...props} />);
341
+
342
+ expect(screen.queryByText('Import')).not.toBeInTheDocument();
343
+ });
344
+
345
+ it('hides Export button when user lacks export permission', () => {
346
+ const props = createCommonProps({
347
+ permissions: {
348
+ ...basePermissions,
349
+ canExport: { can: false, isLoading: false },
350
+ },
351
+ });
352
+
353
+ render(<DataTableToolbar {...props} />);
354
+
355
+ expect(screen.queryByText('Export')).not.toBeInTheDocument();
356
+ });
357
+
358
+ it('hides Delete button when user lacks delete permission', () => {
359
+ const props = createCommonProps({
360
+ permissions: {
361
+ ...basePermissions,
362
+ canDelete: { can: false, isLoading: false },
363
+ },
364
+ rowSelection: { 'row-1': true },
365
+ });
366
+
367
+ render(<DataTableToolbar {...props} />);
368
+
369
+ expect(screen.queryByText('Delete')).not.toBeInTheDocument();
370
+ });
371
+
372
+ it('shows buttons when user has all permissions', () => {
373
+ const props = createCommonProps();
374
+ render(<DataTableToolbar {...props} />);
375
+
376
+ expect(screen.getByText('Add Row')).toBeInTheDocument();
377
+ expect(screen.getByText('Import')).toBeInTheDocument();
378
+ expect(screen.getByText('Export')).toBeInTheDocument();
379
+ });
380
+ });
381
+
382
+ describe('Feature Flags', () => {
383
+ it('hides creation button when creation feature is disabled', () => {
384
+ const props = createCommonProps({
385
+ features: { ...baseFeatures, creation: false },
386
+ });
387
+
388
+ render(<DataTableToolbar {...props} />);
389
+
390
+ expect(screen.queryByText('Add Row')).not.toBeInTheDocument();
391
+ });
392
+
393
+ it('hides import button when import feature is disabled', () => {
394
+ const props = createCommonProps({
395
+ features: { ...baseFeatures, import: false },
396
+ });
397
+
398
+ render(<DataTableToolbar {...props} />);
399
+
400
+ expect(screen.queryByText('Import')).not.toBeInTheDocument();
401
+ });
402
+
403
+ it('hides export button when export feature is disabled', () => {
404
+ const props = createCommonProps({
405
+ features: { ...baseFeatures, export: false },
406
+ });
407
+
408
+ render(<DataTableToolbar {...props} />);
409
+
410
+ expect(screen.queryByText('Export')).not.toBeInTheDocument();
411
+ });
412
+
413
+ it('hides delete button when deleteSelected feature is disabled', () => {
414
+ const props = createCommonProps({
415
+ features: { ...baseFeatures, deleteSelected: false },
416
+ rowSelection: { 'row-1': true },
417
+ });
418
+
419
+ render(<DataTableToolbar {...props} />);
420
+
421
+ expect(screen.queryByText('Delete')).not.toBeInTheDocument();
422
+ });
423
+
424
+ it('hides delete button when deletion feature is disabled', () => {
425
+ const props = createCommonProps({
426
+ features: { ...baseFeatures, deletion: false },
427
+ rowSelection: { 'row-1': true },
428
+ });
429
+
430
+ render(<DataTableToolbar {...props} />);
431
+
432
+ expect(screen.queryByText('Delete')).not.toBeInTheDocument();
433
+ });
434
+
435
+ it('hides delete button when selection feature is disabled', () => {
436
+ const props = createCommonProps({
437
+ features: { ...baseFeatures, selection: false },
438
+ rowSelection: { 'row-1': true },
439
+ });
440
+
441
+ render(<DataTableToolbar {...props} />);
442
+
443
+ expect(screen.queryByText('Delete')).not.toBeInTheDocument();
444
+ });
445
+ });
446
+
447
+ describe('Delete Button State', () => {
448
+ it('disables delete button when no rows are selected', () => {
449
+ const props = createCommonProps({
450
+ rowSelection: {},
451
+ });
452
+
453
+ render(<DataTableToolbar {...props} />);
454
+
455
+ const deleteButton = screen.getByRole('button', { name: /Delete/i });
456
+ expect(deleteButton).toBeDisabled();
457
+ });
458
+
459
+ it('enables delete button when rows are selected', () => {
460
+ const props = createCommonProps({
461
+ rowSelection: { 'row-1': true },
462
+ });
463
+
464
+ render(<DataTableToolbar {...props} />);
465
+
466
+ const deleteButton = screen.getByText('Delete');
467
+ expect(deleteButton).not.toBeDisabled();
468
+ });
469
+
470
+ it('does not render Add Row button when onCreateRow is not provided even with permission', () => {
471
+ const props = createCommonProps({
472
+ onCreateRow: undefined,
473
+ });
474
+
475
+ render(<DataTableToolbar {...props} />);
476
+
477
+ // Button should not render if onCreateRow is missing
478
+ expect(screen.queryByText('Add Row')).not.toBeInTheDocument();
479
+ });
480
+ });
481
+
482
+ describe('Edge Cases', () => {
483
+ it('handles empty columns array', () => {
484
+ const props = createCommonProps({
485
+ columns: [],
486
+ tableColumns: [],
487
+ });
488
+
489
+ expect(() => {
490
+ render(<DataTableToolbar {...props} />);
491
+ }).not.toThrow();
492
+ });
493
+
494
+ it('handles missing onCreateRow callback gracefully', () => {
495
+ const props = createCommonProps({
496
+ onCreateRow: undefined,
497
+ });
498
+
499
+ render(<DataTableToolbar {...props} />);
500
+
501
+ // Button should not render if onCreateRow is missing
502
+ expect(screen.queryByText('Add Row')).not.toBeInTheDocument();
503
+ });
504
+
505
+ it('renders delete button even when onDeleteSelected callback is missing', () => {
506
+ const props = createCommonProps({
507
+ onDeleteSelected: undefined,
508
+ rowSelection: { 'row-1': true },
509
+ });
510
+
511
+ render(<DataTableToolbar {...props} />);
512
+
513
+ // Delete button still renders, but clicking may not work
514
+ expect(screen.getByText('Delete')).toBeInTheDocument();
515
+ });
516
+
517
+ it('handles missing onToggleFilterRow when filtering is enabled', () => {
518
+ const props = createCommonProps({
519
+ onToggleFilterRow: undefined,
520
+ });
521
+
522
+ render(<DataTableToolbar {...props} />);
523
+
524
+ // Filter button should not render if callback is missing
525
+ expect(screen.queryByText('Show Filters')).not.toBeInTheDocument();
526
+ });
527
+
528
+ it('handles rapid filter toggle clicks', async () => {
529
+ const user = userEvent.setup();
530
+ const onToggleFilterRow = vi.fn();
531
+ const props = createCommonProps({ onToggleFilterRow });
532
+
533
+ render(<DataTableToolbar {...props} />);
534
+
535
+ const filterButton = screen.getByText('Show Filters');
536
+ await user.click(filterButton);
537
+ await user.click(filterButton);
538
+ await user.click(filterButton);
539
+
540
+ expect(onToggleFilterRow).toHaveBeenCalledTimes(3);
541
+ });
542
+ });
543
+
544
+ describe('Accessibility', () => {
545
+ it('provides aria-label for search input', () => {
546
+ const props = createCommonProps();
547
+ render(<DataTableToolbar {...props} />);
548
+
549
+ const searchInput = screen.getByPlaceholderText('Search...');
550
+ expect(searchInput).toHaveAttribute('aria-label', 'Search table');
551
+ });
552
+
553
+ it('provides proper button labels', () => {
554
+ const props = createCommonProps();
555
+ render(<DataTableToolbar {...props} />);
556
+
557
+ expect(screen.getByText('Add Row')).toBeInTheDocument();
558
+ expect(screen.getByText('Import')).toBeInTheDocument();
559
+ expect(screen.getByText('Export')).toBeInTheDocument();
560
+ });
561
+ });
562
+
563
+ describe('Combined Scenarios', () => {
564
+ it('renders correctly with minimal features enabled', () => {
565
+ const props = createCommonProps({
566
+ features: {
567
+ search: true,
568
+ grouping: false,
569
+ columnVisibility: false,
570
+ filtering: false,
571
+ creation: false,
572
+ import: false,
573
+ export: false,
574
+ selection: false,
575
+ deletion: false,
576
+ deleteSelected: false,
577
+ },
578
+ });
579
+
580
+ render(<DataTableToolbar {...props} />);
581
+
582
+ expect(screen.getByPlaceholderText('Search...')).toBeInTheDocument();
583
+ expect(screen.queryByTestId('grouping-dropdown')).not.toBeInTheDocument();
584
+ expect(screen.queryByText('Add Row')).not.toBeInTheDocument();
585
+ });
586
+
587
+ it('renders correctly with all features disabled', () => {
588
+ const props = createCommonProps({
589
+ features: {
590
+ search: false,
591
+ grouping: false,
592
+ columnVisibility: false,
593
+ filtering: false,
594
+ creation: false,
595
+ import: false,
596
+ export: false,
597
+ selection: false,
598
+ deletion: false,
599
+ deleteSelected: false,
600
+ },
601
+ });
602
+
603
+ render(<DataTableToolbar {...props} />);
604
+
605
+ expect(screen.queryByTestId('search-input')).not.toBeInTheDocument();
606
+ expect(screen.queryByTestId('grouping-dropdown')).not.toBeInTheDocument();
607
+ });
608
+
609
+ it('handles combination of disabled features and missing permissions', () => {
610
+ const props = createCommonProps({
611
+ features: {
612
+ ...baseFeatures,
613
+ creation: false,
614
+ import: false,
615
+ },
616
+ permissions: {
617
+ ...basePermissions,
618
+ canExport: { can: false, isLoading: false },
619
+ },
620
+ });
151
621
 
152
- render(<DataTableToolbar {...props} />);
622
+ render(<DataTableToolbar {...props} />);
153
623
 
154
- expect(screen.queryByText('Add Row')).not.toBeInTheDocument();
155
- expect(screen.queryByText('Delete')).not.toBeInTheDocument();
624
+ expect(screen.queryByText('Add Row')).not.toBeInTheDocument();
625
+ expect(screen.queryByText('Import')).not.toBeInTheDocument();
626
+ expect(screen.queryByText('Export')).not.toBeInTheDocument();
627
+ });
156
628
  });
157
629
  });