@jmruthers/pace-core 0.5.135 → 0.5.137

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 (544) hide show
  1. package/dist/{DataTable-A36PJG6N.js → DataTable-6M4L6BI2.js} +26 -13
  2. package/dist/{DataTable-C7GaRZye.d.ts → DataTable-CWAZZcXC.d.ts} +1 -1
  3. package/dist/{PublicLoadingSpinner-CUAnTvcg.d.ts → EventLogo-rFL_kRjk.d.ts} +123 -135
  4. package/dist/{UnifiedAuthProvider-BVKmQd9u.d.ts → UnifiedAuthProvider-DJxGTftH.d.ts} +1 -1
  5. package/dist/{UnifiedAuthProvider-CQDZRJIS.js → UnifiedAuthProvider-XIQQ7LVU.js} +5 -5
  6. package/dist/{api-TNIBJWLM.js → api-45XYYO2A.js} +4 -3
  7. package/dist/{audit-T36HM7IM.js → audit-64X3VJXB.js} +3 -2
  8. package/dist/{chunk-F64FFPOZ.js → chunk-22WKWKRX.js} +26 -20
  9. package/dist/chunk-22WKWKRX.js.map +1 -0
  10. package/dist/{chunk-VZ5OR6HD.js → chunk-4C7EXCAR.js} +62 -150
  11. package/dist/chunk-4C7EXCAR.js.map +1 -0
  12. package/dist/{chunk-PYUXFQJ3.js → chunk-56XJ3TU6.js} +2 -2
  13. package/dist/chunk-56XJ3TU6.js.map +1 -0
  14. package/dist/{chunk-CTJRBUX2.js → chunk-6LAAY47Q.js} +2 -2
  15. package/dist/{chunk-UJI6WSMD.js → chunk-7QCC6MCP.js} +90 -3
  16. package/dist/chunk-7QCC6MCP.js.map +1 -0
  17. package/dist/{chunk-66C4BSAY.js → chunk-ANBQRTPX.js} +9 -2
  18. package/dist/chunk-ANBQRTPX.js.map +1 -0
  19. package/dist/{chunk-CQZU6TFE.js → chunk-BCIBECNB.js} +100 -62
  20. package/dist/chunk-BCIBECNB.js.map +1 -0
  21. package/dist/{chunk-GKHF54DI.js → chunk-BESYRHQM.js} +10 -4
  22. package/dist/chunk-BESYRHQM.js.map +1 -0
  23. package/dist/chunk-BJPBT3CU.js +21 -0
  24. package/dist/chunk-BJPBT3CU.js.map +1 -0
  25. package/dist/{chunk-BYXRHAIF.js → chunk-BLCXZEYF.js} +23 -14
  26. package/dist/chunk-BLCXZEYF.js.map +1 -0
  27. package/dist/{chunk-WP5I5GLN.js → chunk-BVYWGZVV.js} +112 -97
  28. package/dist/chunk-BVYWGZVV.js.map +1 -0
  29. package/dist/{chunk-GEVIB2UB.js → chunk-ERISIBYU.js} +14 -5
  30. package/dist/chunk-ERISIBYU.js.map +1 -0
  31. package/dist/{chunk-O3NWNXDY.js → chunk-FMUCXFII.js} +2 -2
  32. package/dist/chunk-FMUCXFII.js.map +1 -0
  33. package/dist/{chunk-GVDR7WNV.js → chunk-HAWZXGR2.js} +334 -614
  34. package/dist/chunk-HAWZXGR2.js.map +1 -0
  35. package/dist/{chunk-ZV77RZMU.js → chunk-INQLMHPF.js} +2 -2
  36. package/dist/chunk-JISYG63F.js +70 -0
  37. package/dist/chunk-JISYG63F.js.map +1 -0
  38. package/dist/{chunk-HMNOSGVA.js → chunk-KYRHUBIU.js} +576 -767
  39. package/dist/chunk-KYRHUBIU.js.map +1 -0
  40. package/dist/{chunk-M6DDYFUD.js → chunk-LS353YLY.js} +19 -16
  41. package/dist/chunk-LS353YLY.js.map +1 -0
  42. package/dist/{chunk-TGIY2AR2.js → chunk-MA6EPSGZ.js} +4 -3
  43. package/dist/{chunk-TGIY2AR2.js.map → chunk-MA6EPSGZ.js.map} +1 -1
  44. package/dist/chunk-OWAG3GSU.js +58 -0
  45. package/dist/chunk-OWAG3GSU.js.map +1 -0
  46. package/dist/{chunk-JCQZ6LA7.js → chunk-Q5QRDWKI.js} +9 -3
  47. package/dist/chunk-Q5QRDWKI.js.map +1 -0
  48. package/dist/chunk-S5OFRT4M.js +94 -0
  49. package/dist/chunk-S5OFRT4M.js.map +1 -0
  50. package/dist/{chunk-3DBFLLLU.js → chunk-SBVILCCA.js} +14 -9
  51. package/dist/chunk-SBVILCCA.js.map +1 -0
  52. package/dist/{chunk-ZYZCRSBD.js → chunk-T6JN6LH6.js} +16 -11
  53. package/dist/chunk-T6JN6LH6.js.map +1 -0
  54. package/dist/chunk-XDNLUEXI.js +138 -0
  55. package/dist/chunk-XDNLUEXI.js.map +1 -0
  56. package/dist/{chunk-3CG5L6RN.js → chunk-YCWDTTUK.js} +90 -75
  57. package/dist/chunk-YCWDTTUK.js.map +1 -0
  58. package/dist/{chunk-5F3NDPJV.js → chunk-ZZ2SS7NI.js} +10 -5
  59. package/dist/chunk-ZZ2SS7NI.js.map +1 -0
  60. package/dist/components.d.ts +7 -287
  61. package/dist/components.js +27 -157
  62. package/dist/components.js.map +1 -1
  63. package/dist/{file-reference-C9isKNPn.d.ts → file-reference-C6Gkn77H.d.ts} +1 -1
  64. package/dist/{formatting-DFcCxUEk.d.ts → formatting-CvUXy2mF.d.ts} +1 -1
  65. package/dist/hooks.d.ts +3 -3
  66. package/dist/hooks.js +21 -16
  67. package/dist/hooks.js.map +1 -1
  68. package/dist/index.d.ts +101 -9
  69. package/dist/index.js +44 -31
  70. package/dist/index.js.map +1 -1
  71. package/dist/providers.d.ts +1 -1
  72. package/dist/providers.js +4 -4
  73. package/dist/rbac/index.js +12 -12
  74. package/dist/schema-DTDZQe2u.d.ts +28 -0
  75. package/dist/styles/index.js +2 -1
  76. package/dist/theming/runtime.d.ts +2 -19
  77. package/dist/theming/runtime.js +2 -1
  78. package/dist/{types-D5rqZQXk.d.ts → types-Dfz9dmVH.d.ts} +12 -1
  79. package/dist/types.d.ts +153 -4
  80. package/dist/types.js +51 -16
  81. package/dist/types.js.map +1 -1
  82. package/dist/{useInactivityTracker-MRUU55XI.js → useInactivityTracker-TO6ZOF35.js} +3 -2
  83. package/dist/{usePublicRouteParams-Dyt1tzI9.d.ts → usePublicRouteParams-B7PabvuH.d.ts} +1 -1
  84. package/dist/utils.d.ts +221 -173
  85. package/dist/utils.js +185 -225
  86. package/dist/utils.js.map +1 -1
  87. package/dist/validation.d.ts +24 -115
  88. package/dist/validation.js +19 -474
  89. package/dist/validation.js.map +1 -1
  90. package/docs/api/classes/ColumnFactory.md +1 -1
  91. package/docs/api/classes/ErrorBoundary.md +6 -6
  92. package/docs/api/classes/InvalidScopeError.md +1 -1
  93. package/docs/api/classes/MissingUserContextError.md +1 -1
  94. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  95. package/docs/api/classes/PermissionDeniedError.md +1 -1
  96. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  97. package/docs/api/classes/RBACAuditManager.md +6 -6
  98. package/docs/api/classes/RBACCache.md +1 -1
  99. package/docs/api/classes/RBACEngine.md +7 -7
  100. package/docs/api/classes/RBACError.md +1 -1
  101. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  102. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  103. package/docs/api/classes/StorageUtils.md +1 -1
  104. package/docs/api/enums/FileCategory.md +1 -1
  105. package/docs/api/interfaces/AggregateConfig.md +4 -4
  106. package/docs/api/interfaces/BadgeProps.md +27 -0
  107. package/docs/api/interfaces/ButtonProps.md +1 -1
  108. package/docs/api/interfaces/CardProps.md +1 -1
  109. package/docs/api/interfaces/ColorPalette.md +1 -1
  110. package/docs/api/interfaces/ColorShade.md +29 -4
  111. package/docs/api/interfaces/DataAccessRecord.md +9 -9
  112. package/docs/api/interfaces/DataRecord.md +1 -1
  113. package/docs/api/interfaces/DataTableAction.md +18 -18
  114. package/docs/api/interfaces/DataTableColumn.md +61 -1
  115. package/docs/api/interfaces/DataTableProps.md +1 -1
  116. package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
  117. package/docs/api/interfaces/EmptyStateConfig.md +5 -5
  118. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +14 -14
  119. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  120. package/docs/api/interfaces/EventLogoProps.md +152 -0
  121. package/docs/api/interfaces/ExportColumn.md +1 -1
  122. package/docs/api/interfaces/ExportOptions.md +8 -8
  123. package/docs/api/interfaces/FileDisplayProps.md +15 -15
  124. package/docs/api/interfaces/FileMetadata.md +1 -1
  125. package/docs/api/interfaces/FileReference.md +1 -1
  126. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  127. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  128. package/docs/api/interfaces/FileUploadProps.md +1 -1
  129. package/docs/api/interfaces/FooterProps.md +1 -1
  130. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  131. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  132. package/docs/api/interfaces/InputProps.md +1 -1
  133. package/docs/api/interfaces/LabelProps.md +1 -1
  134. package/docs/api/interfaces/LoginFormProps.md +1 -1
  135. package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
  136. package/docs/api/interfaces/NavigationContextType.md +9 -9
  137. package/docs/api/interfaces/NavigationGuardProps.md +10 -10
  138. package/docs/api/interfaces/NavigationItem.md +1 -1
  139. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  140. package/docs/api/interfaces/NavigationProviderProps.md +7 -7
  141. package/docs/api/interfaces/Organisation.md +1 -1
  142. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  143. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  144. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  145. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  146. package/docs/api/interfaces/PaceAppLayoutProps.md +27 -27
  147. package/docs/api/interfaces/PaceLoginPageProps.md +4 -4
  148. package/docs/api/interfaces/PageAccessRecord.md +8 -8
  149. package/docs/api/interfaces/PagePermissionContextType.md +8 -8
  150. package/docs/api/interfaces/PagePermissionGuardProps.md +11 -11
  151. package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
  152. package/docs/api/interfaces/PaletteData.md +4 -4
  153. package/docs/api/interfaces/PermissionEnforcerProps.md +11 -11
  154. package/docs/api/interfaces/ProtectedRouteProps.md +6 -6
  155. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  156. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  157. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  158. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  159. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  160. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  161. package/docs/api/interfaces/RBACConfig.md +1 -1
  162. package/docs/api/interfaces/RBACLogger.md +1 -1
  163. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  164. package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
  165. package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
  166. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  167. package/docs/api/interfaces/RouteAccessRecord.md +10 -10
  168. package/docs/api/interfaces/RouteConfig.md +10 -10
  169. package/docs/api/interfaces/SecureDataContextType.md +9 -9
  170. package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
  171. package/docs/api/interfaces/SessionRestorationLoaderProps.md +21 -0
  172. package/docs/api/interfaces/StorageConfig.md +1 -1
  173. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  174. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  175. package/docs/api/interfaces/StorageListOptions.md +1 -1
  176. package/docs/api/interfaces/StorageListResult.md +1 -1
  177. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  178. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  179. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  180. package/docs/api/interfaces/StyleImport.md +1 -1
  181. package/docs/api/interfaces/SwitchProps.md +1 -1
  182. package/docs/api/interfaces/ToastActionElement.md +1 -1
  183. package/docs/api/interfaces/ToastProps.md +1 -1
  184. package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
  185. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  186. package/docs/api/interfaces/UseInactivityTrackerOptions.md +9 -9
  187. package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
  188. package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
  189. package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
  190. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
  191. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +9 -9
  192. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  193. package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
  194. package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
  195. package/docs/api/interfaces/UserEventAccess.md +11 -11
  196. package/docs/api/interfaces/UserMenuProps.md +1 -1
  197. package/docs/api/interfaces/UserProfile.md +1 -1
  198. package/docs/api/modules.md +591 -220
  199. package/docs/api-reference/components.md +106 -26
  200. package/docs/architecture/README.md +0 -3
  201. package/docs/implementation-guides/data-tables.md +277 -13
  202. package/docs/implementation-guides/forms.md +1 -16
  203. package/docs/implementation-guides/permission-enforcement.md +8 -2
  204. package/docs/styles/README.md +0 -2
  205. package/examples/README.md +30 -14
  206. package/examples/STRUCTURE.md +125 -0
  207. package/examples/components 2/DataTable/HierarchicalActionsExample.tsx +421 -0
  208. package/examples/components 2/DataTable/HierarchicalExample.tsx +475 -0
  209. package/examples/components 2/DataTable/InitialPageSizeExample.tsx +177 -0
  210. package/examples/components 2/DataTable/PerformanceExample.tsx +506 -0
  211. package/examples/components 2/DataTable/index.ts +13 -0
  212. package/examples/components 2/Dialog/BasicHtmlTest.tsx +55 -0
  213. package/examples/components 2/Dialog/DebugHtmlExample.tsx +68 -0
  214. package/examples/components 2/Dialog/HtmlDialogExample.tsx +202 -0
  215. package/examples/components 2/Dialog/ScrollableDialogExample.tsx +290 -0
  216. package/examples/components 2/Dialog/SimpleHtmlTest.tsx +61 -0
  217. package/examples/components 2/Dialog/SmartDialogExample.tsx +322 -0
  218. package/examples/components 2/Dialog/index.ts +15 -0
  219. package/examples/components 2/index.ts +11 -0
  220. package/examples/features/index.ts +12 -0
  221. package/{src/examples → examples/features/public-pages}/CorrectPublicPageImplementation.tsx +14 -17
  222. package/{src/examples → examples/features/public-pages}/PublicEventPage.tsx +14 -27
  223. package/{src/examples → examples/features/public-pages}/PublicPageApp.tsx +15 -28
  224. package/{src/examples → examples/features/public-pages}/PublicPageUsageExample.tsx +8 -10
  225. package/examples/features/public-pages/index.ts +14 -0
  226. package/examples/features/rbac/CompleteRBACExample.tsx +324 -0
  227. package/examples/features/rbac/EventBasedApp.tsx +239 -0
  228. package/examples/features/rbac/PermissionExample.tsx +151 -0
  229. package/examples/features/rbac/index.ts +13 -0
  230. package/examples/index.ts +11 -3
  231. package/package.json +30 -19
  232. package/src/__tests__/TEST_STANDARD.md +92 -0
  233. package/src/components/Alert/Alert.tsx +1 -1
  234. package/src/components/Avatar/Avatar.tsx +1 -1
  235. package/src/components/Badge/Badge.test.tsx +314 -0
  236. package/src/components/Badge/Badge.tsx +304 -0
  237. package/src/components/Badge/index.ts +3 -0
  238. package/src/components/Button/Button.tsx +1 -1
  239. package/src/components/Card/Card.tsx +1 -1
  240. package/src/components/Checkbox/Checkbox.tsx +1 -1
  241. package/src/components/DataTable/DataTable.test.tsx +1 -1
  242. package/src/components/DataTable/DataTable.tsx +1 -30
  243. package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +562 -0
  244. package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +217 -0
  245. package/src/components/DataTable/__tests__/styles.test.ts +3 -3
  246. package/src/components/DataTable/components/ActionButtons.tsx +0 -15
  247. package/src/components/DataTable/components/ColumnFilter.tsx +8 -4
  248. package/src/components/DataTable/components/DataTableBody.tsx +461 -0
  249. package/src/components/DataTable/components/DataTableCore.tsx +4 -185
  250. package/src/components/DataTable/components/DataTableErrorBoundary.tsx +1 -1
  251. package/src/components/DataTable/components/DataTableModals.tsx +1 -27
  252. package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
  253. package/src/components/DataTable/components/EditableRow.tsx +1 -1
  254. package/src/components/DataTable/components/FilterRow.tsx +9 -3
  255. package/src/components/DataTable/components/ImportModal.tsx +2 -14
  256. package/src/components/DataTable/components/PaginationControls.tsx +2 -1
  257. package/src/components/DataTable/components/UnifiedTableBody.tsx +109 -82
  258. package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
  259. package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +14 -68
  260. package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +1 -1
  261. package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +62 -0
  262. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +1 -1
  263. package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +1 -1
  264. package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +43 -0
  265. package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +1 -1
  266. package/src/components/DataTable/core/ActionManager.ts +235 -0
  267. package/src/components/DataTable/core/ColumnManager.ts +205 -0
  268. package/src/components/DataTable/core/DataManager.ts +188 -0
  269. package/src/components/DataTable/core/DataTableContext.tsx +181 -0
  270. package/src/components/DataTable/core/LocalDataAdapter.ts +273 -0
  271. package/src/components/DataTable/core/PluginRegistry.ts +229 -0
  272. package/src/components/DataTable/core/StateManager.ts +311 -0
  273. package/src/components/DataTable/core/interfaces.ts +338 -0
  274. package/src/components/DataTable/examples/GroupingAggregationExample.tsx +273 -0
  275. package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +1 -1
  276. package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +1 -1
  277. package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +1 -1
  278. package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +1 -1
  279. package/src/components/DataTable/hooks/useDataTablePermissions.ts +2 -23
  280. package/src/components/DataTable/index.ts +4 -0
  281. package/src/components/DataTable/styles.ts +28 -7
  282. package/src/components/DataTable/types.ts +13 -0
  283. package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +94 -0
  284. package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +1 -1
  285. package/src/components/DataTable/utils/aggregationUtils.ts +161 -0
  286. package/src/components/DataTable/utils/columnUtils.ts +40 -0
  287. package/src/components/DataTable/utils/debugTools.ts +609 -0
  288. package/src/components/DataTable/utils/exportUtils.ts +1 -1
  289. package/src/components/DataTable/utils/flexibleImport.ts +1 -11
  290. package/src/components/DataTable/utils/index.ts +2 -0
  291. package/src/components/DataTable/utils/paginationUtils.ts +1 -1
  292. package/src/components/Dialog/Dialog.tsx +2 -2
  293. package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +8 -1
  294. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +35 -7
  295. package/src/components/ErrorBoundary/ErrorBoundary.tsx +5 -4
  296. package/src/components/EventSelector/EventSelector.tsx +3 -2
  297. package/src/components/FileDisplay/FileDisplay.tsx +2 -36
  298. package/src/components/FileUpload/FileUpload.test.tsx +2 -2
  299. package/src/components/FileUpload/FileUpload.tsx +2 -2
  300. package/src/components/Footer/Footer.test.tsx +1 -1
  301. package/src/components/Footer/Footer.tsx +1 -1
  302. package/src/components/Form/Form.test.tsx +5 -510
  303. package/src/components/Form/Form.tsx +1 -1
  304. package/src/components/Form/FormField.tsx +1 -1
  305. package/src/components/Form/index.ts +0 -12
  306. package/src/components/Header/Header.tsx +1 -1
  307. package/src/components/Input/Input.tsx +1 -1
  308. package/src/components/Label/Label.tsx +1 -1
  309. package/src/components/LoginForm/LoginForm.test.tsx +1 -1
  310. package/src/components/LoginForm/LoginForm.tsx +1 -1
  311. package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -3
  312. package/src/components/NavigationMenu/NavigationMenu.tsx +9 -8
  313. package/src/components/OrganisationSelector/OrganisationSelector.tsx +4 -3
  314. package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -12
  315. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +0 -16
  316. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +76 -10
  317. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +0 -1
  318. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -9
  319. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +35 -3
  320. package/src/components/PaceLoginPage/PaceLoginPage.tsx +14 -13
  321. package/src/components/PasswordReset/PasswordChangeForm.tsx +1 -1
  322. package/src/components/PasswordReset/index.ts +0 -2
  323. package/src/components/Progress/Progress.tsx +1 -1
  324. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +35 -8
  325. package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -2
  326. package/src/components/PublicLayout/PublicErrorBoundary.tsx +1 -1
  327. package/src/components/PublicLayout/PublicLoadingSpinner.tsx +1 -1
  328. package/src/components/PublicLayout/PublicPageContextChecker.tsx +44 -43
  329. package/src/components/PublicLayout/PublicPageFooter.tsx +1 -1
  330. package/src/components/PublicLayout/PublicPageHeader.tsx +1 -15
  331. package/src/components/PublicLayout/PublicPageProvider.tsx +3 -2
  332. package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +2 -0
  333. package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +1 -1
  334. package/src/components/PublicLayout/index.ts +4 -2
  335. package/src/components/Select/Select.test.tsx +1 -1
  336. package/src/components/Select/Select.tsx +21 -9
  337. package/src/components/{SessionRestorationLoader.tsx → SessionRestorationLoader/SessionRestorationLoader.tsx} +3 -2
  338. package/src/components/SessionRestorationLoader/index.ts +3 -0
  339. package/src/components/Switch/Switch.tsx +1 -1
  340. package/src/components/Table/Table.tsx +1 -1
  341. package/src/components/Table/__tests__/Table.test.tsx +1 -1
  342. package/src/components/Toast/Toast.tsx +1 -1
  343. package/src/components/Tooltip/Tooltip.tsx +1 -1
  344. package/src/components/index.ts +7 -10
  345. package/src/hooks/__tests__/hooks.integration.test.tsx +37 -22
  346. package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +33 -17
  347. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +28 -3
  348. package/src/hooks/__tests__/useFileDisplay.unit.test.ts +36 -9
  349. package/src/hooks/__tests__/useFileUrl.unit.test.ts +83 -85
  350. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +26 -2
  351. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +19 -6
  352. package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -4
  353. package/src/hooks/__tests__/usePermissionCache.unit.test.ts +17 -4
  354. package/src/hooks/__tests__/usePublicEvent.simple.test.ts +26 -6
  355. package/src/hooks/__tests__/usePublicFileDisplay.test.ts +16 -6
  356. package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +3 -3
  357. package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +17 -3
  358. package/src/hooks/public/usePublicEvent.ts +7 -6
  359. package/src/hooks/public/usePublicEventLogo.ts +7 -4
  360. package/src/hooks/public/usePublicFileDisplay.ts +6 -150
  361. package/src/hooks/useComponentPerformance.ts +4 -1
  362. package/src/hooks/useDataTablePerformance.ts +4 -3
  363. package/src/hooks/useEventTheme.test.ts +18 -5
  364. package/src/hooks/useEventTheme.ts +4 -1
  365. package/src/hooks/useEvents.ts +2 -0
  366. package/src/hooks/useFileDisplay.ts +9 -8
  367. package/src/hooks/useFileReference.ts +4 -1
  368. package/src/hooks/useFileUrl.ts +4 -1
  369. package/src/hooks/useInactivityTracker.ts +5 -4
  370. package/src/hooks/useOrganisationSecurity.test.ts +33 -12
  371. package/src/hooks/useOrganisationSecurity.ts +8 -7
  372. package/src/hooks/usePerformanceMonitor.ts +6 -3
  373. package/src/hooks/usePermissionCache.ts +13 -6
  374. package/src/hooks/useSecureDataAccess.test.ts +2 -2
  375. package/src/hooks/useSecureDataAccess.ts +9 -8
  376. package/src/hooks/useSessionRestoration.ts +4 -1
  377. package/src/hooks/useStorage.ts +4 -1
  378. package/src/index.ts +20 -7
  379. package/src/providers/services/AuthServiceProvider.tsx +3 -2
  380. package/src/providers/services/EventServiceProvider.tsx +2 -1
  381. package/src/providers/services/InactivityServiceProvider.tsx +2 -1
  382. package/src/providers/services/OrganisationServiceProvider.tsx +2 -1
  383. package/src/providers/services/UnifiedAuthProvider.tsx +4 -3
  384. package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +22 -2
  385. package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +24 -2
  386. package/src/rbac/__tests__/cache-invalidation.test.ts +20 -6
  387. package/src/rbac/api.ts +5 -2
  388. package/src/rbac/audit-enhanced.ts +6 -6
  389. package/src/rbac/audit.test.ts +60 -38
  390. package/src/rbac/audit.ts +8 -8
  391. package/src/rbac/cache-invalidation.ts +7 -4
  392. package/src/rbac/components/EnhancedNavigationMenu.tsx +11 -5
  393. package/src/rbac/components/NavigationGuard.tsx +7 -3
  394. package/src/rbac/components/NavigationProvider.tsx +6 -3
  395. package/src/rbac/components/PagePermissionGuard.tsx +28 -16
  396. package/src/rbac/components/PagePermissionProvider.tsx +4 -1
  397. package/src/rbac/components/PermissionEnforcer.tsx +9 -3
  398. package/src/rbac/components/RoleBasedRouter.tsx +3 -1
  399. package/src/rbac/components/SecureDataProvider.tsx +7 -3
  400. package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +87 -61
  401. package/src/rbac/components/__tests__/NavigationGuard.test.tsx +83 -33
  402. package/src/rbac/components/__tests__/NavigationProvider.test.tsx +36 -13
  403. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +2 -2
  404. package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +22 -8
  405. package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +19 -6
  406. package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +43 -17
  407. package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +42 -17
  408. package/src/rbac/engine.ts +15 -7
  409. package/src/rbac/hooks/usePermissions.ts +7 -3
  410. package/src/rbac/hooks/useResolvedScope.test.ts +2 -2
  411. package/src/rbac/hooks/useResolvedScope.ts +10 -7
  412. package/src/rbac/permissions.ts +5 -2
  413. package/src/rbac/security.test.ts +27 -16
  414. package/src/rbac/security.ts +5 -4
  415. package/src/services/AuthService.ts +22 -21
  416. package/src/services/EventService.ts +12 -12
  417. package/src/services/InactivityService.ts +5 -4
  418. package/src/services/OrganisationService.ts +26 -25
  419. package/src/services/__tests__/AuthService.test.ts +51 -19
  420. package/src/services/__tests__/EventService.test.ts +37 -5
  421. package/src/services/__tests__/InactivityService.test.ts +38 -4
  422. package/src/services/__tests__/OrganisationService.test.ts +3 -8
  423. package/src/services/base/BaseService.ts +3 -1
  424. package/src/styles/core.css +3 -0
  425. package/src/theming/__tests__/runtime.test.ts +21 -12
  426. package/src/theming/parseEventColours.ts +5 -19
  427. package/src/theming/runtime.ts +8 -4
  428. package/src/types/validation.ts +2 -29
  429. package/src/utils/__tests__/appConfig.unit.test.ts +1 -1
  430. package/src/utils/__tests__/audit.unit.test.ts +1 -1
  431. package/src/utils/__tests__/auth-utils.unit.test.ts +1 -1
  432. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +19 -19
  433. package/src/utils/__tests__/cn.unit.test.ts +1 -1
  434. package/src/utils/__tests__/debugLogger.test.ts +1 -1
  435. package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -1
  436. package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -1
  437. package/src/utils/__tests__/formatting.unit.test.ts +1 -1
  438. package/src/utils/__tests__/lazyLoad.unit.test.tsx +1 -1
  439. package/src/utils/__tests__/logger.unit.test.ts +1 -1
  440. package/src/utils/__tests__/organisationContext.unit.test.ts +1 -1
  441. package/src/utils/__tests__/performanceBenchmark.test.ts +1 -1
  442. package/src/utils/__tests__/performanceBudgets.unit.test.ts +1 -1
  443. package/src/utils/__tests__/permissionTypes.unit.test.ts +1 -1
  444. package/src/utils/__tests__/permissionUtils.unit.test.ts +1 -1
  445. package/src/utils/__tests__/sanitization.unit.test.ts +1 -1
  446. package/src/utils/__tests__/schemaUtils.unit.test.ts +1 -1
  447. package/src/utils/__tests__/secureDataAccess.unit.test.ts +1 -1
  448. package/src/utils/__tests__/secureErrors.unit.test.ts +33 -15
  449. package/src/utils/__tests__/secureStorage.unit.test.ts +1 -1
  450. package/src/utils/__tests__/security.unit.test.ts +40 -18
  451. package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -1
  452. package/src/utils/__tests__/sessionTracking.unit.test.ts +40 -29
  453. package/src/utils/__tests__/validationUtils.unit.test.ts +19 -6
  454. package/src/utils/app/appConfig.ts +47 -0
  455. package/src/utils/app/appIdResolver.test.ts +497 -0
  456. package/src/utils/app/appIdResolver.ts +133 -0
  457. package/src/utils/app/appNameResolver.simple.test.ts +212 -0
  458. package/src/utils/app/appNameResolver.test.ts +121 -0
  459. package/src/utils/app/appNameResolver.ts +195 -0
  460. package/src/utils/audit/audit.ts +127 -0
  461. package/src/utils/context/organisationContext.test.ts +322 -0
  462. package/src/utils/context/organisationContext.ts +156 -0
  463. package/src/utils/context/sessionTracking.ts +125 -0
  464. package/src/utils/core/cn.ts +7 -0
  465. package/src/utils/core/debugLogger.ts +67 -0
  466. package/src/utils/core/logger.ts +181 -0
  467. package/src/utils/device/deviceFingerprint.ts +215 -0
  468. package/src/utils/dynamic/dynamicUtils.ts +105 -0
  469. package/src/utils/dynamic/lazyLoad.tsx +44 -0
  470. package/src/utils/file-reference/__tests__/file-reference.test.ts +788 -0
  471. package/src/utils/file-reference/index.ts +501 -0
  472. package/src/utils/formatting/formatDate.test.ts +237 -0
  473. package/src/utils/formatting/formatting.ts +133 -0
  474. package/src/utils/index.ts +39 -54
  475. package/src/utils/performance/bundleAnalysis.ts +129 -0
  476. package/src/utils/performance/performanceBenchmark.ts +64 -0
  477. package/src/utils/performance/performanceBudgets.ts +110 -0
  478. package/src/utils/permissions/permissionTypes.ts +37 -0
  479. package/src/utils/permissions/permissionUtils.test.ts +393 -0
  480. package/src/utils/permissions/permissionUtils.ts +34 -0
  481. package/src/utils/security/auth-utils.ts +96 -0
  482. package/src/utils/security/secureDataAccess.test.ts +711 -0
  483. package/src/utils/security/secureDataAccess.ts +377 -0
  484. package/src/utils/security/secureErrors.ts +82 -0
  485. package/src/utils/security/secureStorage.ts +244 -0
  486. package/src/utils/security/security.ts +159 -0
  487. package/src/utils/security/securityMonitor.ts +45 -0
  488. package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -4
  489. package/src/utils/storage/helpers.ts +15 -8
  490. package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +598 -0
  491. package/src/{validation → utils/validation}/csrf.ts +1 -1
  492. package/src/utils/validation/htmlSanitization.ts +184 -0
  493. package/src/utils/validation/index.ts +79 -0
  494. package/src/utils/validation/sanitization.ts +333 -0
  495. package/src/{validation/schemaUtils.ts → utils/validation/schema.ts} +11 -6
  496. package/src/{validation → utils/validation}/sqlInjectionProtection.ts +2 -0
  497. package/src/utils/validation/validation.ts +111 -0
  498. package/src/utils/validation/validationUtils.ts +123 -0
  499. package/src/validation/index.ts +3 -34
  500. package/dist/chunk-24MKLB7U.js +0 -81
  501. package/dist/chunk-24MKLB7U.js.map +0 -1
  502. package/dist/chunk-3CG5L6RN.js.map +0 -1
  503. package/dist/chunk-3DBFLLLU.js.map +0 -1
  504. package/dist/chunk-5F3NDPJV.js.map +0 -1
  505. package/dist/chunk-66C4BSAY.js.map +0 -1
  506. package/dist/chunk-BDZUMRBD.js +0 -87
  507. package/dist/chunk-BDZUMRBD.js.map +0 -1
  508. package/dist/chunk-BYXRHAIF.js.map +0 -1
  509. package/dist/chunk-CDQ3PX7L.js +0 -18
  510. package/dist/chunk-CDQ3PX7L.js.map +0 -1
  511. package/dist/chunk-CQZU6TFE.js.map +0 -1
  512. package/dist/chunk-F64FFPOZ.js.map +0 -1
  513. package/dist/chunk-GEVIB2UB.js.map +0 -1
  514. package/dist/chunk-GKHF54DI.js.map +0 -1
  515. package/dist/chunk-GVDR7WNV.js.map +0 -1
  516. package/dist/chunk-HMNOSGVA.js.map +0 -1
  517. package/dist/chunk-JCQZ6LA7.js.map +0 -1
  518. package/dist/chunk-M6DDYFUD.js.map +0 -1
  519. package/dist/chunk-O3NWNXDY.js.map +0 -1
  520. package/dist/chunk-PYUXFQJ3.js.map +0 -1
  521. package/dist/chunk-UJI6WSMD.js.map +0 -1
  522. package/dist/chunk-VZ5OR6HD.js.map +0 -1
  523. package/dist/chunk-WP5I5GLN.js.map +0 -1
  524. package/dist/chunk-ZYZCRSBD.js.map +0 -1
  525. package/dist/validation-DnhrNMju.d.ts +0 -159
  526. package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +0 -185
  527. package/src/validation/__tests__/common.unit.test.ts +0 -101
  528. package/src/validation/__tests__/csrf.unit.test.ts +0 -365
  529. package/src/validation/__tests__/passwordSchema.unit.test.ts +0 -203
  530. package/src/validation/__tests__/sanitization.unit.test.ts +0 -250
  531. package/src/validation/__tests__/schemaUtils.unit.test.ts +0 -451
  532. package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +0 -462
  533. package/src/validation/__tests__/user.unit.test.ts +0 -440
  534. package/src/validation/sanitization.ts +0 -96
  535. /package/dist/{DataTable-A36PJG6N.js.map → DataTable-6M4L6BI2.js.map} +0 -0
  536. /package/dist/{UnifiedAuthProvider-CQDZRJIS.js.map → UnifiedAuthProvider-XIQQ7LVU.js.map} +0 -0
  537. /package/dist/{api-TNIBJWLM.js.map → api-45XYYO2A.js.map} +0 -0
  538. /package/dist/{audit-T36HM7IM.js.map → audit-64X3VJXB.js.map} +0 -0
  539. /package/dist/{chunk-CTJRBUX2.js.map → chunk-6LAAY47Q.js.map} +0 -0
  540. /package/dist/{chunk-ZV77RZMU.js.map → chunk-INQLMHPF.js.map} +0 -0
  541. /package/dist/{useInactivityTracker-MRUU55XI.js.map → useInactivityTracker-TO6ZOF35.js.map} +0 -0
  542. /package/src/{validation → utils/validation}/common.ts +0 -0
  543. /package/src/{validation → utils/validation}/passwordSchema.ts +0 -0
  544. /package/src/{validation → utils/validation}/user.ts +0 -0
