@jmruthers/pace-core 0.6.9 → 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 (665) hide show
  1. package/audit-tool/audits/02-project-structure.cjs +62 -0
  2. package/audit-tool/audits/03-architecture.cjs +145 -19
  3. package/audit-tool/audits/04-code-quality.cjs +86 -1
  4. package/audit-tool/audits/06-security-rbac.cjs +109 -11
  5. package/cursor-rules/02-project-structure.mdc +2 -26
  6. package/cursor-rules/05-styling.mdc +84 -6
  7. package/cursor-rules/06-security-rbac.mdc +124 -1
  8. package/dist/{DataTable-SOAFXIWY.js → DataTable-SAXFG4XI.js} +11 -13
  9. package/dist/{AuthService-DmfO5rGS.d.ts → InactivityServiceProvider-DHryoh6K.d.ts} +24 -249
  10. package/dist/UnifiedAuthProvider-BBD2PS3Q.js +7 -0
  11. package/dist/{UnifiedAuthProvider-CKvHP1MK.d.ts → UnifiedAuthProvider-CiBAl9-s.d.ts} +34 -22
  12. package/dist/{api-7P7DI652.js → api-F47QJ7FX.js} +3 -3
  13. package/dist/assets/app-icons/admin_favicon.svg +462 -0
  14. package/dist/assets/app-icons/base_favicon.svg +85 -0
  15. package/dist/assets/app-icons/cake_favicon.svg +68 -0
  16. package/dist/assets/app-icons/core_favicon.svg +256 -0
  17. package/dist/assets/app-icons/gear_favicon.svg +91 -0
  18. package/dist/assets/app-icons/medi_favicon.svg +92 -0
  19. package/dist/assets/app-icons/mint_favicon.svg +83 -0
  20. package/dist/assets/app-icons/pace_favicon.svg +49 -0
  21. package/dist/assets/app-icons/pump_favicon.svg +68 -0
  22. package/dist/assets/app-icons/seed_favicon.svg +91 -0
  23. package/dist/assets/app-icons/team_favicon.svg +67 -0
  24. package/dist/assets/app-icons/trac_favicon.svg +112 -0
  25. package/dist/assets/app-icons/trip_favicon.svg +102 -0
  26. package/dist/audit-Z6ZZBWLU.js +3 -0
  27. package/dist/chunk-3GWSPISD.js +61 -0
  28. package/dist/{chunk-4DDCYDQ3.js → chunk-66R6RLUZ.js} +12 -27
  29. package/dist/{chunk-FYHN4DD5.js → chunk-7YDC7LMU.js} +80 -8
  30. package/dist/{chunk-S7DKJPLT.js → chunk-BCTXBU6U.js} +22 -17
  31. package/dist/{chunk-TTRFSOKR.js → chunk-BTHN5MKC.js} +4 -4
  32. package/dist/{chunk-A3W6LW53.js → chunk-DDMPHZ3D.js} +6 -18
  33. package/dist/{chunk-MPBLMWVR.js → chunk-FBZ7U3ID.js} +140 -92
  34. package/dist/chunk-FN52B75D.js +246 -0
  35. package/dist/{chunk-5W2A3DRC.js → chunk-JJEYZ3DX.js} +5 -4
  36. package/dist/chunk-KPYQWGFQ.js +183 -0
  37. package/dist/{chunk-C7ZQ5O4C.js → chunk-KSNLMI7N.js} +3 -3
  38. package/dist/chunk-KYURMOQM.js +977 -0
  39. package/dist/{chunk-LX6U42O3.js → chunk-LNHFAF4X.js} +160 -58
  40. package/dist/{chunk-J2U36LHD.js → chunk-MPY44PWB.js} +620 -627
  41. package/dist/{chunk-AHU7G2R5.js → chunk-NIU6DPQV.js} +10 -6
  42. package/dist/{chunk-HF6O3O37.js → chunk-RMLY6KB5.js} +1 -1
  43. package/dist/{chunk-6GLLNA6U.js → chunk-SACF5YSM.js} +1 -1
  44. package/dist/{chunk-5HNSDQWH.js → chunk-TFIPNIPE.js} +865 -532
  45. package/dist/{chunk-OJ4SKRSV.js → chunk-UZNAFKGW.js} +25 -5
  46. package/dist/chunk-W46INAVW.js +1216 -0
  47. package/dist/chunk-X5EAU5G7.js +793 -0
  48. package/dist/{chunk-T5CVK4R3.js → chunk-Y4PF6HIM.js} +110 -64
  49. package/dist/components.d.ts +8 -86
  50. package/dist/components.js +21 -55
  51. package/dist/eslint-rules/rules/05-styling.cjs +507 -0
  52. package/dist/eslint-rules/rules/06-security-rbac.cjs +10 -0
  53. package/dist/{event-CW5YB_2p.d.ts → event-WTAQuGcq.d.ts} +1 -1
  54. package/dist/{functions-lBy5L2ry.d.ts → functions-DH45k8ec.d.ts} +1 -1
  55. package/dist/hooks.d.ts +11 -10
  56. package/dist/hooks.js +69 -44
  57. package/dist/index.d.ts +379 -31
  58. package/dist/index.js +46 -32
  59. package/dist/papaparseLoader-WG2UXQ22.js +7 -0
  60. package/dist/providers.d.ts +28 -14
  61. package/dist/providers.js +5 -5
  62. package/dist/rbac/eslint-rules.js +2 -2
  63. package/dist/rbac/index.d.ts +57 -213
  64. package/dist/rbac/index.js +11 -11
  65. package/dist/theming/runtime.d.ts +9 -3
  66. package/dist/theming/runtime.js +2 -2
  67. package/dist/{timezone-0AyangqX.d.ts → timezone-K-ptz3HO.d.ts} +21 -22
  68. package/dist/{types-t9H8qKRw.d.ts → types-BE2sEHKd.d.ts} +1 -1
  69. package/dist/{types-BeoeWV5I.d.ts → types-CvOPXWWZ.d.ts} +6 -5
  70. package/dist/{types-DXstZpNI.d.ts → types-D05dCGma.d.ts} +56 -149
  71. package/dist/types-Dr8sNhER.d.ts +50 -0
  72. package/dist/types.d.ts +4 -4
  73. package/dist/{PublicPageProvider-CIGSujI2.d.ts → usePublicPageContext-vxBlEHO9.d.ts} +294 -151
  74. package/dist/{usePublicRouteParams-DQLrDqDb.d.ts → usePublicRouteParams-G3Ks53mk.d.ts} +7 -6
  75. package/dist/utils.d.ts +300 -136
  76. package/dist/utils.js +42 -41
  77. package/dist/{validation-643vUDZW.d.ts → validation-g5n0hDkh.d.ts} +2 -2
  78. package/docs/api/modules.md +542 -549
  79. package/docs/api-reference/components.md +5 -5
  80. package/docs/implementation-guides/data-tables.md +190 -8
  81. package/docs/rbac/RBAC_CONTRACT.md +0 -12
  82. package/docs/standards/2-project-structure-standards.md +12 -74
  83. package/docs/standards/6-security-rbac-standards.md +222 -7
  84. package/docs/standards/7-api-tech-stack-standards.md +91 -3
  85. package/docs/testing/README.md +10 -0
  86. package/docs/testing/test-setup-for-consumers.md +914 -0
  87. package/eslint-config-pace-core.cjs +4 -0
  88. package/package.json +1 -1
  89. package/scripts/eslint-audit.cjs +110 -11
  90. package/src/__mocks__/lucide-react.ts +0 -2
  91. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -2
  92. package/src/__tests__/index.test.ts +532 -0
  93. package/src/__tests__/integration/UserProfile.test.tsx +1 -1
  94. package/src/__tests__/rbac/PagePermissionGuard.test.tsx +10 -8
  95. package/src/__tests__/rls-policies.test.ts +3 -2
  96. package/src/assets/app-icons/admin_favicon.svg +462 -0
  97. package/src/assets/app-icons/base_favicon.svg +85 -0
  98. package/src/assets/app-icons/cake_favicon.svg +68 -0
  99. package/src/assets/app-icons/core_favicon.svg +256 -0
  100. package/src/assets/app-icons/gear_favicon.svg +91 -0
  101. package/src/assets/app-icons/index.ts +83 -0
  102. package/src/assets/app-icons/medi_favicon.svg +92 -0
  103. package/src/assets/app-icons/mint_favicon.svg +83 -0
  104. package/src/assets/app-icons/pace_favicon.svg +49 -0
  105. package/src/assets/app-icons/pump_favicon.svg +68 -0
  106. package/src/assets/app-icons/seed_favicon.svg +91 -0
  107. package/src/assets/app-icons/team_favicon.svg +67 -0
  108. package/src/assets/app-icons/trac_favicon.svg +112 -0
  109. package/src/assets/app-icons/trip_favicon.svg +102 -0
  110. package/src/components/AddressField/AddressField.test.tsx +378 -3
  111. package/src/components/AddressField/AddressField.tsx +2 -2
  112. package/src/components/AddressField/types.ts +2 -2
  113. package/src/components/Alert/Alert.test.tsx +35 -25
  114. package/src/components/Alert/Alert.tsx +8 -8
  115. package/src/components/AppSwitcher/AppSwitcher.test.tsx +1250 -0
  116. package/src/components/AppSwitcher/AppSwitcher.tsx +315 -0
  117. package/src/components/Avatar/Avatar.test.tsx +11 -1
  118. package/src/components/Avatar/Avatar.tsx +3 -2
  119. package/src/components/Badge/Badge.test.tsx +11 -1
  120. package/src/components/Button/Button.test.tsx +13 -3
  121. package/src/components/Calendar/Calendar.test.tsx +523 -131
  122. package/src/components/Calendar/Calendar.tsx +107 -488
  123. package/src/components/Card/Card.test.tsx +220 -249
  124. package/src/components/Checkbox/Checkbox.test.tsx +58 -174
  125. package/src/components/ContextSelector/ContextSelector.tsx +3 -3
  126. package/src/components/ContextSelector/__tests__/ContextSelector.test.tsx +360 -0
  127. package/src/components/DataTable/DataTable.tsx +2 -2
  128. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -1
  129. package/src/components/DataTable/__tests__/DataTable.export.test.tsx +2 -2
  130. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +1 -1
  131. package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +16 -14
  132. package/src/components/DataTable/__tests__/DataTable.test.tsx +2 -2
  133. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +1 -1
  134. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +76 -580
  135. package/src/components/DataTable/__tests__/README.md +1 -1
  136. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +1 -1
  137. package/src/components/DataTable/__tests__/keyboard.test.tsx +1 -1
  138. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +1 -3
  139. package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -6
  140. package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +14 -6
  141. package/src/components/DataTable/components/ActionButtons.tsx +9 -4
  142. package/src/components/DataTable/components/BulkOperationsDropdown.tsx +3 -3
  143. package/src/components/DataTable/components/ColumnFilter.tsx +2 -7
  144. package/src/components/DataTable/components/DataTableCore.tsx +44 -52
  145. package/src/components/DataTable/components/DataTableLayout.tsx +37 -26
  146. package/src/components/DataTable/components/DataTableModals.tsx +118 -30
  147. package/src/components/DataTable/components/DataTableToolbar.tsx +2 -2
  148. package/src/components/DataTable/components/EditFields.tsx +6 -47
  149. package/src/components/DataTable/components/EditableRow.tsx +8 -8
  150. package/src/components/DataTable/components/EmptyState.tsx +6 -3
  151. package/src/components/DataTable/components/FilterRow.tsx +18 -11
  152. package/src/components/DataTable/components/GroupingDropdown.tsx +0 -1
  153. package/src/components/DataTable/components/ImportModal.tsx +305 -133
  154. package/src/components/DataTable/components/LoadingState.tsx +2 -2
  155. package/src/components/DataTable/components/PaginationControls.tsx +0 -4
  156. package/src/components/DataTable/components/RowComponent.tsx +42 -22
  157. package/src/components/DataTable/components/UnifiedTableBody.tsx +52 -12
  158. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +51 -463
  159. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +122 -116
  160. package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +40 -68
  161. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +9 -137
  162. package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +57 -17
  163. package/src/components/DataTable/components/__tests__/DataTableCore.test.tsx +792 -0
  164. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +24 -65
  165. package/src/components/DataTable/components/__tests__/DataTableLayout.test.tsx +467 -0
  166. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +8 -125
  167. package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +528 -56
  168. package/src/components/DataTable/components/__tests__/EditFields.test.tsx +526 -0
  169. package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +1 -68
  170. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +8 -25
  171. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +3 -62
  172. package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +9 -14
  173. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +50 -186
  174. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +39 -97
  175. package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +13 -103
  176. package/src/components/DataTable/components/__tests__/RowComponent.test.tsx +629 -0
  177. package/src/components/DataTable/components/__tests__/SortIndicator.test.tsx +135 -0
  178. package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +31 -171
  179. package/src/components/DataTable/components/__tests__/cellValueUtils.test.ts +453 -0
  180. package/src/components/DataTable/components/hooks/useImportModalFocus.test.ts +184 -0
  181. package/src/components/DataTable/components/hooks/usePermissionTracking.test.ts +381 -0
  182. package/src/components/DataTable/context/DataTableContext.tsx +9 -10
  183. package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +12 -26
  184. package/src/components/DataTable/core/ColumnFactory.ts +3 -3
  185. package/src/components/DataTable/core/ColumnManager.ts +0 -1
  186. package/src/components/DataTable/core/DataManager.ts +4 -2
  187. package/src/components/DataTable/core/LocalDataAdapter.ts +1 -1
  188. package/src/components/DataTable/core/PluginRegistry.ts +2 -2
  189. package/src/components/DataTable/core/__tests__/ActionManager.test.ts +114 -2
  190. package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +103 -5
  191. package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +57 -0
  192. package/src/components/DataTable/core/__tests__/DataManager.test.ts +63 -0
  193. package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +42 -9
  194. package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +29 -7
  195. package/src/components/DataTable/core/__tests__/StateManager.test.ts +58 -4
  196. package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +16 -21
  197. package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +93 -4
  198. package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +227 -54
  199. package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +215 -62
  200. package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +217 -39
  201. package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +101 -6
  202. package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +157 -27
  203. package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +80 -0
  204. package/src/components/DataTable/hooks/__tests__/useKeyboardNavigation.test.ts +787 -0
  205. package/src/components/DataTable/hooks/__tests__/useServerSideDataEffect.test.ts +258 -0
  206. package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +128 -77
  207. package/src/components/DataTable/hooks/__tests__/useTableHandlers.test.ts +440 -0
  208. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +12 -9
  209. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +12 -9
  210. package/src/components/DataTable/hooks/useDataTableConfiguration.ts +1 -1
  211. package/src/components/DataTable/hooks/useDataTablePermissions.ts +11 -22
  212. package/src/components/DataTable/hooks/useDataTableState.ts +20 -24
  213. package/src/components/DataTable/hooks/useKeyboardNavigation.ts +5 -5
  214. package/src/components/DataTable/hooks/useServerSideDataEffect.ts +13 -1
  215. package/src/components/DataTable/hooks/useTableColumns.ts +15 -39
  216. package/src/components/DataTable/hooks/useTableHandlers.ts +8 -20
  217. package/src/components/DataTable/index.ts +24 -2
  218. package/src/components/DataTable/types.ts +6 -3
  219. package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +3 -67
  220. package/src/components/DataTable/utils/__tests__/aggregationUtils.test.ts +288 -0
  221. package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +3 -60
  222. package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +1 -1
  223. package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +9 -21
  224. package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +102 -86
  225. package/src/components/DataTable/utils/__tests__/paginationUtils.test.ts +593 -0
  226. package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +33 -49
  227. package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +1 -0
  228. package/src/components/DataTable/utils/a11yUtils.ts +1 -1
  229. package/src/components/DataTable/utils/aggregationUtils.ts +5 -5
  230. package/src/components/DataTable/utils/errorHandling.ts +3 -1
  231. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  232. package/src/components/DataTable/utils/flexibleImport.ts +2 -2
  233. package/src/components/DataTable/utils/hierarchicalSorting.ts +3 -3
  234. package/src/components/DataTable/utils/paginationUtils.ts +1 -1
  235. package/src/components/DataTable/utils/performanceUtils.ts +1 -1
  236. package/src/components/DataTable/utils/selectFieldUtils.ts +0 -7
  237. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +17 -24
  238. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +1 -1
  239. package/src/components/DateTimeField/DateTimeField.test.tsx +2 -15
  240. package/src/components/DateTimeField/DateTimeField.tsx +1 -1
  241. package/src/components/Dialog/Dialog.test.tsx +2007 -407
  242. package/src/components/Dialog/Dialog.tsx +97 -192
  243. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +2 -62
  244. package/src/components/ErrorBoundary/ErrorBoundaryContext.context.ts +17 -0
  245. package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +2 -45
  246. package/src/components/ErrorBoundary/ErrorBoundaryContext.types.ts +41 -0
  247. package/src/components/ErrorBoundary/index.ts +3 -4
  248. package/src/components/ErrorBoundary/useErrorBoundaryContext.ts +20 -0
  249. package/src/components/FileDisplay/FileDisplay.test.tsx +454 -222
  250. package/src/components/FileDisplay/FileDisplay.tsx +14 -12
  251. package/src/components/FileDisplay/index.tsx +1 -1
  252. package/src/components/FileUpload/FileUpload.test.tsx +54 -18
  253. package/src/components/FileUpload/FileUpload.tsx +10 -7
  254. package/src/components/FileUpload/index.tsx +1 -1
  255. package/src/components/Footer/Footer.test.tsx +33 -114
  256. package/src/components/Form/Form.test.tsx +388 -68
  257. package/src/components/Form/Form.tsx +57 -42
  258. package/src/components/Header/Header.test.tsx +645 -154
  259. package/src/components/Header/Header.tsx +52 -43
  260. package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +35 -76
  261. package/src/components/Input/Input.test.tsx +34 -120
  262. package/src/components/Label/Label.test.tsx +47 -46
  263. package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +9 -12
  264. package/src/components/LoginForm/LoginForm.test.tsx +0 -1
  265. package/src/components/NavigationMenu/NavigationMenu.test.tsx +1399 -82
  266. package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
  267. package/src/components/NavigationMenu/__tests__/useNavigationFiltering.test.ts +1934 -0
  268. package/src/components/NavigationMenu/useNavigationFiltering.ts +5 -15
  269. package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +1307 -0
  270. package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +47 -46
  271. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +81 -38
  272. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +87 -66
  273. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +245 -39
  274. package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -20
  275. package/src/components/PaceAppLayout/README.md +0 -9
  276. package/src/components/PaceAppLayout/test-setup.tsx +15 -9
  277. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +759 -3
  278. package/src/components/PaceLoginPage/PaceLoginPage.tsx +2 -3
  279. package/src/components/PasswordChange/PasswordChangeForm.test.tsx +1 -1
  280. package/src/components/Progress/Progress.test.tsx +127 -1
  281. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +1196 -4
  282. package/src/components/ProtectedRoute/ProtectedRoute.tsx +24 -6
  283. package/src/components/PublicLayout/PublicLayout.test.tsx +1435 -14
  284. package/src/components/PublicLayout/PublicPageContext.ts +28 -0
  285. package/src/components/PublicLayout/PublicPageLayout.tsx +6 -6
  286. package/src/components/PublicLayout/PublicPageProvider.tsx +2 -41
  287. package/src/components/PublicLayout/usePublicPageContext.ts +36 -0
  288. package/src/components/Select/Select.test.tsx +46 -9
  289. package/src/components/Select/Select.tsx +31 -24
  290. package/src/components/Select/__tests__/context.test.tsx +56 -0
  291. package/src/components/Select/hooks/__tests__/useSelectEvents.test.ts +279 -0
  292. package/src/components/Select/hooks/__tests__/useSelectSearch.test.tsx +295 -0
  293. package/src/components/Select/hooks/__tests__/useSelectState.test.ts +254 -0
  294. package/src/components/Select/hooks/useSelectState.ts +16 -16
  295. package/src/components/Select/types.ts +3 -0
  296. package/src/components/Select/utils/__tests__/text.test.tsx +104 -0
  297. package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +28 -112
  298. package/src/components/Switch/Switch.test.tsx +57 -153
  299. package/src/components/Table/Table.test.tsx +47 -317
  300. package/src/components/Tabs/Tabs.tsx +3 -3
  301. package/src/components/Textarea/Textarea.test.tsx +11 -38
  302. package/src/components/Toast/Toast.test.tsx +78 -569
  303. package/src/components/Tooltip/Tooltip.test.tsx +4 -21
  304. package/src/components/UserMenu/UserMenu.test.tsx +1 -21
  305. package/src/components/UserMenu/UserMenu.tsx +0 -1
  306. package/src/components/__tests__/index.test.ts +346 -0
  307. package/src/components/index.ts +12 -1
  308. package/src/constants/__tests__/performance.test.ts +91 -0
  309. package/src/hooks/__tests__/ServiceHooks.test.tsx +239 -129
  310. package/src/hooks/__tests__/hooks.integration.test.tsx +4 -3
  311. package/src/hooks/__tests__/useApiFetch.unit.test.ts +1 -1
  312. package/src/hooks/__tests__/useAppConfig.unit.test.ts +88 -29
  313. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +282 -98
  314. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +53 -109
  315. package/src/hooks/__tests__/useDataTableState.test.ts +143 -49
  316. package/src/hooks/__tests__/useDebounce.unit.test.ts +94 -19
  317. package/src/hooks/__tests__/useEvents.unit.test.ts +100 -125
  318. package/src/hooks/__tests__/useFileDisplay.test.ts +540 -0
  319. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +1 -4
  320. package/src/hooks/__tests__/useFileUrl.unit.test.ts +27 -247
  321. package/src/hooks/__tests__/useFileUrlCache.test.ts +246 -56
  322. package/src/hooks/__tests__/useFocusManagement.unit.test.ts +442 -68
  323. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +345 -560
  324. package/src/hooks/__tests__/useFormDialog.test.ts +51 -222
  325. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +1 -1
  326. package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +1 -4
  327. package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -1
  328. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +1 -1
  329. package/src/hooks/__tests__/usePermissionCache.test.ts +506 -0
  330. package/src/hooks/__tests__/usePreventTabReload.test.ts +255 -36
  331. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +17 -8
  332. package/src/hooks/__tests__/usePublicEvent.test.ts +16 -24
  333. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +12 -4
  334. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +3 -6
  335. package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +1 -2
  336. package/src/hooks/__tests__/useQueryCache.test.ts +313 -66
  337. package/src/hooks/__tests__/useSessionDraft.test.ts +496 -103
  338. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +2 -2
  339. package/src/hooks/__tests__/useStorage.unit.test.ts +72 -102
  340. package/src/hooks/__tests__/useToast.test.ts +413 -0
  341. package/src/hooks/__tests__/useToast.unit.test.tsx +1 -1
  342. package/src/hooks/__tests__/useZodForm.unit.test.tsx +175 -21
  343. package/src/hooks/index.ts +13 -1
  344. package/src/hooks/public/usePublicEvent.test.ts +304 -0
  345. package/src/hooks/public/usePublicEvent.ts +11 -11
  346. package/src/hooks/public/usePublicEventLogo.test.ts +655 -120
  347. package/src/hooks/public/usePublicEventLogo.ts +2 -2
  348. package/src/hooks/public/usePublicFileDisplay.test.ts +723 -0
  349. package/src/hooks/public/usePublicFileDisplay.ts +79 -49
  350. package/src/hooks/public/usePublicRouteParams.test.ts +595 -0
  351. package/src/hooks/public/usePublicRouteParams.ts +2 -2
  352. package/src/hooks/services/useAuthService.ts +1 -1
  353. package/src/hooks/services/useEventService.ts +1 -1
  354. package/src/hooks/useAccessibleApps.test.ts +400 -0
  355. package/src/hooks/useAccessibleApps.ts +264 -0
  356. package/src/hooks/useAddressAutocomplete.test.ts +165 -42
  357. package/src/hooks/useAddressAutocomplete.ts +41 -28
  358. package/src/hooks/useAppConfig.ts +13 -3
  359. package/src/hooks/useDataTablePerformance.ts +13 -12
  360. package/src/hooks/useDataTableState.ts +5 -5
  361. package/src/hooks/useEventTheme.test.ts +66 -17
  362. package/src/hooks/useEventTheme.ts +1 -1
  363. package/src/hooks/useEvents.ts +8 -1
  364. package/src/hooks/useFileDisplay.ts +66 -33
  365. package/src/hooks/useFileReference.test.ts +365 -87
  366. package/src/hooks/useFileReference.ts +2 -6
  367. package/src/hooks/useFileUrlCache.ts +4 -1
  368. package/src/hooks/useFormDialog.ts +2 -2
  369. package/src/hooks/useInactivityTracker.ts +3 -3
  370. package/src/hooks/useOrganisationPermissions.test.ts +1 -2
  371. package/src/hooks/useOrganisationPermissions.ts +1 -4
  372. package/src/hooks/useOrganisationSecurity.test.ts +1 -30
  373. package/src/hooks/useOrganisationSecurity.ts +3 -3
  374. package/src/hooks/useOrganisations.ts +1 -1
  375. package/src/hooks/usePerformanceMonitor.ts +1 -1
  376. package/src/hooks/usePermissionCache.ts +2 -6
  377. package/src/hooks/useQueryCache.ts +7 -7
  378. package/src/hooks/useSessionDraft.ts +14 -11
  379. package/src/hooks/useSessionRestoration.ts +1 -1
  380. package/src/hooks/useStorage.ts +75 -40
  381. package/src/hooks/useToast.ts +2 -2
  382. package/src/hooks/useZodForm.ts +3 -3
  383. package/src/icons/__tests__/index.test.ts +133 -0
  384. package/src/icons/index.ts +1 -1
  385. package/src/index.ts +43 -4
  386. package/src/providers/OrganisationProvider.test.tsx +40 -0
  387. package/src/providers/OrganisationProvider.tsx +5 -5
  388. package/src/providers/UnifiedAuthProvider.smoke.test.tsx +7 -12
  389. package/src/providers/__tests__/AuthProvider.test.tsx +22 -91
  390. package/src/providers/__tests__/EventProvider.test.tsx +16 -80
  391. package/src/providers/__tests__/InactivityProvider.test.tsx +29 -173
  392. package/src/providers/__tests__/OrganisationProvider.test.tsx +4 -5
  393. package/src/providers/__tests__/OrganisationProvider.wrapper.test.tsx +591 -0
  394. package/src/providers/__tests__/ProviderLifecycle.test.tsx +80 -196
  395. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +40 -133
  396. package/src/providers/__tests__/index.test.ts +138 -0
  397. package/src/providers/services/AuthServiceContext.ts +27 -0
  398. package/src/providers/services/AuthServiceProvider.tsx +81 -20
  399. package/src/providers/services/EventServiceContext.ts +25 -0
  400. package/src/providers/services/EventServiceProvider.tsx +11 -20
  401. package/src/providers/services/InactivityServiceContext.ts +25 -0
  402. package/src/providers/services/InactivityServiceProvider.tsx +7 -17
  403. package/src/providers/services/OrganisationServiceContext.ts +25 -0
  404. package/src/providers/services/OrganisationServiceProvider.tsx +7 -17
  405. package/src/providers/services/UnifiedAuthContext.ts +99 -0
  406. package/src/providers/services/UnifiedAuthProvider.test.tsx +212 -0
  407. package/src/providers/services/UnifiedAuthProvider.tsx +38 -143
  408. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +61 -95
  409. package/src/providers/services/__tests__/AuthServiceProvider.test.tsx +638 -0
  410. package/src/providers/services/__tests__/EventServiceProvider.test.tsx +839 -0
  411. package/src/providers/services/__tests__/InactivityServiceProvider.test.tsx +662 -0
  412. package/src/providers/services/__tests__/OrganisationServiceProvider.test.tsx +440 -0
  413. package/src/providers/services/__tests__/UnifiedAuthProvider.advanced.test.tsx +435 -0
  414. package/src/providers/services/__tests__/UnifiedAuthProvider.appId.test.tsx +408 -0
  415. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +55 -48
  416. package/src/providers/services/__tests__/contexts.test.tsx +281 -0
  417. package/src/providers/services/__tests__/useUnifiedAuth.test.tsx +251 -0
  418. package/src/providers/services/useUnifiedAuth.ts +29 -0
  419. package/src/rbac/README.md +5 -5
  420. package/src/rbac/__tests__/adapters.comprehensive.test.tsx +9 -14
  421. package/src/rbac/__tests__/audit-batched.test.ts +550 -0
  422. package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +1 -14
  423. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +43 -12
  424. package/src/rbac/__tests__/cache-invalidation.test.ts +8 -14
  425. package/src/rbac/__tests__/engine.comprehensive.test.ts +2 -7
  426. package/src/rbac/__tests__/index.test.ts +107 -0
  427. package/src/rbac/__tests__/performance.test.ts +451 -0
  428. package/src/rbac/__tests__/rbac-core.test.tsx +2 -2
  429. package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -5
  430. package/src/rbac/__tests__/rbac-engine-simplified.test.ts +1 -7
  431. package/src/rbac/__tests__/rbac-functions.test.ts +0 -1
  432. package/src/rbac/__tests__/rbac-integration.test.ts +0 -1
  433. package/src/rbac/__tests__/scenarios.user-role.test.tsx +21 -32
  434. package/src/rbac/adapters.test.tsx +654 -0
  435. package/src/rbac/adapters.tsx +24 -9
  436. package/src/rbac/api.test.ts +13 -217
  437. package/src/rbac/api.ts +85 -16
  438. package/src/rbac/audit-batched.ts +5 -4
  439. package/src/rbac/audit.test.ts +225 -28
  440. package/src/rbac/audit.ts +22 -17
  441. package/src/rbac/cache-invalidation.ts +18 -15
  442. package/src/rbac/cache.test.ts +123 -63
  443. package/src/rbac/cache.ts +3 -4
  444. package/src/rbac/components/AccessDenied.tsx +20 -18
  445. package/src/rbac/components/NavigationGuard.tsx +10 -8
  446. package/src/rbac/components/PagePermissionGuard.tsx +27 -25
  447. package/src/rbac/components/__tests__/AccessDenied.test.tsx +324 -0
  448. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +242 -71
  449. package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +20 -37
  450. package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +18 -17
  451. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +452 -129
  452. package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -13
  453. package/src/rbac/config.test.ts +131 -48
  454. package/src/rbac/config.ts +11 -8
  455. package/src/rbac/docs/event-based-apps.md +26 -13
  456. package/src/rbac/engine.test.ts +496 -146
  457. package/src/rbac/engine.ts +53 -13
  458. package/src/rbac/errors.test.ts +99 -87
  459. package/src/rbac/eslint-rules.js +2 -2
  460. package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -5
  461. package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +601 -1
  462. package/src/rbac/hooks/permissions/__tests__/useAccessLevel.test.ts +622 -0
  463. package/src/rbac/hooks/permissions/__tests__/useCan.test.ts +798 -0
  464. package/src/rbac/hooks/permissions/__tests__/useMultiplePermissions.test.ts +843 -0
  465. package/src/rbac/hooks/permissions/__tests__/usePermissions.test.ts +545 -0
  466. package/src/rbac/hooks/permissions/useAccessLevel.ts +7 -8
  467. package/src/rbac/hooks/permissions/useCan.ts +12 -10
  468. package/src/rbac/hooks/permissions/useMultiplePermissions.ts +57 -8
  469. package/src/rbac/hooks/permissions/usePermissions.ts +15 -14
  470. package/src/rbac/hooks/useCan.test.ts +319 -3
  471. package/src/rbac/hooks/usePermissions.test.ts +426 -0
  472. package/src/rbac/hooks/usePermissions.ts +5 -7
  473. package/src/rbac/hooks/useRBAC.test.ts +1669 -2
  474. package/src/rbac/hooks/useRBAC.ts +7 -11
  475. package/src/rbac/hooks/useResolvedScope.test.ts +442 -5
  476. package/src/rbac/hooks/useResolvedScope.ts +4 -1
  477. package/src/rbac/hooks/useResourcePermissions.test.ts +538 -1
  478. package/src/rbac/hooks/useResourcePermissions.ts +9 -7
  479. package/src/rbac/hooks/useRoleManagement.test.ts +659 -1
  480. package/src/rbac/hooks/useRoleManagement.ts +16 -12
  481. package/src/rbac/hooks/useSecureSupabase.ts +11 -12
  482. package/src/rbac/index.ts +32 -32
  483. package/src/rbac/permissions.test.ts +149 -68
  484. package/src/rbac/permissions.ts +0 -3
  485. package/src/rbac/request-deduplication.test.ts +347 -0
  486. package/src/rbac/secureClient.test.ts +112 -159
  487. package/src/rbac/secureClient.ts +46 -26
  488. package/src/rbac/security.test.ts +125 -44
  489. package/src/rbac/security.ts +7 -6
  490. package/src/rbac/types.test.ts +236 -0
  491. package/src/rbac/types.ts +7 -5
  492. package/src/rbac/utils/__tests__/clientSecurity.test.ts +192 -0
  493. package/src/rbac/utils/__tests__/contextValidator.test.ts +1 -3
  494. package/src/rbac/utils/__tests__/deep-equal.test.ts +23 -0
  495. package/src/rbac/utils/__tests__/eventContext.test.ts +10 -57
  496. package/src/rbac/utils/clientSecurity.ts +6 -4
  497. package/src/rbac/utils/contextValidator.ts +1 -2
  498. package/src/rbac/utils/eventContext.ts +2 -2
  499. package/src/services/AuthService.ts +13 -11
  500. package/src/services/EventService.ts +4 -5
  501. package/src/services/OrganisationService.ts +13 -30
  502. package/src/services/__tests__/AuthService.edge-cases.test.ts +746 -0
  503. package/src/services/__tests__/AuthService.restoreSession.test.ts +23 -3
  504. package/src/services/__tests__/AuthService.test.ts +4 -8
  505. package/src/services/__tests__/BaseService.edge-cases.test.ts +506 -0
  506. package/src/services/__tests__/BaseService.test.ts +49 -0
  507. package/src/services/__tests__/EventService.edge-cases.test.ts +633 -0
  508. package/src/services/__tests__/EventService.eventColours.test.ts +0 -12
  509. package/src/services/__tests__/EventService.test.ts +0 -7
  510. package/src/services/__tests__/InactivityService.edge-cases.test.ts +492 -0
  511. package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -5
  512. package/src/services/__tests__/OrganisationService.edge-cases.test.ts +633 -0
  513. package/src/services/base/BaseService.test.ts +214 -0
  514. package/src/services/interfaces/IOrganisationService.ts +0 -1
  515. package/src/services/interfaces/__tests__/IAuthService.test.ts +190 -0
  516. package/src/services/interfaces/__tests__/IEventService.test.ts +176 -0
  517. package/src/services/interfaces/__tests__/IInactivityService.test.ts +183 -0
  518. package/src/services/interfaces/__tests__/IOrganisationService.test.ts +207 -0
  519. package/src/styles/core.css +1 -0
  520. package/src/theming/__tests__/runtime.test.ts +29 -94
  521. package/src/theming/parseEventColours.ts +18 -9
  522. package/src/theming/runtime.ts +1 -5
  523. package/src/types/__tests__/core.test.ts +397 -0
  524. package/src/types/__tests__/database-generated.test.ts +78 -0
  525. package/src/types/__tests__/file-reference.test.ts +270 -366
  526. package/src/types/__tests__/guards.test.ts +26 -26
  527. package/src/types/__tests__/index.test.ts +265 -0
  528. package/src/types/__tests__/type-validation.test.ts +3 -3
  529. package/src/types/__tests__/validation.test.ts +0 -2
  530. package/src/types/auth.ts +0 -1
  531. package/src/types/event.ts +1 -1
  532. package/src/types/rpc-responses.ts +33 -0
  533. package/src/types/supabase.ts +1 -2
  534. package/src/types/vitest-globals.d.ts +1 -1
  535. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +64 -77
  536. package/src/utils/__tests__/dynamicUtils.unit.test.ts +13 -0
  537. package/src/utils/__tests__/formatDate.unit.test.ts +1 -1
  538. package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -1
  539. package/src/utils/__tests__/logger.unit.test.ts +1 -1
  540. package/src/utils/__tests__/performanceBenchmark.test.ts +1 -2
  541. package/src/utils/__tests__/performanceBudgets.unit.test.ts +48 -13
  542. package/src/utils/__tests__/request-deduplication.test.ts +349 -0
  543. package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -1
  544. package/src/utils/__tests__/timezone.test.ts +1 -1
  545. package/src/utils/__tests__/validation.unit.test.ts +1 -2
  546. package/src/utils/__tests__/validationUtils.unit.test.ts +1 -1
  547. package/src/utils/app/appConfig.test.ts +235 -0
  548. package/src/utils/app/appIdResolver.test.ts +188 -20
  549. package/src/utils/app/appNameResolver.test.ts +18 -10
  550. package/src/utils/app/appNameResolver.ts +11 -9
  551. package/src/utils/app/appPortMap.test.ts +125 -0
  552. package/src/utils/app/appPortMap.ts +51 -0
  553. package/src/utils/app/buildAppUrl.test.ts +273 -0
  554. package/src/utils/app/buildAppUrl.ts +114 -0
  555. package/src/utils/audit/audit.test.ts +354 -39
  556. package/src/utils/context/organisationContext.test.ts +10 -4
  557. package/src/utils/context/organisationContext.ts +5 -5
  558. package/src/utils/context/sessionTracking.test.ts +354 -0
  559. package/src/utils/core/__tests__/cn.test.ts +66 -0
  560. package/src/utils/core/__tests__/debugLogger.test.ts +113 -0
  561. package/src/utils/core/__tests__/logger.test.ts +217 -0
  562. package/src/utils/core/debugLogger.ts +15 -8
  563. package/src/utils/core/logger.ts +20 -16
  564. package/src/utils/device/deviceFingerprint.test.ts +8 -5
  565. package/src/utils/device/deviceFingerprint.ts +3 -3
  566. package/src/utils/dynamic/__tests__/dynamicUtils.test.ts +185 -0
  567. package/src/utils/dynamic/__tests__/lazyLoad.test.tsx +156 -0
  568. package/src/utils/dynamic/createLazyComponent.tsx +38 -0
  569. package/src/utils/dynamic/dynamicUtils.ts +6 -6
  570. package/src/utils/dynamic/lazyLoad.tsx +8 -36
  571. package/src/utils/dynamic/papaparseLoader.ts +7 -0
  572. package/src/utils/file-reference/__tests__/file-reference.test.ts +583 -145
  573. package/src/utils/file-reference/index.ts +0 -1
  574. package/src/utils/formatting/formatDate.test.ts +22 -148
  575. package/src/utils/formatting/formatDateTime.test.ts +41 -119
  576. package/src/utils/formatting/formatDateTimeTimezone.test.ts +40 -84
  577. package/src/utils/formatting/formatNumber.test.ts +259 -0
  578. package/src/utils/formatting/formatTime.test.ts +36 -128
  579. package/src/utils/formatting/formatting.ts +1 -1
  580. package/src/utils/google-places/googlePlacesUtils.test.ts +72 -3
  581. package/src/utils/google-places/googlePlacesUtils.ts +15 -2
  582. package/src/utils/google-places/loadGoogleMapsScript.test.ts +58 -1
  583. package/src/utils/google-places/loadGoogleMapsScript.ts +2 -1
  584. package/src/utils/index.ts +52 -11
  585. package/src/utils/location/location.test.ts +18 -115
  586. package/src/utils/performance/__tests__/bundleAnalysis.test.ts +148 -0
  587. package/src/utils/performance/__tests__/performanceBenchmark.test.ts +251 -0
  588. package/src/utils/performance/__tests__/performanceBudgets.test.ts +241 -0
  589. package/src/utils/performance/bundleAnalysis.ts +16 -22
  590. package/src/utils/performance/performanceBenchmark.ts +12 -4
  591. package/src/utils/performance/performanceBudgets.ts +9 -6
  592. package/src/utils/permissions/__tests__/permissionTypes.test.ts +149 -0
  593. package/src/utils/permissions/permissionUtils.test.ts +20 -42
  594. package/src/utils/persistence/__tests__/keyDerivation.test.ts +180 -9
  595. package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +164 -16
  596. package/src/utils/persistence/sensitiveFieldDetection.ts +2 -2
  597. package/src/utils/request-deduplication.ts +6 -4
  598. package/src/utils/security/auth-utils.ts +7 -7
  599. package/src/utils/security/secureDataAccess.test.ts +22 -191
  600. package/src/utils/security/secureErrors.test.ts +163 -0
  601. package/src/utils/security/secureStorage.test.ts +156 -0
  602. package/src/utils/security/secureStorage.ts +1 -1
  603. package/src/utils/security/security.test.ts +204 -0
  604. package/src/utils/security/securityMonitor.test.ts +90 -0
  605. package/src/utils/security/securityMonitor.ts +1 -1
  606. package/src/utils/storage/__tests__/config.unit.test.ts +239 -0
  607. package/src/utils/storage/__tests__/index.unit.test.ts +64 -12
  608. package/src/utils/storage/helpers.test.ts +757 -430
  609. package/src/utils/storage/helpers.ts +1 -2
  610. package/src/utils/storage/{index.ts → storageUtils.ts} +1 -36
  611. package/src/utils/storage/types.ts +2 -2
  612. package/src/utils/supabase/createBaseClient.test.ts +201 -0
  613. package/src/utils/supabase/createBaseClient.ts +2 -1
  614. package/src/utils/timezone/timezone.test.ts +25 -43
  615. package/src/utils/validation/__tests__/common.test.ts +115 -0
  616. package/src/utils/validation/__tests__/csrf.test.ts +65 -0
  617. package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +27 -7
  618. package/src/utils/validation/__tests__/passwordSchema.test.ts +164 -0
  619. package/src/utils/validation/__tests__/schema.test.ts +127 -0
  620. package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +76 -3
  621. package/src/utils/validation/__tests__/user.test.ts +173 -0
  622. package/src/utils/validation/__tests__/validation.test.ts +197 -0
  623. package/src/utils/validation/__tests__/validationUtils.test.ts +265 -43
  624. package/src/utils/validation/htmlSanitization.ts +27 -31
  625. package/src/utils/validation/schema.ts +6 -3
  626. package/src/utils/validation/sqlInjectionProtection.ts +2 -2
  627. package/src/vite-env.d.ts +6 -0
  628. package/dist/DataTable-DRUIgtUH.d.ts +0 -166
  629. package/dist/UnifiedAuthProvider-7SNDOWYD.js +0 -7
  630. package/dist/audit-MYQXYZFU.js +0 -3
  631. package/dist/chunk-7ILTDCL2.js +0 -80
  632. package/dist/chunk-EF2UGZWY.js +0 -611
  633. package/dist/chunk-FEJLJNWA.js +0 -181
  634. package/dist/chunk-GS5672WG.js +0 -2003
  635. package/dist/chunk-S6ZQKDY6.js +0 -62
  636. package/dist/chunk-Z2FNRKF3.js +0 -994
  637. package/dist/useToast-AyaT-x7p.d.ts +0 -68
  638. package/src/components/DataTable/components/index.ts +0 -16
  639. package/src/components/DataTable/core/index.ts +0 -1
  640. package/src/components/DataTable/hooks/index.ts +0 -13
  641. package/src/components/DataTable/utils/index.ts +0 -10
  642. package/src/components/PublicLayout/index.ts +0 -32
  643. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
  644. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
  645. package/src/hooks/public/index.ts +0 -36
  646. package/src/hooks/usePermissionCache.test.ts +0 -536
  647. package/src/rbac/__tests__/isSuperAdmin.real.test.ts +0 -82
  648. package/src/rbac/audit-enhanced.ts +0 -384
  649. package/src/rbac/compliance/database-validator.ts +0 -165
  650. package/src/rbac/compliance/index.ts +0 -48
  651. package/src/rbac/compliance/pattern-detector.ts +0 -553
  652. package/src/rbac/compliance/quick-fix-suggestions.ts +0 -209
  653. package/src/rbac/compliance/runtime-compliance.ts +0 -99
  654. package/src/rbac/compliance/setup-validator.ts +0 -131
  655. package/src/rbac/components/index.ts +0 -26
  656. package/src/rbac/hooks/index.ts +0 -34
  657. package/src/rbac/hooks/permissions/index.ts +0 -4
  658. package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
  659. package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -490
  660. package/src/utils/app/appNameResolver.simple.test.ts +0 -212
  661. package/src/utils/google-places/index.ts +0 -26
  662. package/src/utils/location/index.ts +0 -16
  663. package/src/utils/storage/__tests__/helpers.unit.test.ts +0 -332
  664. package/src/utils/timezone/index.ts +0 -17
  665. package/src/utils/validation/index.ts +0 -73
@@ -1,7 +1,11 @@
1
1
  /**
2
- * @file Card Component Tests
3
- * @description Comprehensive tests for Card component suite
2
+ * @file Integration Tests for Card Component Suite
4
3
  * @package @jmruthers/pace-core
4
+ * @module Components/Card/__tests__
5
+ * @since 1.0.0
6
+ *
7
+ * Integration tests for Card component suite focusing on observable behavior,
8
+ * user interactions, accessibility, and edge cases.
5
9
  */
6
10
 
7
11
  import React from 'react';
@@ -22,49 +26,69 @@ import {
22
26
  } from './Card';
23
27
  import { renderWithProviders } from '../../__tests__/helpers/test-utils';
24
28
 
25
- describe('Card Component Suite', () => {
29
+ // Following testing standards: use timeout parameter to prevent hanging
30
+ const TEST_TIMEOUT = 10000; // 10 seconds per test
31
+
32
+ describe('[integration] Card Component Suite', () => {
26
33
  describe('Card Component', () => {
27
34
  describe('Rendering', () => {
28
- it('renders with default props', () => {
29
- renderWithProviders(<Card>Card content</Card>);
35
+ it('renders with default props, custom className, and HTML attributes', () => {
36
+ const ref = React.createRef<HTMLElement>();
37
+ renderWithProviders(
38
+ <Card
39
+ ref={ref}
40
+ className="custom-class"
41
+ data-testid="test-card"
42
+ aria-label="Test card"
43
+ id="card-1"
44
+ >
45
+ Card content
46
+ </Card>
47
+ );
30
48
  const card = screen.getByRole('article');
31
49
  expect(card).toBeInTheDocument();
32
50
  expect(card).toHaveTextContent('Card content');
33
- });
34
-
35
- it('renders with custom className', () => {
36
- renderWithProviders(<Card className="custom-class">Card content</Card>);
37
- const card = screen.getByRole('article');
38
51
  expect(card).toHaveClass('custom-class');
52
+ expect(card).toHaveAttribute('data-testid', 'test-card');
53
+ expect(card).toHaveAttribute('aria-label', 'Test card');
54
+ expect(card).toHaveAttribute('id', 'card-1');
55
+ expect(ref.current).toBeInstanceOf(HTMLElement);
56
+ expect(ref.current).toHaveTextContent('Card content');
39
57
  });
40
58
 
41
- it('renders with different variants', () => {
42
- const { rerender } = renderWithProviders(<Card variant="default">Default card</Card>);
59
+ it('renders with different variants and sizes', () => {
60
+ const { rerender } = renderWithProviders(<Card variant="default" size="default">Default card</Card>);
43
61
  let card = screen.getByRole('article');
44
62
  expect(card).toHaveClass('shadow-xl');
45
-
46
- rerender(<Card variant="outline">Outline card</Card>);
47
- card = screen.getByRole('article');
48
- expect(card).toHaveClass('border-2');
49
-
50
- rerender(<Card variant="ghost">Ghost card</Card>);
51
- card = screen.getByRole('article');
52
- expect(card).toHaveClass('border-0', 'shadow-none');
53
- });
54
-
55
- it('renders with different sizes', () => {
56
- const { rerender } = renderWithProviders(<Card size="default">Default size</Card>);
57
- let card = screen.getByRole('article');
58
63
  expect(card).not.toHaveClass('text-sm', 'text-lg');
59
64
 
60
- rerender(<Card size="sm">Small card</Card>);
65
+ rerender(<Card variant="outline" size="sm">Outline small card</Card>);
61
66
  card = screen.getByRole('article');
62
- expect(card).toHaveClass('text-sm');
67
+ expect(card).toHaveClass('border-2', 'text-sm');
63
68
 
64
- rerender(<Card size="lg">Large card</Card>);
69
+ rerender(<Card variant="ghost" size="lg">Ghost large card</Card>);
65
70
  card = screen.getByRole('article');
66
- expect(card).toHaveClass('text-lg');
67
- });
71
+ expect(card).toHaveClass('border-0', 'shadow-none', 'text-lg');
72
+ }, TEST_TIMEOUT);
73
+
74
+ it('renders all variant and size combinations', () => {
75
+ const variants: Array<'default' | 'outline' | 'ghost'> = ['default', 'outline', 'ghost'];
76
+ const sizes: Array<'sm' | 'default' | 'lg'> = ['sm', 'default', 'lg'];
77
+
78
+ variants.forEach(variant => {
79
+ sizes.forEach(size => {
80
+ const { unmount } = renderWithProviders(
81
+ <Card variant={variant} size={size}>
82
+ {variant} {size} card
83
+ </Card>
84
+ );
85
+ const card = screen.getByRole('article');
86
+ expect(card).toBeInTheDocument();
87
+ expect(card).toHaveTextContent(`${variant} ${size} card`);
88
+ unmount();
89
+ });
90
+ });
91
+ }, TEST_TIMEOUT);
68
92
 
69
93
  it('renders with children content', () => {
70
94
  renderWithProviders(
@@ -75,131 +99,117 @@ describe('Card Component Suite', () => {
75
99
  );
76
100
  expect(screen.getByText('Child content')).toBeInTheDocument();
77
101
  expect(screen.getByText('More content')).toBeInTheDocument();
78
- });
102
+ }, TEST_TIMEOUT);
79
103
 
80
- it('forwards ref correctly', () => {
81
- const ref = React.createRef<HTMLElement>();
82
- renderWithProviders(<Card ref={ref}>Card content</Card>);
83
- expect(ref.current).toBeInstanceOf(HTMLElement);
84
- expect(ref.current).toHaveTextContent('Card content');
85
- });
104
+ it('renders with isLink prop for link styling', () => {
105
+ renderWithProviders(<Card isLink={true}>Link card</Card>);
106
+ const card = screen.getByRole('article');
107
+ expect(card).toHaveClass('cursor-pointer', 'hover:bg-acc-200');
108
+ }, TEST_TIMEOUT);
86
109
 
87
- it('applies all HTML attributes', () => {
110
+ it('renders with link prop for navigation styling', () => {
88
111
  renderWithProviders(
89
- <Card
90
- data-testid="test-card"
91
- aria-label="Test card"
92
- id="card-1"
93
- >
94
- Card content
95
- </Card>
112
+ <Card link="/test-path">Link card</Card>
96
113
  );
97
- const card = screen.getByRole('article');
98
- expect(card).toHaveAttribute('data-testid', 'test-card');
99
- expect(card).toHaveAttribute('aria-label', 'Test card');
100
- expect(card).toHaveAttribute('id', 'card-1');
101
- });
114
+ const card = screen.getByRole('link');
115
+ expect(card).toBeInTheDocument();
116
+ expect(card).toHaveClass('cursor-pointer', 'hover:bg-acc-200');
117
+ expect(card).toHaveAttribute('tabIndex', '0');
118
+ }, TEST_TIMEOUT);
102
119
  });
103
120
 
104
121
  describe('Accessibility', () => {
105
- it('uses semantic article element', () => {
106
- renderWithProviders(<Card>Card content</Card>);
122
+ it('uses semantic article element with proper layout and keyboard support', () => {
123
+ renderWithProviders(<Card tabIndex={0}>Card content</Card>);
107
124
  const card = screen.getByRole('article');
108
125
  expect(card).toBeInTheDocument();
109
- });
110
-
111
- it('has proper grid layout classes', () => {
112
- renderWithProviders(<Card>Card content</Card>);
113
- const card = screen.getByRole('article');
114
126
  expect(card).toHaveClass('grid', 'grid-rows-[auto_1fr_auto]');
115
- });
127
+ expect(card).toHaveAttribute('tabIndex', '0');
128
+ }, TEST_TIMEOUT);
116
129
 
117
- it('supports keyboard navigation', () => {
130
+ it('supports keyboard navigation with tabIndex', async () => {
131
+ const user = userEvent.setup();
118
132
  renderWithProviders(<Card tabIndex={0}>Card content</Card>);
119
133
  const card = screen.getByRole('article');
120
- expect(card).toHaveAttribute('tabIndex', '0');
121
- });
134
+
135
+ card.focus();
136
+ expect(document.activeElement).toBe(card);
137
+
138
+ await user.tab();
139
+ // Focus should move away from card
140
+ }, TEST_TIMEOUT);
141
+
142
+ it('handles Enter key on focusable card', async () => {
143
+ const user = userEvent.setup();
144
+ const handleClick = vi.fn();
145
+ renderWithProviders(
146
+ <Card tabIndex={0} onClick={handleClick}>
147
+ Card content
148
+ </Card>
149
+ );
150
+ const card = screen.getByRole('article');
151
+ card.focus();
152
+ await user.keyboard('{Enter}');
153
+ // Note: Enter key on article doesn't trigger click by default, but test structure is correct
154
+ }, TEST_TIMEOUT);
155
+
156
+ it('maintains proper semantic structure for screen readers', () => {
157
+ renderWithProviders(
158
+ <Card>
159
+ <CardHeader>
160
+ <CardTitle>Title</CardTitle>
161
+ </CardHeader>
162
+ <CardContent>Content</CardContent>
163
+ </Card>
164
+ );
165
+
166
+ expect(screen.getByRole('article')).toBeInTheDocument();
167
+ expect(screen.getByRole('banner')).toBeInTheDocument();
168
+ expect(screen.getByRole('main')).toBeInTheDocument();
169
+ expect(screen.getByRole('heading')).toBeInTheDocument();
170
+ }, TEST_TIMEOUT);
122
171
  });
123
172
  });
124
173
 
125
174
  describe('CardHeader Component', () => {
126
175
  describe('Rendering', () => {
127
- it('renders with default props', () => {
128
- renderWithProviders(<CardHeader>Header content</CardHeader>);
176
+ it('renders with default props, custom className, and proper semantic structure', () => {
177
+ const ref = React.createRef<HTMLElement>();
178
+ renderWithProviders(<CardHeader ref={ref} className="custom-header">Header content</CardHeader>);
129
179
  const header = screen.getByRole('banner');
130
180
  expect(header).toBeInTheDocument();
131
181
  expect(header).toHaveTextContent('Header content');
132
- });
133
-
134
- it('renders with custom className', () => {
135
- renderWithProviders(<CardHeader className="custom-header">Header content</CardHeader>);
136
- const header = screen.getByRole('banner');
137
- expect(header).toHaveClass('custom-header');
138
- });
139
-
140
- it('forwards ref correctly', () => {
141
- const ref = React.createRef<HTMLElement>();
142
- renderWithProviders(<CardHeader ref={ref}>Header content</CardHeader>);
143
- expect(ref.current).toBeInstanceOf(HTMLElement);
144
- });
145
-
146
- it('has proper semantic structure', () => {
147
- renderWithProviders(<CardHeader>Header content</CardHeader>);
148
- const header = screen.getByRole('banner');
182
+ expect(header).toHaveClass('custom-header', 'p-6', 'min-w-0', 'w-full');
149
183
  expect(header.tagName).toBe('HEADER');
150
- expect(header).toHaveClass('p-6', 'min-w-0', 'w-full');
184
+ expect(ref.current).toBeInstanceOf(HTMLElement);
151
185
  });
152
186
  });
153
187
  });
154
188
 
155
189
  describe('CardTitle Component', () => {
156
190
  describe('Rendering', () => {
157
- it('renders with default props', () => {
158
- renderWithProviders(<CardTitle>Card Title</CardTitle>);
191
+ it('renders with default props, custom className, and proper semantic structure', () => {
192
+ const ref = React.createRef<HTMLHeadingElement>();
193
+ renderWithProviders(<CardTitle ref={ref} className="custom-title">Card Title</CardTitle>);
159
194
  const title = screen.getByRole('heading', { level: 3 });
160
195
  expect(title).toBeInTheDocument();
161
196
  expect(title).toHaveTextContent('Card Title');
162
- });
163
-
164
- it('renders with custom className', () => {
165
- renderWithProviders(<CardTitle className="custom-title">Card Title</CardTitle>);
166
- const title = screen.getByRole('heading', { level: 3 });
167
197
  expect(title).toHaveClass('custom-title');
168
- });
169
-
170
- it('forwards ref correctly', () => {
171
- const ref = React.createRef<HTMLHeadingElement>();
172
- renderWithProviders(<CardTitle ref={ref}>Card Title</CardTitle>);
173
- expect(ref.current).toBeInstanceOf(HTMLHeadingElement);
174
- });
175
-
176
- it('uses semantic heading element', () => {
177
- renderWithProviders(<CardTitle>Card Title</CardTitle>);
178
- const title = screen.getByRole('heading', { level: 3 });
179
198
  expect(title.tagName).toBe('H3');
180
- expect(title.className).toBe('');
199
+ expect(ref.current).toBeInstanceOf(HTMLHeadingElement);
181
200
  });
182
201
  });
183
202
  });
184
203
 
185
204
  describe('CardDescription Component', () => {
186
205
  describe('Rendering', () => {
187
- it('renders with default props', () => {
188
- renderWithProviders(<CardDescription>Card description</CardDescription>);
206
+ it('renders with default props, custom className, and proper semantic structure', () => {
207
+ const ref = React.createRef<HTMLParagraphElement>();
208
+ renderWithProviders(<CardDescription ref={ref} className="custom-desc">Card description</CardDescription>);
189
209
  const description = screen.getByText('Card description');
190
210
  expect(description).toBeInTheDocument();
191
211
  expect(description.tagName).toBe('P');
192
- });
193
-
194
- it('renders with custom className', () => {
195
- renderWithProviders(<CardDescription className="custom-desc">Card description</CardDescription>);
196
- const description = screen.getByText('Card description');
197
212
  expect(description).toHaveClass('custom-desc');
198
- });
199
-
200
- it('forwards ref correctly', () => {
201
- const ref = React.createRef<HTMLParagraphElement>();
202
- renderWithProviders(<CardDescription ref={ref}>Card description</CardDescription>);
203
213
  expect(ref.current).toBeInstanceOf(HTMLParagraphElement);
204
214
  });
205
215
  });
@@ -207,154 +217,125 @@ describe('Card Component Suite', () => {
207
217
 
208
218
  describe('CardContent Component', () => {
209
219
  describe('Rendering', () => {
210
- it('renders with default props', () => {
211
- renderWithProviders(<CardContent>Card content</CardContent>);
220
+ it('renders with default props, custom className, and proper semantic structure', () => {
221
+ const ref = React.createRef<HTMLElement>();
222
+ renderWithProviders(<CardContent ref={ref} className="custom-content">Card content</CardContent>);
212
223
  const content = screen.getByRole('main');
213
224
  expect(content).toBeInTheDocument();
214
225
  expect(content).toHaveTextContent('Card content');
215
- });
216
-
217
- it('renders with custom className', () => {
218
- renderWithProviders(<CardContent className="custom-content">Card content</CardContent>);
219
- const content = screen.getByRole('main');
220
- expect(content).toHaveClass('custom-content');
221
- });
222
-
223
- it('forwards ref correctly', () => {
224
- const ref = React.createRef<HTMLElement>();
225
- renderWithProviders(<CardContent ref={ref}>Card content</CardContent>);
226
+ expect(content).toHaveClass('custom-content', 'p-6', 'pt-0', 'min-w-0', 'w-full');
226
227
  expect(ref.current).toBeInstanceOf(HTMLElement);
227
228
  });
228
-
229
- it('has proper semantic structure', () => {
230
- renderWithProviders(<CardContent>Card content</CardContent>);
231
- const content = screen.getByRole('main');
232
- expect(content).toHaveClass('p-6', 'pt-0', 'min-w-0', 'w-full');
233
- });
234
229
  });
235
230
  });
236
231
 
237
232
  describe('CardFooter Component', () => {
238
233
  describe('Rendering', () => {
239
- it('renders with default props', () => {
240
- renderWithProviders(<CardFooter>Footer content</CardFooter>);
234
+ it('renders with default props, custom className, and proper semantic structure', () => {
235
+ const ref = React.createRef<HTMLElement>();
236
+ renderWithProviders(<CardFooter ref={ref} className="custom-footer">Footer content</CardFooter>);
241
237
  const footer = screen.getByRole('contentinfo');
242
238
  expect(footer).toBeInTheDocument();
243
239
  expect(footer).toHaveTextContent('Footer content');
244
- });
245
-
246
- it('renders with custom className', () => {
247
- renderWithProviders(<CardFooter className="custom-footer">Footer content</CardFooter>);
248
- const footer = screen.getByRole('contentinfo');
249
- expect(footer).toHaveClass('custom-footer');
250
- });
251
-
252
- it('forwards ref correctly', () => {
253
- const ref = React.createRef<HTMLElement>();
254
- renderWithProviders(<CardFooter ref={ref}>Footer content</CardFooter>);
255
- expect(ref.current).toBeInstanceOf(HTMLElement);
256
- });
257
-
258
- it('has proper semantic structure', () => {
259
- renderWithProviders(<CardFooter>Footer content</CardFooter>);
260
- const footer = screen.getByRole('contentinfo');
240
+ expect(footer).toHaveClass('custom-footer', 'p-6', 'pt-0', 'min-w-0', 'w-full');
261
241
  expect(footer.tagName).toBe('FOOTER');
262
- expect(footer).toHaveClass('p-6', 'pt-0', 'min-w-0', 'w-full');
242
+ expect(ref.current).toBeInstanceOf(HTMLElement);
263
243
  });
264
244
  });
265
245
  });
266
246
 
267
247
  describe('CardActions Component', () => {
268
248
  describe('Rendering', () => {
269
- it('renders with default props', () => {
270
- renderWithProviders(<CardActions>Action buttons</CardActions>);
249
+ it('renders with default props, custom className, proper ARIA attributes, and layout classes', () => {
250
+ const ref = React.createRef<HTMLElement>();
251
+ renderWithProviders(<CardActions ref={ref} className="custom-actions">Action buttons</CardActions>);
271
252
  const actions = screen.getByRole('group', { name: 'Card actions' });
272
253
  expect(actions).toBeInTheDocument();
273
254
  expect(actions).toHaveTextContent('Action buttons');
274
- });
275
-
276
- it('renders with custom className', () => {
277
- renderWithProviders(<CardActions className="custom-actions">Action buttons</CardActions>);
278
- const actions = screen.getByRole('group', { name: 'Card actions' });
279
- expect(actions).toHaveClass('custom-actions');
280
- });
281
-
282
- it('forwards ref correctly', () => {
283
- const ref = React.createRef<HTMLElement>();
284
- renderWithProviders(<CardActions ref={ref}>Action buttons</CardActions>);
285
- expect(ref.current).toBeInstanceOf(HTMLElement);
286
- });
287
-
288
- it('has proper ARIA attributes', () => {
289
- renderWithProviders(<CardActions>Action buttons</CardActions>);
290
- const actions = screen.getByRole('group', { name: 'Card actions' });
255
+ expect(actions).toHaveClass('custom-actions', 'flex', 'gap-2');
291
256
  expect(actions).toHaveAttribute('role', 'group');
292
257
  expect(actions).toHaveAttribute('aria-label', 'Card actions');
293
- });
294
-
295
- it('has proper layout classes', () => {
296
- renderWithProviders(<CardActions>Action buttons</CardActions>);
297
- const actions = screen.getByRole('group', { name: 'Card actions' });
298
- expect(actions).toHaveClass('flex', 'gap-2');
258
+ expect(ref.current).toBeInstanceOf(HTMLElement);
299
259
  });
300
260
  });
301
261
  });
302
262
 
303
263
  describe('HoverCard Component', () => {
304
264
  describe('Rendering', () => {
305
- it('renders with default props', () => {
265
+ it('renders with default props, custom className, and proper semantic structure', () => {
266
+ const ref = React.createRef<HTMLElement>();
306
267
  renderWithProviders(
307
- <HoverCard>
268
+ <HoverCard ref={ref} className="custom-hover">
308
269
  <HoverCardTrigger>Hover me</HoverCardTrigger>
309
270
  <HoverCardContent>Hover content</HoverCardContent>
310
271
  </HoverCard>
311
272
  );
312
273
  expect(screen.getByText('Hover me')).toBeInTheDocument();
313
274
  expect(screen.getByText('Hover content')).toBeInTheDocument();
314
- });
275
+ const hoverCard = screen.getByText('Hover me').closest('section');
276
+ expect(hoverCard).toHaveClass('custom-hover');
277
+ expect(hoverCard).toBeInTheDocument();
278
+ expect(ref.current).toBeInstanceOf(HTMLElement);
279
+ }, TEST_TIMEOUT);
315
280
 
316
- it('renders with custom className', () => {
281
+ it('renders with proper semantic structure (section wrapper)', () => {
317
282
  renderWithProviders(
318
- <HoverCard className="custom-hover">
319
- <HoverCardTrigger>Hover me</HoverCardTrigger>
320
- <HoverCardContent>Hover content</HoverCardContent>
283
+ <HoverCard>
284
+ <HoverCardTrigger>Trigger</HoverCardTrigger>
285
+ <HoverCardContent>Content</HoverCardContent>
321
286
  </HoverCard>
322
287
  );
323
- const hoverCard = screen.getByText('Hover me').closest('section');
324
- expect(hoverCard).toHaveClass('custom-hover');
325
- });
288
+
289
+ const section = screen.getByText('Trigger').closest('section');
290
+ expect(section).toBeInTheDocument();
291
+ expect(section).toHaveClass('relative', 'inline-block');
292
+ }, TEST_TIMEOUT);
293
+ });
326
294
 
327
- it('forwards ref correctly', () => {
328
- const ref = React.createRef<HTMLElement>();
295
+ describe('Accessibility', () => {
296
+ it('has proper ARIA attributes on content', () => {
329
297
  renderWithProviders(
330
- <HoverCard ref={ref}>
331
- <HoverCardTrigger>Hover me</HoverCardTrigger>
332
- <HoverCardContent>Hover content</HoverCardContent>
298
+ <HoverCard>
299
+ <HoverCardTrigger>Trigger</HoverCardTrigger>
300
+ <HoverCardContent>Content</HoverCardContent>
333
301
  </HoverCard>
334
302
  );
335
- expect(ref.current).toBeInstanceOf(HTMLElement);
336
- });
303
+
304
+ const content = screen.getByRole('tooltip');
305
+ expect(content).toBeInTheDocument();
306
+ expect(content).toHaveTextContent('Content');
307
+ }, TEST_TIMEOUT);
337
308
 
338
- it('uses semantic section element', () => {
309
+ it('supports keyboard navigation on trigger', async () => {
310
+ const user = userEvent.setup();
339
311
  renderWithProviders(
340
312
  <HoverCard>
341
- <HoverCardTrigger>Hover me</HoverCardTrigger>
342
- <HoverCardContent>Hover content</HoverCardContent>
313
+ <HoverCardTrigger>Trigger</HoverCardTrigger>
314
+ <HoverCardContent>Content</HoverCardContent>
343
315
  </HoverCard>
344
316
  );
345
- const hoverCard = screen.getByText('Hover me').closest('section');
346
- expect(hoverCard).toBeInTheDocument();
347
- });
317
+
318
+ const trigger = screen.getByRole('button');
319
+ trigger.focus();
320
+ expect(document.activeElement).toBe(trigger);
321
+
322
+ await user.keyboard('{Tab}');
323
+ // Focus should move away
324
+ }, TEST_TIMEOUT);
348
325
  });
349
326
  });
350
327
 
351
328
  describe('HoverCardTrigger Component', () => {
352
329
  describe('Rendering', () => {
353
- it('renders as button by default', () => {
354
- renderWithProviders(<HoverCardTrigger>Click me</HoverCardTrigger>);
330
+ it('renders as button by default with proper attributes and className', () => {
331
+ const ref = React.createRef<HTMLButtonElement>();
332
+ renderWithProviders(<HoverCardTrigger ref={ref} className="custom-trigger">Click me</HoverCardTrigger>);
355
333
  const trigger = screen.getByRole('button');
356
334
  expect(trigger).toBeInTheDocument();
357
335
  expect(trigger).toHaveTextContent('Click me');
336
+ expect(trigger).toHaveClass('custom-trigger', 'cursor-pointer', 'bg-transparent', 'border-0');
337
+ expect(trigger).toHaveAttribute('type', 'button');
338
+ expect(ref.current).toBeInstanceOf(HTMLButtonElement);
358
339
  });
359
340
 
360
341
  it('renders as child element when asChild is true', () => {
@@ -365,29 +346,9 @@ describe('Card Component Suite', () => {
365
346
  );
366
347
  const trigger = screen.getByText('Click me');
367
348
  expect(trigger.tagName).toBe('SPAN');
368
- // The span should be wrapped in a span with cursor-pointer class
369
349
  const wrapper = trigger.parentElement;
370
350
  expect(wrapper).toHaveClass('cursor-pointer');
371
351
  });
372
-
373
- it('renders with custom className', () => {
374
- renderWithProviders(<HoverCardTrigger className="custom-trigger">Click me</HoverCardTrigger>);
375
- const trigger = screen.getByRole('button');
376
- expect(trigger).toHaveClass('custom-trigger');
377
- });
378
-
379
- it('forwards ref correctly', () => {
380
- const ref = React.createRef<HTMLButtonElement>();
381
- renderWithProviders(<HoverCardTrigger ref={ref}>Click me</HoverCardTrigger>);
382
- expect(ref.current).toBeInstanceOf(HTMLButtonElement);
383
- });
384
-
385
- it('has proper button attributes', () => {
386
- renderWithProviders(<HoverCardTrigger>Click me</HoverCardTrigger>);
387
- const trigger = screen.getByRole('button');
388
- expect(trigger).toHaveAttribute('type', 'button');
389
- expect(trigger).toHaveClass('cursor-pointer', 'bg-transparent', 'border-0');
390
- });
391
352
  });
392
353
 
393
354
  describe('Event Handling', () => {
@@ -424,35 +385,15 @@ describe('Card Component Suite', () => {
424
385
 
425
386
  describe('HoverCardContent Component', () => {
426
387
  describe('Rendering', () => {
427
- it('renders with default props', () => {
428
- renderWithProviders(<HoverCardContent>Hover content</HoverCardContent>);
388
+ it('renders with default props, custom className, proper ARIA attributes, and positioning classes', () => {
389
+ const ref = React.createRef<HTMLElement>();
390
+ renderWithProviders(<HoverCardContent ref={ref} className="custom-content">Hover content</HoverCardContent>);
429
391
  const content = screen.getByRole('tooltip');
430
392
  expect(content).toBeInTheDocument();
431
393
  expect(content).toHaveTextContent('Hover content');
432
- });
433
-
434
- it('renders with custom className', () => {
435
- renderWithProviders(<HoverCardContent className="custom-content">Hover content</HoverCardContent>);
436
- const content = screen.getByRole('tooltip');
437
- expect(content).toHaveClass('custom-content');
438
- });
439
-
440
- it('forwards ref correctly', () => {
441
- const ref = React.createRef<HTMLElement>();
442
- renderWithProviders(<HoverCardContent ref={ref}>Hover content</HoverCardContent>);
443
- expect(ref.current).toBeInstanceOf(HTMLElement);
444
- });
445
-
446
- it('has proper ARIA attributes', () => {
447
- renderWithProviders(<HoverCardContent>Hover content</HoverCardContent>);
448
- const content = screen.getByRole('tooltip');
394
+ expect(content).toHaveClass('custom-content', 'absolute', 'z-50', 'min-w-[8rem]');
449
395
  expect(content).toHaveAttribute('role', 'tooltip');
450
- });
451
-
452
- it('has proper positioning classes', () => {
453
- renderWithProviders(<HoverCardContent>Hover content</HoverCardContent>);
454
- const content = screen.getByRole('tooltip');
455
- expect(content).toHaveClass('absolute', 'z-50', 'min-w-[8rem]');
396
+ expect(ref.current).toBeInstanceOf(HTMLElement);
456
397
  });
457
398
  });
458
399
  });
@@ -516,18 +457,48 @@ describe('Card Component Suite', () => {
516
457
  it('handles missing children gracefully', () => {
517
458
  renderWithProviders(<Card />);
518
459
  expect(screen.getByRole('article')).toBeInTheDocument();
519
- });
460
+ }, TEST_TIMEOUT);
520
461
 
521
462
  it('handles invalid props gracefully', () => {
522
463
  // @ts-expect-error Testing invalid prop
523
464
  renderWithProviders(<Card invalidProp="test">Card content</Card>);
524
465
  expect(screen.getByRole('article')).toBeInTheDocument();
525
- });
466
+ }, TEST_TIMEOUT);
526
467
 
527
468
  it('handles null children', () => {
528
469
  renderWithProviders(<Card>{null}</Card>);
529
470
  expect(screen.getByRole('article')).toBeInTheDocument();
530
- });
471
+ }, TEST_TIMEOUT);
472
+
473
+ it('handles empty string children', () => {
474
+ renderWithProviders(<Card>{''}</Card>);
475
+ expect(screen.getByRole('article')).toBeInTheDocument();
476
+ }, TEST_TIMEOUT);
477
+
478
+ it('handles very long content', () => {
479
+ const longContent = 'A'.repeat(1000);
480
+ renderWithProviders(<Card>{longContent}</Card>);
481
+ expect(screen.getByText(longContent)).toBeInTheDocument();
482
+ }, TEST_TIMEOUT);
483
+
484
+ it('handles special characters in content', () => {
485
+ const specialContent = '<script>alert("xss")</script> & "quotes" & <div>HTML</div>';
486
+ renderWithProviders(<Card>{specialContent}</Card>);
487
+ expect(screen.getByText(specialContent)).toBeInTheDocument();
488
+ }, TEST_TIMEOUT);
489
+
490
+ it('handles array of children', () => {
491
+ renderWithProviders(
492
+ <Card>
493
+ {['First', 'Second', 'Third'].map((item, i) => (
494
+ <div key={i}>{item}</div>
495
+ ))}
496
+ </Card>
497
+ );
498
+ expect(screen.getByText('First')).toBeInTheDocument();
499
+ expect(screen.getByText('Second')).toBeInTheDocument();
500
+ expect(screen.getByText('Third')).toBeInTheDocument();
501
+ }, TEST_TIMEOUT);
531
502
  });
532
503
 
533
504
  describe('Integration', () => {