@@ -1,185 +0,0 @@
1
- /**
2
- * @file PublicPageDebugger Component Tests
3
- * @package @jmruthers/pace-core
4
- * @module Components/PublicLayout/__tests__
5
- * @since 1.0.0
6
- *
7
- * Comprehensive tests for the PublicPageDebugger component
8
- */
9
-
10
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
11
- import { render, screen } from '@testing-library/react';
12
- import { PublicPageDebugger } from '../PublicPageDebugger';
13
- import { PublicPageProvider } from '../PublicPageProvider';
14
-
15
- describe('PublicPageDebugger', () => {
16
- const consoleLogSpy = vi.spyOn(console, 'log');
17
- const consoleWarnSpy = vi.spyOn(console, 'warn');
18
-
19
- beforeEach(() => {
20
- vi.clearAllMocks();
21
- consoleLogSpy.mockImplementation(() => {});
22
- consoleWarnSpy.mockImplementation(() => {});
23
- });
24
-
25
- afterEach(() => {
26
- consoleLogSpy.mockRestore();
27
- consoleWarnSpy.mockRestore();
28
- });
29
-
30
- describe('Rendering', () => {
31
- it('renders debugger UI when enabled', () => {
32
- render(
33
- <PublicPageProvider>
34
- <PublicPageDebugger enabled={true} />
35
- </PublicPageProvider>
36
- );
37
-
38
- expect(screen.getByText('Public Page Debugger')).toBeInTheDocument();
39
- expect(screen.getByText('Check console for context analysis')).toBeInTheDocument();
40
- });
41
-
42
- it('does not render when disabled', () => {
43
- render(
44
- <PublicPageProvider>
45
- <PublicPageDebugger enabled={false} />
46
- </PublicPageProvider>
47
- );
48
-
49
- expect(screen.queryByText('Public Page Debugger')).not.toBeInTheDocument();
50
- });
51
-
52
- it('renders with default enabled state', () => {
53
- render(
54
- <PublicPageProvider>
55
- <PublicPageDebugger />
56
- </PublicPageProvider>
57
- );
58
-
59
- expect(screen.getByText('Public Page Debugger')).toBeInTheDocument();
60
- });
61
-
62
- it('renders with custom label', () => {
63
- render(
64
- <PublicPageProvider>
65
- <PublicPageDebugger label="CustomLabel" />
66
- </PublicPageProvider>
67
- );
68
-
69
- expect(screen.getByText('Public Page Debugger')).toBeInTheDocument();
70
- });
71
- });
72
-
73
- describe('Console Logging', () => {
74
- it('renders with debugging enabled', () => {
75
- render(
76
- <PublicPageProvider>
77
- <PublicPageDebugger enabled={true} label="TestLabel" />
78
- </PublicPageProvider>
79
- );
80
-
81
- expect(screen.getByText('Public Page Debugger')).toBeInTheDocument();
82
- });
83
-
84
- it('does not render when disabled', () => {
85
- render(
86
- <PublicPageProvider>
87
- <PublicPageDebugger enabled={false} label="TestLabel" />
88
- </PublicPageProvider>
89
- );
90
-
91
- expect(screen.queryByText('Public Page Debugger')).not.toBeInTheDocument();
92
- });
93
- });
94
-
95
- describe('Context Detection', () => {
96
- it('renders within public page context', () => {
97
- render(
98
- <PublicPageProvider>
99
- <PublicPageDebugger enabled={true} label="TestLabel" />
100
- </PublicPageProvider>
101
- );
102
-
103
- expect(screen.getByText('Public Page Debugger')).toBeInTheDocument();
104
- });
105
- });
106
-
107
- describe('Visual Debugger', () => {
108
- it('displays fixed position debugger', () => {
109
- render(
110
- <PublicPageProvider>
111
- <PublicPageDebugger enabled={true} />
112
- </PublicPageProvider>
113
- );
114
-
115
- // Visual debugger should be rendered
116
- expect(screen.getByText('Public Page Debugger')).toBeInTheDocument();
117
- });
118
-
119
- it('renders debugger with correct text content', () => {
120
- render(
121
- <PublicPageProvider>
122
- <PublicPageDebugger enabled={true} />
123
- </PublicPageProvider>
124
- );
125
-
126
- expect(screen.getByText('Public Page Debugger')).toBeInTheDocument();
127
- expect(screen.getByText('Check console for context analysis')).toBeInTheDocument();
128
- });
129
- });
130
-
131
- describe('Edge Cases', () => {
132
- it('renders without crashing', () => {
133
- render(
134
- <PublicPageProvider>
135
- <PublicPageDebugger enabled={true} />
136
- </PublicPageProvider>
137
- );
138
-
139
- expect(screen.getByText('Public Page Debugger')).toBeInTheDocument();
140
- });
141
-
142
- it('handles multiple instances', () => {
143
- render(
144
- <PublicPageProvider>
145
- <PublicPageDebugger enabled={true} label="FirstDebugger" />
146
- <PublicPageDebugger enabled={true} label="SecondDebugger" />
147
- </PublicPageProvider>
148
- );
149
-
150
- expect(screen.getAllByText('Public Page Debugger')).toHaveLength(2);
151
- });
152
-
153
- it('handles label changes on re-render', () => {
154
- const { rerender } = render(
155
- <PublicPageProvider>
156
- <PublicPageDebugger enabled={true} label="Label1" />
157
- </PublicPageProvider>
158
- );
159
-
160
- expect(screen.getByText('Public Page Debugger')).toBeInTheDocument();
161
-
162
- rerender(
163
- <PublicPageProvider>
164
- <PublicPageDebugger enabled={true} label="Label2" />
165
- </PublicPageProvider>
166
- );
167
-
168
- // Component should still render
169
- expect(screen.getByText('Public Page Debugger')).toBeInTheDocument();
170
- });
171
- });
172
-
173
- describe('Performance', () => {
174
- it('renders quickly without performance issues', () => {
175
- const { container } = render(
176
- <PublicPageProvider>
177
- <PublicPageDebugger enabled={true} label="TestLabel" />
178
- </PublicPageProvider>
179
- );
180
-
181
- expect(container).toBeInTheDocument();
182
- });
183
- });
184
- });
185
-
@@ -1,101 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import {
3
- emailSchema,
4
- nameSchema,
5
- phoneSchema,
6
- urlSchema,
7
- dateSchema
8
- } from '../common';
9
-
10
- describe('Common Validation Schemas', () => {
11
- describe('emailSchema', () => {
12
- it('should validate correct email addresses', () => {
13
- expect(emailSchema.safeParse('test@example.com').success).toBe(true);
14
- expect(emailSchema.safeParse('user.name+tag@domain.co.uk').success).toBe(true);
15
- expect(emailSchema.safeParse('123@domain.org').success).toBe(true);
16
- });
17
-
18
- it('should reject invalid email addresses', () => {
19
- expect(emailSchema.safeParse('invalid-email').success).toBe(false);
20
- expect(emailSchema.safeParse('@domain.com').success).toBe(false);
21
- expect(emailSchema.safeParse('user@').success).toBe(false);
22
- expect(emailSchema.safeParse('').success).toBe(false);
23
- });
24
-
25
- it('should reject emails that are too long', () => {
26
- const longEmail = 'a'.repeat(255) + '@example.com';
27
- expect(emailSchema.safeParse(longEmail).success).toBe(false);
28
- });
29
- });
30
-
31
- describe('nameSchema', () => {
32
- it('should validate correct names', () => {
33
- expect(nameSchema.safeParse('John Doe').success).toBe(true);
34
- expect(nameSchema.safeParse('Mary-Jane').success).toBe(true);
35
- expect(nameSchema.safeParse("O'Connor").success).toBe(true);
36
- });
37
-
38
- it('should reject invalid names', () => {
39
- expect(nameSchema.safeParse('').success).toBe(false);
40
- expect(nameSchema.safeParse('John123').success).toBe(false);
41
- expect(nameSchema.safeParse('John@Doe').success).toBe(false);
42
- });
43
-
44
- it('should reject names that are too long', () => {
45
- const longName = 'A'.repeat(101);
46
- expect(nameSchema.safeParse(longName).success).toBe(false);
47
- });
48
- });
49
-
50
- describe('phoneSchema', () => {
51
- it('should validate correct phone numbers', () => {
52
- expect(phoneSchema.safeParse('+1-555-123-4567').success).toBe(true);
53
- expect(phoneSchema.safeParse('555-123-4567').success).toBe(true);
54
- expect(phoneSchema.safeParse('(555) 123-4567').success).toBe(true);
55
- });
56
-
57
- it('should reject invalid phone numbers', () => {
58
- expect(phoneSchema.safeParse('123').success).toBe(false);
59
- expect(phoneSchema.safeParse('not-a-number').success).toBe(false);
60
- expect(phoneSchema.safeParse('').success).toBe(false);
61
- });
62
-
63
- it('should reject phone numbers that are too short or long', () => {
64
- expect(phoneSchema.safeParse('123').success).toBe(false);
65
- expect(phoneSchema.safeParse('1'.repeat(21)).success).toBe(false);
66
- });
67
- });
68
-
69
- describe('urlSchema', () => {
70
- it('should validate correct URLs', () => {
71
- expect(urlSchema.safeParse('https://example.com').success).toBe(true);
72
- expect(urlSchema.safeParse('http://sub.domain.co.uk/path').success).toBe(true);
73
- expect(urlSchema.safeParse('https://example.com?param=value').success).toBe(true);
74
- });
75
-
76
- it('should reject invalid URLs', () => {
77
- expect(urlSchema.safeParse('not-a-url').success).toBe(false);
78
- expect(urlSchema.safeParse('').success).toBe(false);
79
- });
80
-
81
- it('should reject URLs that are too long', () => {
82
- const longUrl = 'https://example.com/' + 'a'.repeat(2048);
83
- expect(urlSchema.safeParse(longUrl).success).toBe(false);
84
- });
85
- });
86
-
87
- describe('dateSchema', () => {
88
- it('should validate correct dates', () => {
89
- expect(dateSchema.safeParse('2023-12-25').success).toBe(true);
90
- expect(dateSchema.safeParse('2023-01-01').success).toBe(true);
91
- });
92
-
93
- it('should reject invalid dates', () => {
94
- expect(dateSchema.safeParse('invalid-date').success).toBe(false);
95
- expect(dateSchema.safeParse('2023/12/25').success).toBe(false);
96
- expect(dateSchema.safeParse('12/25/2023').success).toBe(false);
97
- expect(dateSchema.safeParse('2023-13-45').success).toBe(false);
98
- expect(dateSchema.safeParse('').success).toBe(false);
99
- });
100
- });
101
- });
@@ -1,365 +0,0 @@
1
- /**
2
- * @file CSRF Protection Unit Tests
3
- * @package @jmruthers/pace-core
4
- * @module Validation/CSRF/Tests
5
- * @since 0.1.0
6
- */
7
-
8
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
9
- import {
10
- generateCSRFToken,
11
- validateCSRFToken,
12
- getCSRFToken,
13
- csrfManager,
14
- CSRFTokenData,
15
- } from '../csrf';
16
-
17
- // Mock crypto for testing
18
- const mockCrypto = {
19
- getRandomValues: vi.fn(),
20
- };
21
-
22
- Object.defineProperty(global, 'crypto', {
23
- value: mockCrypto,
24
- writable: true,
25
- });
26
-
27
- // Mock secure storage
28
- vi.mock('../../utils/secureStorage', () => ({
29
- secureStorage: {
30
- setItem: vi.fn().mockResolvedValue(undefined),
31
- getItem: vi.fn().mockResolvedValue(null),
32
- removeItem: vi.fn().mockResolvedValue(undefined),
33
- },
34
- }));
35
-
36
- describe('CSRF Protection', () => {
37
- const testSessionId = 'test-session-123';
38
- const testSessionId2 = 'test-session-456';
39
-
40
- beforeEach(() => {
41
- vi.clearAllMocks();
42
- mockCrypto.getRandomValues.mockImplementation((array) => {
43
- for (let i = 0; i < array.length; i++) {
44
- array[i] = Math.floor(Math.random() * 256);
45
- }
46
- return array;
47
- });
48
- });
49
-
50
- afterEach(async () => {
51
- // Clear session tokens
52
- await csrfManager.clearSession(testSessionId);
53
- await csrfManager.clearSession(testSessionId2);
54
- });
55
-
56
- describe('generateCSRFToken', () => {
57
- it('should generate a valid CSRF token', async () => {
58
- const token = await generateCSRFToken(testSessionId);
59
-
60
- expect(token).toBeDefined();
61
- expect(typeof token).toBe('string');
62
- expect(token.length).toBe(64); // 32 bytes * 2 hex chars
63
- });
64
-
65
- it('should generate different tokens on subsequent calls', async () => {
66
- const token1 = await generateCSRFToken(testSessionId);
67
- const token2 = await generateCSRFToken(testSessionId);
68
-
69
- expect(token1).not.toBe(token2);
70
- });
71
-
72
- it('should generate tokens for different sessions', async () => {
73
- const token1 = await generateCSRFToken(testSessionId);
74
- const token2 = await generateCSRFToken(testSessionId2);
75
-
76
- expect(token1).not.toBe(token2);
77
- });
78
-
79
- it('should handle crypto.getRandomValues errors', async () => {
80
- mockCrypto.getRandomValues.mockImplementation(() => {
81
- throw new Error('Crypto unavailable');
82
- });
83
-
84
- await expect(generateCSRFToken(testSessionId)).rejects.toThrow('CSRF token generation failed');
85
- });
86
- });
87
-
88
- describe('validateCSRFToken', () => {
89
- it('should validate a valid token for correct session', async () => {
90
- const token = await generateCSRFToken(testSessionId);
91
- const isValid = await validateCSRFToken(token, testSessionId);
92
-
93
- expect(isValid).toBe(true);
94
- });
95
-
96
- it('should reject token for wrong session', async () => {
97
- const token = await generateCSRFToken(testSessionId);
98
- const isValid = await validateCSRFToken(token, testSessionId2);
99
-
100
- expect(isValid).toBe(false);
101
- });
102
-
103
- it('should reject invalid token format', async () => {
104
- const invalidToken = 'invalid-token';
105
- const isValid = await validateCSRFToken(invalidToken, testSessionId);
106
-
107
- expect(isValid).toBe(false);
108
- });
109
-
110
- it('should reject reused tokens (one-time use)', async () => {
111
- const token = await generateCSRFToken(testSessionId);
112
-
113
- // First use should succeed
114
- const firstUse = await validateCSRFToken(token, testSessionId);
115
- expect(firstUse).toBe(true);
116
-
117
- // Second use should fail
118
- const secondUse = await validateCSRFToken(token, testSessionId);
119
- expect(secondUse).toBe(false);
120
- });
121
-
122
- it('should handle empty or null tokens', async () => {
123
- expect(await validateCSRFToken('', testSessionId)).toBe(false);
124
- expect(await validateCSRFToken(null as any, testSessionId)).toBe(false);
125
- expect(await validateCSRFToken(undefined as any, testSessionId)).toBe(false);
126
- });
127
- });
128
-
129
- describe('getCSRFToken', () => {
130
- it('should return existing valid token for session', async () => {
131
- const generatedToken = await generateCSRFToken(testSessionId);
132
- const retrievedToken = await getCSRFToken(testSessionId);
133
-
134
- expect(retrievedToken).toBeDefined();
135
- expect(typeof retrievedToken).toBe('string');
136
- });
137
-
138
- it('should generate new token if none exists', async () => {
139
- const token = await getCSRFToken(testSessionId);
140
-
141
- expect(token).toBeDefined();
142
- expect(typeof token).toBe('string');
143
- expect(token!.length).toBe(64);
144
- });
145
-
146
- it('should return different tokens for different sessions', async () => {
147
- const token1 = await getCSRFToken(testSessionId);
148
- const token2 = await getCSRFToken(testSessionId2);
149
-
150
- expect(token1).not.toBe(token2);
151
- });
152
- });
153
-
154
- describe('csrfManager', () => {
155
- it('should manage multiple sessions', async () => {
156
- const token1 = await csrfManager.generateToken(testSessionId);
157
- const token2 = await csrfManager.generateToken(testSessionId2);
158
-
159
- expect(await csrfManager.validateToken(token1, testSessionId)).toBe(true);
160
- expect(await csrfManager.validateToken(token2, testSessionId2)).toBe(true);
161
-
162
- // Cross-session validation should fail
163
- expect(await csrfManager.validateToken(token1, testSessionId2)).toBe(false);
164
- expect(await csrfManager.validateToken(token2, testSessionId)).toBe(false);
165
- });
166
-
167
- it('should clear session tokens', async () => {
168
- const token = await csrfManager.generateToken(testSessionId);
169
-
170
- // Token should be valid
171
- expect(await csrfManager.validateToken(token, testSessionId)).toBe(true);
172
-
173
- // Clear session
174
- await csrfManager.clearSession(testSessionId);
175
-
176
- // Token should no longer be valid
177
- expect(await csrfManager.validateToken(token, testSessionId)).toBe(false);
178
- });
179
-
180
- it('should handle getCurrentToken for existing session', async () => {
181
- await csrfManager.generateToken(testSessionId);
182
- const currentToken = await csrfManager.getCurrentToken(testSessionId);
183
-
184
- expect(currentToken).toBeDefined();
185
- expect(typeof currentToken).toBe('string');
186
- });
187
-
188
- it('should handle getCurrentToken for new session', async () => {
189
- const currentToken = await csrfManager.getCurrentToken('new-session-789');
190
-
191
- expect(currentToken).toBeDefined();
192
- expect(typeof currentToken).toBe('string');
193
- expect(currentToken!.length).toBe(64);
194
- });
195
- });
196
-
197
- describe('Token Lifecycle and Expiry', () => {
198
- it('should handle token expiry', async () => {
199
- // Mock Date.now to simulate time passage
200
- const originalNow = Date.now;
201
- const mockNow = vi.fn();
202
- Date.now = mockNow;
203
-
204
- try {
205
- const initialTime = 1000000;
206
- mockNow.mockReturnValue(initialTime);
207
-
208
- const token = await generateCSRFToken(testSessionId);
209
-
210
- // Token should be valid immediately
211
- expect(await validateCSRFToken(token, testSessionId)).toBe(true);
212
-
213
- // Regenerate token since it was consumed
214
- const token2 = await generateCSRFToken(testSessionId);
215
-
216
- // Simulate time passage beyond expiry (30 minutes + 1 second)
217
- mockNow.mockReturnValue(initialTime + (30 * 60 * 1000) + 1000);
218
-
219
- // Token should now be expired
220
- expect(await validateCSRFToken(token2, testSessionId)).toBe(false);
221
- } finally {
222
- Date.now = originalNow;
223
- }
224
- });
225
- });
226
-
227
- describe('Security Features', () => {
228
- it('should limit tokens per session', async () => {
229
- // Generate maximum tokens for session
230
- const tokens: string[] = [];
231
- for (let i = 0; i < 15; i++) { // More than MAX_TOKENS_PER_SESSION (10)
232
- const token = await generateCSRFToken(testSessionId);
233
- tokens.push(token);
234
- }
235
-
236
- expect(tokens.length).toBe(15);
237
- expect(new Set(tokens).size).toBe(15); // All should be unique
238
- });
239
-
240
- it('should use cryptographically secure random values', async () => {
241
- const calledValues: Uint8Array[] = [];
242
- mockCrypto.getRandomValues.mockImplementation((array) => {
243
- calledValues.push(new Uint8Array(array));
244
- for (let i = 0; i < array.length; i++) {
245
- array[i] = i % 256; // Deterministic but different values
246
- }
247
- return array;
248
- });
249
-
250
- await generateCSRFToken(testSessionId);
251
-
252
- expect(mockCrypto.getRandomValues).toHaveBeenCalledTimes(1);
253
- expect(calledValues[0].length).toBe(32); // 32 bytes
254
- });
255
- });
256
-
257
- describe('Error Handling', () => {
258
- it('should handle storage failures gracefully', async () => {
259
- // Mock storage to fail
260
- const { secureStorage } = await import('../../utils/secureStorage');
261
- vi.mocked(secureStorage.setItem).mockRejectedValue(new Error('Storage failed'));
262
-
263
- // Should still generate token despite storage failure
264
- const token = await generateCSRFToken(testSessionId);
265
- expect(token).toBeDefined();
266
- });
267
-
268
- it('should handle storage retrieval failures', async () => {
269
- const { secureStorage } = await import('../../utils/secureStorage');
270
- vi.mocked(secureStorage.getItem).mockRejectedValue(new Error('Retrieval failed'));
271
-
272
- // Should still work by creating new tokens
273
- const token = await getCSRFToken(testSessionId);
274
- expect(token).toBeDefined();
275
- });
276
-
277
- it('should handle malformed stored data', async () => {
278
- const { secureStorage } = await import('../../utils/secureStorage');
279
- vi.mocked(secureStorage.getItem).mockResolvedValue('invalid-json');
280
-
281
- // Should clear cache and continue working
282
- const token = await getCSRFToken(testSessionId);
283
- expect(token).toBeDefined();
284
- });
285
- });
286
-
287
- describe('Type Safety', () => {
288
- it('should have correct CSRFTokenData interface', () => {
289
- const tokenData: CSRFTokenData = {
290
- token: 'test-token',
291
- sessionId: 'test-session',
292
- timestamp: Date.now(),
293
- used: false,
294
- };
295
-
296
- expect(tokenData.token).toBe('test-token');
297
- expect(tokenData.sessionId).toBe('test-session');
298
- expect(typeof tokenData.timestamp).toBe('number');
299
- expect(typeof tokenData.used).toBe('boolean');
300
- });
301
- });
302
-
303
- describe('Edge Cases', () => {
304
- it('should handle very long session IDs', async () => {
305
- const longSessionId = 'a'.repeat(500);
306
- const token = await generateCSRFToken(longSessionId);
307
-
308
- expect(token).toBeDefined();
309
- expect(token.length).toBe(64);
310
-
311
- // Should be valid for that session
312
- const isValid = await validateCSRFToken(token, longSessionId);
313
- expect(isValid).toBe(true);
314
- });
315
-
316
- it('should handle rapid token generation', async () => {
317
- const tokens = await Promise.all(
318
- Array.from({ length: 20 }, () => generateCSRFToken(testSessionId))
319
- );
320
-
321
- expect(tokens).toHaveLength(20);
322
- // All should be unique 32-byte tokens
323
- const uniqueTokens = new Set(tokens);
324
- expect(uniqueTokens.size).toBe(20);
325
-
326
- // Last token should be valid
327
- const lastToken = tokens[tokens.length - 1];
328
- expect(await validateCSRFToken(lastToken, testSessionId)).toBe(true);
329
- });
330
-
331
- it('should handle storage corruption by clearing cache', async () => {
332
- const { secureStorage } = await import('../../utils/secureStorage');
333
-
334
- // Simulate malformed storage data
335
- vi.mocked(secureStorage.getItem).mockResolvedValueOnce('{{invalid json}');
336
-
337
- // Should handle gracefully and generate new token
338
- const token = await getCSRFToken(testSessionId);
339
- expect(token).toBeDefined();
340
- expect(typeof token).toBe('string');
341
- });
342
-
343
- it('should handle concurrent token generation safely', async () => {
344
- const promises = Array.from({ length: 10 }, (_, i) =>
345
- generateCSRFToken(`session-${i}`)
346
- );
347
-
348
- const tokens = await Promise.all(promises);
349
-
350
- expect(tokens).toHaveLength(10);
351
- expect(new Set(tokens).size).toBe(10);
352
- });
353
-
354
- it('should handle session ID collision edge cases', async () => {
355
- const sameSession = 'collision-session';
356
-
357
- const token1 = await generateCSRFToken(sameSession);
358
- const token2 = await generateCSRFToken(sameSession);
359
-
360
- // Both should be valid for same session
361
- expect(await validateCSRFToken(token1, sameSession)).toBe(true);
362
- expect(await validateCSRFToken(token2, sameSession)).toBe(true);
363
- });
364
- });
365
- });